我有两个相关的类:
class Purchase < ActiveRecord::Base
has_many :actions
before_create do |p|
self.actions.build
end
end
class Action < ActiveRecord::Base
belongs_to :purchase
before_save do |a|
false
end
end
Action
类中的块阻止它保存。我在想Purchase.create
会失败,因为它无法保存子对象。但是虽然它没有保存Action
,但它会提交Purchase
。当子对象出错时,如何防止保存父对象?
答案 0 :(得分:0)
尝试在Purchase
class:
validate :all_children_are_valid
def all_children_are_valid
self.actions.each do |action|
unless action.valid?
self.errors.add(:actions, "aren't valid")
break
end
end
end
或在validates_associated
课程中使用Purchase
:
validates_associated :actions
答案 1 :(得分:0)
如果您的商业逻辑中没有任何操作就无法保存购买,那么请在购买内的操作中添加状态验证工具
validates :actions, length: {minimum: 1}, presence: true
答案 2 :(得分:0)
事实证明,您必须显式回滚事务,子对象的错误不会传播。所以我最终得到了:
class Purchase < ActiveRecord::Base
has_many :actions
after_create do |p|
a = Action.new(purchase: p)
if !a.save
raise ActiveRecord::Rollback
end
end
end
class Action < ActiveRecord::Base
belongs_to :purchase
before_save do |a|
false
end
end
请注意,我还将before_create
回调更改为after_create
。否则,由于belongs_to
也会导致保存父级,因此您将获得SystemStackError: stack level too deep.
答案 3 :(得分:0)
我在处理竞争条件时遇到了这个问题,子对象将通过唯一性验证,但随后数据库约束失败(尝试保存父对象时),导致数据库中无子(无效)父对象
对@lunr建议的解决方案的一般性解决方案:
class Purchase < ActiveRecord::Base
has_many :actions
after_save do
actions.each do |action|
raise ActiveRecord::Rollback unless action.save
end
end
end
class Action < ActiveRecord::Base
belongs_to :purchase
before_save do |a|
false
end
end