我有两个模型Submission
(父母)和SubmissionDetail
(孩子)。 Submission
有一个名为status
的字段,可以是“未完成”,“待审批”,“已批准”或“已拒登”。当您创建新的Submission
时,status
会自动设置为“未完成”。孩子的外键为:submission_id
。
我想要的是,当创建新的SubmissionDetail
时,其父级的状态将自动更改为“待定”。不知道该怎么做。例如,我在模型中阅读了一些关于touch
的内容,但我认为这不适用于此。
答案 0 :(得分:4)
每当创建新子项时,您都可以使用ActiveRecord's callbacks来更新父项。
class Submission < ActiveRecord::Base
has_many :submission_details
end
class SubmissionDetail < ActiveRecord::Base
belongs_to :submission
after_create :set_parent_to_pending
def set_parent_to_pending
# child should always have a parent, but we need to check just in case
submission.update(status: 'pending') unless submission.nil?
end
end
创建子记录后将运行after_create
回调。
答案 1 :(得分:2)
您当然可以通过挂钩create
来处理此问题,但之后您没有挂钩update
,某些操作也不会传播回Submission
。您还在使用业务逻辑和耦合模型乱丢您的持久层。
我的偏好是避免创建服务对象,而是使用after_touch
:
class SubmissionDetail < ActiveRecord::Base
belongs_to :submission, touch: true
end
class Submission < ActiveRecord::Base
has_many :submission_details
after_touch :pending!
protected
def pending!
self.status = 'pending'
save!
end
end
这使逻辑保持在SubmissionDetail
之外,并让Submission
负责保持自己的状态为最新状态。
请注意,如果你最终不得不根据这样的流量和条件来操纵状态,那么你真的想要研究一下状态机的集成。
答案 2 :(得分:1)
触摸只是将updated_at列更新为当前时间。你可以添加一个after_create钩子:
class SubmissionDetail < AR
belongs_to :submission
after_create :set_pending
private
def set_pending
submission.update_attributes(state: "Pending") # or whatever random method
end
end