From e9bf87f08e77a457e1b82c2409abcaf4aef5f97c Mon Sep 17 00:00:00 2001 From: thedarkone Date: Sun, 29 Sep 2013 18:56:32 +0200 Subject: 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 --- activerecord/lib/active_record/attribute_methods.rb | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'activerecord/lib') 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 -- cgit v1.2.3