This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the rails category.
Last Updated: 2024-11-23
A LawCase
had and belonged to many LawDiscipline
s and vice-versa.
I wanted to touch
(bump timestamp of) the law_discipline
whenever a law_case
was added to that discipline.
My first draft was:
class LawCase
has_and_belongs_to_many :law_disciplines
after_commit :touch_associated_records
private
def touch_associated_records
# n < 3, therefore optimizations were overkill
law_disciplines.each(&:touch)
end
end
The current code correctly touched the association when an attribute of a
LawCase
was modified. But this did not touch the associated records when you
added or removed a record from the association, e.g. as follows
law_case.law_disciplines << law_discipline
# or (not sure syntax is correct...but you get the idea)
law_case.law_disciplines.delete(law_discipline)
This is because these actions just interact with the has_and_belongs_to_many
association.
The solution involved adding after_add
and after_remove
callbacks:
has_and_belongs_to_many :law_disciplines,
after_add: :touch_updated_at,
after_remove: :touch_updated_at
# This always get a parameter
def touch_updated_at(law_discipline)
law_discipline.touch
end