Index: associations.rb =================================================================== --- associations.rb (revision 5411) +++ associations.rb (revision 5462) @@ -608,16 +608,16 @@ def has_one(association_id, options = {}) reflection = create_has_one_reflection(association_id, options) - module_eval do - after_save <<-EOF - association = instance_variable_get("@#{reflection.name}") - if !association.nil? && (new_record? || association.new_record? || association["#{reflection.primary_key_name}"] != id) - association["#{reflection.primary_key_name}"] = id - association.save(true) - end - EOF + define_method("has_one_after_save_for_#{reflection.name}") do + association = instance_variable_get("@#{reflection.name}") + if !association.nil? && (new_record? || association.new_record? || association["#{reflection.primary_key_name}"] != id) + association["#{reflection.primary_key_name}"] = id + association.save(true) + end end - + + after_save "has_one_after_save_for_#{reflection.name}".to_sym + association_accessor_methods(reflection, HasOneAssociation) association_constructor_method(:build, reflection, HasOneAssociation) association_constructor_method(:create, reflection, HasOneAssociation) @@ -686,41 +686,40 @@ if reflection.options[:polymorphic] association_accessor_methods(reflection, BelongsToPolymorphicAssociation) - module_eval do - before_save <<-EOF - association = instance_variable_get("@#{reflection.name}") - if association && association.target - if association.new_record? - association.save(true) - end - - if association.updated? - self["#{reflection.primary_key_name}"] = association.id - self["#{reflection.options[:foreign_type]}"] = association.class.base_class.name.to_s - end + define_method("polymorphic_belongs_to_before_save_for_#{reflection.name}") do + association = instance_variable_get("@#{reflection.name}") + if association && association.target + if association.new_record? + association.save(true) end - EOF + + if association.updated? + self["#{reflection.primary_key_name}"] = association.id + self["#{reflection.options[:foreign_type]}"] = association.class.base_class.name.to_s + end + end end + + before_save "polymorphic_belongs_to_before_save_for_#{reflection.name}".to_sym else association_accessor_methods(reflection, BelongsToAssociation) association_constructor_method(:build, reflection, BelongsToAssociation) association_constructor_method(:create, reflection, BelongsToAssociation) - module_eval do - before_save <<-EOF - association = instance_variable_get("@#{reflection.name}") - if !association.nil? - if association.new_record? - association.save(true) - end - - if association.updated? - self["#{reflection.primary_key_name}"] = association.id - end - end - EOF + define_method("belongs_to_before_save_for_#{reflection.name}") do + association = instance_variable_get("@#{reflection.name}") + if !association.nil? + if association.new_record? + association.save(true) + end + + if association.updated? + self["#{reflection.primary_key_name}"] = association.id + end + end end - + before_save "belongs_to_before_save_for_#{reflection.name}".to_sym + # deprecated api deprecated_has_association_method(reflection.name) deprecated_association_comparison_method(reflection.name, reflection.class_name) @@ -731,15 +730,17 @@ "#{self.to_s.underscore.pluralize}_count" : options[:counter_cache] - module_eval( - "after_create '#{reflection.name}.class.increment_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + - " unless #{reflection.name}.nil?'" - ) + define_method("belongs_to_counter_cache_after_create_for_#{reflection.name}") do + association = send(reflection.name) + association.class.increment_counter("#{cache_column}", self.send("#{reflection.primary_key_name}")) unless association.nil? + end + after_create "belongs_to_counter_cache_after_create_for_#{reflection.name}".to_sym - module_eval( - "before_destroy '#{reflection.name}.class.decrement_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + - " unless #{reflection.name}.nil?'" - ) + define_method("belongs_to_counter_cache_before_destroy_for_#{reflection.name}") do + association = send(reflection.name) + association.class.decrement_counter("#{cache_column}", self.send("#{reflection.primary_key_name}")) unless association.nil? + end + before_destroy "belongs_to_counter_cache_before_destroy_for_#{reflection.name}".to_sym end end @@ -969,9 +970,16 @@ end validate method_name - before_save("@new_record_before_save = new_record?; true") - after_callback = <<-end_eval + method_name = "before_save_associated_records_for_#{association_name}".to_sym + define_method(method_name) do + @new_record_before_save = new_record? + true + end + before_save method_name + + method_name = "after_create_or_update_associated_records_for_#{association_name}".to_sym + define_method(method_name) do association = instance_variable_get("@#{association_name}") if association.respond_to?(:loaded?) @@ -983,11 +991,11 @@ records_to_save.each { |record| association.send(:insert_record, record) } association.send(:construct_sql) # reconstruct the SQL queries now that we know the owner's id end - end_eval - + end + # Doesn't use after_save as that would save associations added in after_create/after_update twice - after_create(after_callback) - after_update(after_callback) + after_create method_name + after_update method_name end def association_constructor_method(constructor, reflection, association_proxy_class) @@ -1043,7 +1051,10 @@ case reflection.options[:dependent] when :destroy, true - module_eval "before_destroy '#{reflection.name}.each { |o| o.destroy }'" + define_method("has_many_dependent_destroy_for_#{reflection.name}") do + send(reflection.name).each { |o| o.destroy } + end + before_destroy "has_many_dependent_destroy_for_#{reflection.name}".to_sym when :delete_all module_eval "before_destroy { |record| #{reflection.class_name}.delete_all(%(#{dependent_conditions})) }" when :nullify @@ -1058,11 +1069,23 @@ def configure_dependency_for_has_one(reflection) case reflection.options[:dependent] when :destroy, true - module_eval "before_destroy '#{reflection.name}.destroy unless #{reflection.name}.nil?'" + define_method("has_one_dependent_destroy_for_#{reflection.name}") do + association = send(reflection.name) + association.destroy unless association.nil? + end + before_destroy "has_one_dependent_destroy_for_#{reflection.name}".to_sym when :delete - module_eval "before_destroy '#{reflection.class_name}.delete(#{reflection.name}.id) unless #{reflection.name}.nil?'" + define_method("has_one_dependent_delete_for_#{reflection.name}") do + association = send(reflection.name) + association.class.delete(association.id) unless association.nil? + end + before_destroy "has_one_dependent_delete_for_#{reflection.name}".to_sym when :nullify - module_eval "before_destroy '#{reflection.name}.update_attribute(\"#{reflection.primary_key_name}\", nil) unless #{reflection.name}.nil?'" + define_method("has_one_dependent_nullify_for_#{reflection.name}") do + association = send(reflection.name) + association.update_attribute(reflection.primary_key_name, nil) unless association.nil? + end + before_destroy "has_one_dependent_nullify_for_#{reflection.name}".to_sym when nil, false # pass else