aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authorthedarkone <thedarkone2@gmail.com>2013-09-29 18:56:32 +0200
committerthedarkone <thedarkone2@gmail.com>2013-09-29 18:58:50 +0200
commite9bf87f08e77a457e1b82c2409abcaf4aef5f97c (patch)
tree01d5b6fc007aa511a2a5ddf092423de198a2647c /activerecord/lib
parent414d1eaf6cd9333fe0c4123ba8d7157946505a3b (diff)
downloadrails-e9bf87f08e77a457e1b82c2409abcaf4aef5f97c.tar.gz
rails-e9bf87f08e77a457e1b82c2409abcaf4aef5f97c.tar.bz2
rails-e9bf87f08e77a457e1b82c2409abcaf4aef5f97c.zip
Fix AR#method_missing re-dispatching into overwritten attribute methods.
This was happening when a `super` call in an overwritten attribute method was triggering a method_missing fallback, because attribute methods haven't been generated yet. class Topic < ActiveRecord::Base def title # `super` would re-invoke this method if define_attribute_methods # hasn't been called yet resulting in double '!' appending super + '!' end end
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/attribute_methods.rb19
1 files changed, 18 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index bf270c1829..f90c11dcf7 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -128,6 +128,16 @@ module ActiveRecord
end
end
+ def find_generated_attribute_method(method_name) # :nodoc:
+ klass = self
+ until klass == Base
+ gen_methods = klass.generated_attribute_methods
+ return gen_methods.instance_method(method_name) if method_defined_within?(method_name, gen_methods, Object)
+ klass = klass.superclass
+ end
+ nil
+ end
+
# Returns +true+ if +attribute+ is an attribute method and table exists,
# +false+ otherwise.
#
@@ -163,7 +173,14 @@ module ActiveRecord
def method_missing(method, *args, &block) # :nodoc:
if self.class.define_attribute_methods
if respond_to_without_attributes?(method)
- send(method, *args, &block)
+ # make sure to invoke the correct attribute method, as we might have gotten here via a `super`
+ # call in a overwritten attribute method
+ if attribute_method = self.class.find_generated_attribute_method(method)
+ # this is probably horribly slow, but should only happen at most once for a given AR class
+ attribute_method.bind(self).call(*args, &block)
+ else
+ send(method, *args, &block)
+ end
else
super
end