diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 68a386f8db..07dfc448e7 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1577,6 +1577,8 @@ module ActiveRecord scope = nil end + habtm_reflection = ActiveRecord::Reflection::AssociationReflection.new(:has_and_belongs_to_many, name, scope, options, self) + builder = Builder::HasAndBelongsToMany.new name, self, options join_model = builder.through_model @@ -1590,6 +1592,7 @@ module ActiveRecord Builder::HasMany.define_callbacks self, middle_reflection Reflection.add_reflection self, middle_reflection.name, middle_reflection + middle_reflection.parent_reflection = [name.to_s, habtm_reflection] include Module.new { class_eval <<-RUBY, __FILE__, __LINE__ + 1 @@ -1610,9 +1613,7 @@ module ActiveRecord end has_many name, scope, hm_options, &extension - - reflection = ActiveRecord::Reflection::AssociationReflection.new(:has_and_belongs_to_many, name, scope, options, self) - self.reflections = self.reflections.except(middle_reflection.name).merge!(name.to_s => reflection) + self._reflections[name.to_s].parent_reflection = [name.to_s, habtm_reflection] end end end diff --git a/activerecord/lib/active_record/counter_cache.rb b/activerecord/lib/active_record/counter_cache.rb index 874a7c2f2d..05c4b13016 100644 --- a/activerecord/lib/active_record/counter_cache.rb +++ b/activerecord/lib/active_record/counter_cache.rb @@ -166,7 +166,7 @@ module ActiveRecord end def each_counter_cached_associations - reflections.each do |name, reflection| + _reflections.each do |name, reflection| yield association(name) if reflection.belongs_to? && reflection.counter_cache_column end end diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index dc9a20fec3..7dc7169a02 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -307,7 +307,6 @@ module ActiveRecord attr_names.each do |association_name| if reflection = _reflect_on_association(association_name) reflection.autosave = true - reflect_on_association(association_name).autosave = true add_autosave_association_callbacks(reflection) nested_attributes_options = self.nested_attributes_options.dup diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index e24ad54be3..dd80ec6274 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -7,11 +7,8 @@ module ActiveRecord included do class_attribute :_reflections - # @api public - class_attribute :reflections class_attribute :aggregate_reflections self._reflections = {} - self.reflections = {} self.aggregate_reflections = {} end @@ -28,7 +25,6 @@ module ActiveRecord def self.add_reflection(ar, name, reflection) ar._reflections = ar._reflections.merge(name.to_s => reflection) - ar.reflections = ar.reflections.merge(name.to_s => reflection) end def self.add_aggregate_reflection(ar, name, reflection) @@ -57,6 +53,24 @@ module ActiveRecord aggregate_reflections[aggregation.to_s] end + # Returns a Hash of name of the reflection as the key and a AssociationReflection as the value. + # + # Account.reflections # => {balance: AggregateReflection} + # + # @api public + def reflections + ref = {} + _reflections.each do |name, reflection| + parent_name, parent_reflection = reflection.parent_reflection + if parent_name + ref[parent_name] = parent_reflection + else + ref[name] = reflection + end + end + ref + end + # Returns an array of AssociationReflection objects for all the # associations in the class. If you only want to reflect on a certain # association type, pass in the symbol (:has_many, :has_one, @@ -142,6 +156,10 @@ module ActiveRecord def autosave=(autosave) @automatic_inverse_of = false @options[:autosave] = autosave + _, parent_reflection = self.parent_reflection + if parent_reflection + parent_reflection.autosave = autosave + end end # Returns the class for the macro. @@ -206,6 +224,7 @@ module ActiveRecord end attr_reader :type, :foreign_type + attr_accessor :parent_reflection # [:name, Reflection] def initialize(macro, name, scope, options, active_record) super