简体   繁体   中英

Ruby on Rails - Update Parent Field upon Child Creation

I have a two models, Submission (the parent) and SubmissionDetail (the child). Submission has a field called status , which can either be Incomplete, Pending, Approved, or Disapproved. When you create a new Submission , status is automatically set to Incomplete. The child has a foreign key of :submission_id .

What I would like to happen is when a new SubmissionDetail is created, its parent's status will automatically be changed to "Pending." Not sure how to go about this. For example, I've read a little about touch in the model, but I don't think that applies here.

You can probably make use of ActiveRecord's callbacks to update the parent whenever a new child is created.

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

The after_create callback will be run after the child record is created.

You can certainly handle this by hooking create , but then you're not hooking update and certain actions won't propagate back to Submission . You're also littering your persistence layer with business logic and coupling models.

My preference, avoiding the creation of service objects, would be to use 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

This keeps the logic out of SubmissionDetail and keeps Submission responsible for keeping its own status up to date.

Note that if you end up having to manipulate status based on flow and conditions like this a lot, you really want to look into integrating a state machine.

Touch just updates the updated_at column to the current time. You can just add an after_create hook:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM