【发布时间】:2012-01-10 04:26:44
【问题描述】:
自从我从 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 错误?谁能给我指点看看?
【问题讨论】:
-
用户模型是否对字段的唯一性进行了验证?另外,旁边带有
#=> pass的注释是什么?您是想同时创建两个版本的收藏夹吗? -
是的,用户模型有很多验证,包括唯一性,但我不确定它是如何关联的。如果您在 find_or_create 行而不是 find_or_initialize 中添加注释,它应该会通过而不会出现错误,如我的问题中所述。
-
你能试试这个吗:不是
u.save!,而是u.save,然后puts u.errors或p u.errors。有什么错误。我有一种感觉,这是一个问题,您正在创建一个没有通过唯一性验证的用户(因为您使用的是通用User.create而没有输入任何属性)。 -
实际上
u.save也引发了同样的异常。也就是说,它无法到达以下puts u.errors。因为它是数据库级别的唯一约束,而不是 ruby 级别的验证。
标签: ruby-on-rails activerecord ruby-on-rails-3.1 associations autosave