我很难调试这个,我正要求帮忙。但我已设法确定原因,并希望分享我的发现,以防其他人遇到同样的问题。 [也许有人可以解释为什么它按照它的方式工作]
我们说我有两个Mongoid-Documents,Customer
和Order
,关系为1:n。此外,Customer
还有一个after_save
回调,用于将文档更改与外部API同步:
class Customer
include Mongoid::Document
has_many :orders
after_save do
puts "synchronizing customer" # <- not my actual code
end
end
class Order
include Mongoid::Document
belongs_to :customer
validates_presence_of :customer
end
一切都按预期工作。创建和更新客户会导致触发after_save
回调并且不会创建订单。
过了一会儿,Customer
需要一个具有默认值的新字段:
class Customer
# ...
field :premium, type: Boolean, default: false
end
但突然间,事情变得奇怪了。在此更改之后,创建(或更新)订单会导致客户也被保存! (我注意到这是因为我的日志 - 同步运行没有明显的原因)
c = Customer.last
c.orders.create
synchronizing customer # <- what the?
#=> #<Order _id: 575a995aab265d730b8bddba ...>
奇怪的是,这只发生在现有客户身上,而且只发生一次。
漫长而乏味的调试会话显示Order
的{{1}}关系有一个belongs_to
标记:
autosave
它是通过在线验证启用的,事实上,Mongoid的documentation随便注意到它:
请注意,在使用
Order.relations['customer'].autosave? #=> true
或验证关系存在时,自动保存功能会自动添加到关系中。
但是accepts_nested_attributes_for
只保存了一个文件,如果它被更改了,那么这个变化来自哪里?显然,我的新autosave
字段具有默认值,引入了一个微妙的变化:
premium
毕竟,修复工作非常简单。我只需要在我的c = Customer.first # a customer from before the change without "premium" attribute
c.changed?
#=> true
c.changes
#=> {"premium"=>[nil, false]}
关系中明确禁用自动保存:
belongs_to
但问题仍然存在:为什么Mongoid&#34;存在&#34;验证启用自动保存?这怎么可能是理想的默认行为?请赐教。
答案 0 :(得分:2)
似乎自动启用自动保存已故意添加到Mongoid 3.0 ,以便其行为与ActiveRecord 一致。看看这两个问题:
第二个问题链接到ActiveRecord doc,它确实表现得一样,让我们特别引用以下声明:
请注意,
autosave: false
与未声明:autosave
不同。如果:autosave
选项不存在,则会保存新的关联记录,但不会保存更新的关联记录。
这是Mongoid功能本身的link to the source code。
此外,从所有这些来源可以看出,您的解决方案非常完美,您确实应该明确指出:autosave => false
来禁用此功能。