aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r--activerecord/lib/active_record/associations.rb43
-rw-r--r--activerecord/lib/active_record/associations/association_proxy.rb10
-rw-r--r--activerecord/lib/active_record/associations/belongs_to_association.rb8
-rw-r--r--activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb9
-rw-r--r--activerecord/lib/active_record/reflection.rb5
5 files changed, 32 insertions, 43 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index e4dff69efe..c6c41a7a12 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1229,14 +1229,12 @@ module ActiveRecord
if reflection.options[:polymorphic]
association_accessor_methods(reflection, BelongsToPolymorphicAssociation)
- association_foreign_type_setter_method(reflection)
else
association_accessor_methods(reflection, BelongsToAssociation)
association_constructor_method(:build, reflection, BelongsToAssociation)
association_constructor_method(:create, reflection, BelongsToAssociation)
end
- association_foreign_key_setter_method(reflection)
add_counter_cache_callbacks(reflection) if options[:counter_cache]
add_touch_callbacks(reflection, options[:touch]) if options[:touch]
@@ -1456,7 +1454,7 @@ module ActiveRecord
force_reload = params.first unless params.empty?
association = association_instance_get(reflection.name)
- if association.nil? || force_reload
+ if association.nil? || force_reload || association.stale_target?
association = association_proxy_class.new(self, reflection)
retval = force_reload ? reflection.klass.uncached { association.reload } : association.reload
if retval.nil? and association_proxy_class == BelongsToAssociation
@@ -1556,45 +1554,6 @@ module ActiveRecord
end
end
- def association_foreign_key_setter_method(reflection)
- setters = reflect_on_all_associations(:belongs_to).map do |belongs_to_reflection|
- if belongs_to_reflection.primary_key_name == reflection.primary_key_name
- "association_instance_set(:#{belongs_to_reflection.name}, nil);"
- end
- end.compact.join
-
- if method_defined?(:"#{reflection.primary_key_name}=")
- undef_method :"#{reflection.primary_key_name}="
- end
-
- class_eval <<-FILE, __FILE__, __LINE__ + 1
- def #{reflection.primary_key_name}=(new_id)
- write_attribute :#{reflection.primary_key_name}, new_id
- if #{reflection.primary_key_name}_changed?
- #{ setters }
- end
- end
- FILE
- end
-
- def association_foreign_type_setter_method(reflection)
- setters = reflect_on_all_associations(:belongs_to).map do |belongs_to_reflection|
- if belongs_to_reflection.options[:foreign_type] == reflection.options[:foreign_type]
- "association_instance_set(:#{belongs_to_reflection.name}, nil);"
- end
- end.compact.join
-
- field = reflection.options[:foreign_type]
- class_eval <<-FILE, __FILE__, __LINE__ + 1
- def #{field}=(new_id)
- write_attribute :#{field}, new_id
- if #{field}_changed?
- #{ setters }
- end
- end
- FILE
- end
-
def add_counter_cache_callbacks(reflection)
cache_column = reflection.counter_cache_column
diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb
index 252ff7e7ea..f4eceeed8c 100644
--- a/activerecord/lib/active_record/associations/association_proxy.rb
+++ b/activerecord/lib/active_record/associations/association_proxy.rb
@@ -130,6 +130,16 @@ module ActiveRecord
@loaded = true
end
+ # The target is stale if the target no longer points to the record(s) that the
+ # relevant foreign_key(s) refers to. If stale, the association accessor method
+ # on the owner will reload the target. It's up to subclasses to implement this
+ # method if relevant.
+ #
+ # Note that if the target has not been loaded, it is not considered stale.
+ def stale_target?
+ false
+ end
+
# Returns the target of this proxy, same as +proxy_target+.
def target
@target
diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb
index b438620c8f..c9abfe36e8 100644
--- a/activerecord/lib/active_record/associations/belongs_to_association.rb
+++ b/activerecord/lib/active_record/associations/belongs_to_association.rb
@@ -42,6 +42,14 @@ module ActiveRecord
@updated
end
+ def stale_target?
+ if @target && @target.persisted?
+ @target.send(@reflection.association_primary_key).to_i != @owner.send(@reflection.primary_key_name).to_i
+ else
+ false
+ end
+ end
+
private
def find_target
find_method = if @reflection.options[:primary_key]
diff --git a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb
index a0df860623..844ae94c3d 100644
--- a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb
+++ b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb
@@ -23,6 +23,15 @@ module ActiveRecord
@updated
end
+ def stale_target?
+ if @target && @target.persisted?
+ @target.send(@reflection.association_primary_key).to_i != @owner.send(@reflection.primary_key_name).to_i ||
+ @target.class.base_class.name.to_s != @owner.send(@reflection.options[:foreign_type]).to_s
+ else
+ false
+ end
+ end
+
private
# NOTE - for now, we're only supporting inverse setting from belongs_to back onto
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index 7a7f7812df..87a842bc6b 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -209,7 +209,10 @@ module ActiveRecord
end
def association_primary_key
- @association_primary_key ||= options[:primary_key] || klass.primary_key
+ @association_primary_key ||=
+ options[:primary_key] ||
+ !options[:polymorphic] && klass.primary_key ||
+ 'id'
end
def active_record_primary_key