トップ «前の日記(2012/04/17 (火) ) 最新 次の日記(2012/04/19 (木) )» 編集 RSS feed

HsbtDiary


2012/04/18 (水) [長年日記]

[MongoDB][Mongoid] Mongoid::Document で initialize を overwride したらはまった話

今のプロジェクトで使っている 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 の挙動が変わっているとは思わなかったよ…ばたり。