自从我从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
尝试INSERT
同一记录到favorites
表。 (请注意,对于此示例,(user_id,site_id)对在收藏夹中必须是唯一的)
有趣的是,如果我使用find_or_create
代替find_or_initialize
,则不会引发异常。
在堆栈跟踪中,我注意到autosave_association
被调用,不知道为什么,但实际上has_many :favorites, :autosave => false
而不是has_many :favorites
也会删除错误。由于我从不关心autosave
,我甚至不确定:autosave => false
是否是个好主意。
我做错了什么,还是Rails错误?任何人都可以给我一个指针来看看吗?
答案 0 :(得分: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