I needed to implement a validation rule on an object which has a has_many relationship to another object. I needed to check whether the collection itself had been changed, rather than associated objects within the collection i.e. were objects added to or removed from the collection?
This was, surprisingly, not as obvious as it would seem. I make use of some rather obscure ActiveRecord associated callbacks, specifically the after_add and before_remove callbacks.
When the callbacks are triggered, I set an instance variable which allows me to easily determine if the collection has changed. I can then use this in my validation rule.
Finally, after the object is successfully saved I ensure the validation flag is reset.
class Assembly < ActiveRecord::Base attr_reader :parts_changed after_save :clear_parts_changed has_many :manifests has_many :parts, through: :manifests, after_add: :parts_changed!, before_remove: :parts_changed! validates_with Validator::Assembly private def parts_changed!(_) @parts_changed = true end def clear_encoding_presets_changed @parts_changed = false end end module Validator class Assembly < ActiveModel::Validator def validate(assembly) if assembly.parts_changed # handle the validation failure # ... # ... end end end end