Ruby on rails 为什么Mongoid';s";“在场”;验证是否启用自动保存?
我很难调试这个,我正要寻求帮助。但我已经设法找出了原因,并想与大家分享我的发现,以防其他人遇到同样的问题。[也许有人能解释为什么它会这样工作] 安装程序 假设我有两个Mongoid文档,Ruby on rails 为什么Mongoid';s";“在场”;验证是否启用自动保存?,ruby-on-rails,validation,mongoid,autosave,Ruby On Rails,Validation,Mongoid,Autosave,我很难调试这个,我正要寻求帮助。但我已经设法找出了原因,并想与大家分享我的发现,以防其他人遇到同样的问题。[也许有人能解释为什么它会这样工作] 安装程序 假设我有两个Mongoid文档,Customer和Order,它们之间的关系为1:n。此外,Customer在保存后有一个回调,用于将文档更改与外部API同步: class Customer include Mongoid::Document has_many :orders after_save do puts "sync
Customer
和Order
,它们之间的关系为1:n。此外,Customer
在保存后有一个回调,用于将文档更改与外部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
问题
但是突然之间,事情变得很奇怪。此更改后,创建(或更新)订单也会保存客户!(我注意到这一点是因为我的日志——同步运行没有明显的原因)
它是通过状态验证启用的,事实上,Mongoid随意地指出:
请注意,当使用接受
的嵌套属性或验证关系的存在时,自动保存功能将自动添加到关系中
但是autosave
仅在文档更改时保存文档,那么更改从何而来?显然,我新的带有默认值的premium
字段引入了一个微妙的变化:
c = Customer.first # a customer from before the change without "premium" attribute
c.changed?
#=> true
c.changes
#=> {"premium"=>[nil, false]}
解决方案
毕竟,修复是相当琐碎的。我只需在我的所属关系上显式禁用autosave即可:
class Order
include Mongoid::Document
belongs_to :customer, autosave: false
validates_presence_of :customer
end
开放性问题
但问题依然存在:为什么Mongoid的“存在”验证支持autosave?这怎么可能是期望的默认行为?请告诉我。看来自动保存的自动启用是故意添加到Mongoid 3.0中的,以便其行为与ActiveRecord一致。看看这两个问题:
第二个问题链接到一个似乎确实以同样方式表现的问题,让我们特别引用以下声明:
请注意,autosave:false
与不声明:autosave
不同。当:autosave
选项不存在时,会保存新的关联记录,但不会保存更新的关联记录
下面是Mongoid特性本身的一个例子
此外,从所有这些来源可以看出,您的解决方案是完美的,您确实应该特别声明:autosave=>false
以禁用此功能
Order.relations['customer'].autosave?
#=> true
c = Customer.first # a customer from before the change without "premium" attribute
c.changed?
#=> true
c.changes
#=> {"premium"=>[nil, false]}
class Order
include Mongoid::Document
belongs_to :customer, autosave: false
validates_presence_of :customer
end