5

Rails 3.0.11 から 3.1.3 に移行してから、奇妙なエラーが表示されます。エラーを再現するためのスタンドアロン コードを次に示します。

require 'active_record'

ActiveRecord::Base.establish_connection(
  :adapter  => 'mysql2',
  :username => 'root',
  :database => "some_development"
)

class User < ActiveRecord::Base
  has_many :favorites
end

class Favorite < ActiveRecord::Base
  belongs_to :user
end

u = User.create

# f = u.favorites.find_or_create_by_site_id(123)      #=> pass
f = u.favorites.find_or_initialize_by_site_id(123)    #=> fail
f.some_attr = 'foo'
f.save!

u.name = 'bar'
u.save!                # ActiveRecord::RecordNotUnique will be thrown here!

テーブルに対して同じレコードをActiveRecord::RecordNotUnique試行することになります。(この例では、(user_id, site_id) ペアはお気に入りで一意である必要があることに注意してください)INSERTfavorites

興味深いことに、find_or_create代わりに使用するとfind_or_initialize、例外は発生しません。

スタック トレースで、呼び出されることに気付きましたautosave_associationが、理由はわかりませんが、実際has_many :favorites, :autosave => falseには代わりにhas_many :favoritesエラーも削除されます。私は気にしたことがないので、良いアイデアかautosaveどうかさえわかりません。:autosave => false

何が間違っているのでしょうか、それとも Rails のバグですか? 誰かが私に見るためのポインタを与えることができますか?

4

1 に答える 1

5

電話をかけないようにしましたf.save!か?u.save!お気に入りとユーザーの両方を保存する必要があります。

> f = u.favorites.find_or_initialize_by_site_id(123)

> u.favorites.include?(f)
==> false

> f2 = u.favorites.build(:site_id => 123)

> u.favorites.include?(f2)
==> true

fあなたが見つけたのは、あなたが作成した新しいお気に入りが別のオブジェクトであるということだと思います. したがって、 f を保存しますが、 にも保存されていない別のお気に入りがありu.favouritesます。したがって、u を保存すると、固有ではないエラーが発生します (お気に入りも保存されます)。

これが Rails 3.1 で新たに導入されたバグかどうかはわかりません。意図的なものかもしれません。

Rails 3.0 では、find_or_initialize_by は配列にデータを入力しませんでした

> f = u.favorites.find_or_initialize_by_site_id(123)

> u.favorites
==> []

バグのようです - https://github.com/rails/rails/pull/3610を参照してください

于 2012-01-10T04:46:58.973 に答える