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.