Ruby on Rails - 在创建子项时更新父字段

时间:2014-02-25 20:20:28

标签: ruby-on-rails activerecord ruby-on-rails-4

我有两个模型Submission(父母)和SubmissionDetail(孩子)。 Submission有一个名为status的字段,可以是“未完成”,“待审批”,“已批准”或“已拒登”。当您创建新的Submission时,status会自动设置为“未完成”。孩子的外键为:submission_id

我想要的是,当创建新的SubmissionDetail时,其父级的状态将自动更改为“待定”。不知道该怎么做。例如,我在模型中阅读了一些关于touch的内容,但我认为这不适用于此。

3 个答案:

答案 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