読者です 読者をやめる 読者になる 読者になる

Rails (OSS) パッチ会#1

勤務先でのRails (OSS) パッチ会#1だった。

自分は、Oracle を使ったアプリケーションコードを Rails 5 にアップグレードするにあたって、モンキーパッチを充てている箇所について調査をしていた。

予め分かっていたこととして、Rails 5 で Rails 4 の頃の (リンク先の) コードが消えていて、そのあたりが Rails 5 へのアップグレードに影響しているようだった。このことにより、String を期待するところ Enumerize::Value が渡されて以下のようなエラーが発生する事象と出会ってた。

サンプルコード。

class Music < ApplicationRecord
  extend Enumerize

  enumerize :genre, in: %i(rock metal)
end

Music.create(genre: :metal)

genre = Music.first.genre # String を継承した Enumerize::Value インスタンスが返る

Music.find_by(genre: genre) # エラーが発生する

エラー内容。

RuntimeError: unsupported datatype: Enumerize::Value: SELECT  "MUSICS".* FROM "MUSICS" WHERE "MUSICS"."GENRE" = :a1 AND ROWNUM <= :a2

ワークアラウンドコードとしては config/initializers/oracle.rb なんかを作って以下のようなコードを書いて回避している。

ActiveSupport.on_load(:active_record) do
  OCI8::BindType::Mapping[Enumerize::Value] = OCI8::BindType::String
end

今回、upstream に手を入れるとしたら AR なのか、Adapter なのか Enumerize なのかといった感じで、開始点としてミニマムケースを作って Oracle 以外の RDBMS でどうかを試したところ、SQLite では同様の問題が起きなかったあたりで時間切れ。

やったことを話した際に得られたフィードバックとして、パッチ以外にアプリケーションコードとして AR::Enum の利用も視野に入れてよさそうというのがあった。Enumerize (Alternative) から AR::Enum (Standard) にするようであれば、以下のあたりを検討材料として加味すると良さそう。

  • Enumerize の場合は default が使える
  • Enumerize の場合は I18n が使える
  • AR::Enum にすると enum genre: { rock: 0, metal: 1 } といった数値になるのでデータパッチは必要

その他、気に留まったいくつかの話題。

すぎのいさんのやっていたことの話から AR::NullRelation まわりの実装話。

github.com

大きくなった Kaminari が解体されはじめた。いずれ kaminari-core なんかもそちらに移って行く予定っぽい。

github.com

Rails の HEAD から jQuery を外した PR が 2日ほど前にマージされてた。

github.com