今のプロジェクトで使っている Mongoid のバージョンを 2.2 系から 2.4 系にバージョンアップという作業をしていたら、以下のような謎の現象にはまってしまった。
% cat app/models/user.rb
class User
include Mongoid::Document
embeds_many :items, inverse_of: :user, class_name: Item::Base.to_s
end
こんな User と
% cat app/models/item.rb
module Item
class Base
include Mongoid::Document
def initialize(*args)
super
p args
end
end
end
こんな Item があったとして以下のように user.items を作ろうとすると…
>> User.create!
=> #<User _id: 4f8e2a1aff2b33e552000001, _type: nil>
>> User.first.items
=> []
>> User.first.items.create({foo: :bar})
[{:foo=>:bar}, {}]
というように謎のハッシュが initialize にわたって来てしまう。上の例は *args としているのでエラーにはならないけど、元のコードは args = {} と引数を一つとして受け取るので ArgumentError を起こして落ちてしまっていた。これは 2.3.0 の 2327c196 で変わった挙動で、initialize の引数を二つ受け取るようになったのが原因らしい。
実はここまでたどり着くのに1日くらいかかっていて、コントローラやら画面の JavaScript から範囲を狭くして、やっと Mongoid のバージョンアップが原因ということにたどりついたんだけど、まさか embeds_many な モデルの initialize の挙動が変わっているとは思わなかったよ…ばたり。