Adds validation and save callbacks for the association as specified by the
reflection.
For performance reasons, we don’t check whether to validate at runtime.
However the validation and callback methods are lazy and those methods get
created when they are invoked for the very first time. However, this can
change, for instance, when using nested attributes, which is called
after the association has been defined. Since we don’t want the
callbacks to get defined multiple times, there are guards that check if the
save or validation methods have already been defined before actually
defining them.
# File activerecord/lib/active_record/autosave_association.rb, line 178
def add_autosave_association_callbacks(reflection)
save_method = :"autosave_associated_records_for_#{reflection.name}"
validation_method = :"validate_associated_records_for_#{reflection.name}"
collection = reflection.collection?
if collection
before_save :before_save_collection_association
define_non_cyclic_method(save_method) { save_collection_association(reflection) }
# Doesn't use after_save as that would save associations added in after_create/after_update twice
after_create save_method
after_update save_method
elsif reflection.macro == :has_one
define_method(save_method) { save_has_one_association(reflection) } unless method_defined?(save_method)
# Configures two callbacks instead of a single after_save so that
# the model may rely on their execution order relative to its
# own callbacks.
#
# For example, given that after_creates run before after_saves, if
# we configured instead an after_save there would be no way to fire
# a custom after_create callback after the child association gets
# created.
after_create save_method
after_update save_method
else
define_non_cyclic_method(save_method) { save_belongs_to_association(reflection) }
before_save save_method
end
if reflection.validate? && !method_defined?(validation_method)
method = (collection ? :validate_collection_association : :validate_single_association)
define_non_cyclic_method(validation_method) { send(method, reflection) }
validate validation_method
end
end