1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Fixed issue w/custom accessors + reserved name + inheritance

Fixed an issue where custom accessor methods (such as those generated by
`enum`) with the same name as a global method are incorrectly overridden
when subclassing.

This was partially fixed in 4155431 then broken again by e5f15a8.

Fixes #16288.
This commit is contained in:
Godfrey Chan 2014-08-11 00:00:23 -07:00
parent 49798b52bf
commit 2638d5c724
3 changed files with 34 additions and 5 deletions

View file

@ -1,3 +1,11 @@
* Fixed an issue where custom accessor methods (such as those generated by
`enum`) with the same name as a global method are incorrectly overridden
when subclassing.
Fixes #16288.
*Godfrey Chan*
* Define `id_was` to get the previous value of the primary key.
Currently when we call id_was and we have a custom primary key name

View file

@ -57,6 +57,8 @@ module ActiveRecord
end
end
class GeneratedAttributeMethods < Module; end # :nodoc:
module ClassMethods
def inherited(child_class) #:nodoc:
child_class.initialize_generated_modules
@ -64,7 +66,7 @@ module ActiveRecord
end
def initialize_generated_modules # :nodoc:
@generated_attribute_methods = Module.new { extend Mutex_m }
@generated_attribute_methods = GeneratedAttributeMethods.new { extend Mutex_m }
@attribute_methods_generated = false
include @generated_attribute_methods
end
@ -113,10 +115,11 @@ module ActiveRecord
if superclass == Base
super
else
# If B < A and A defines its own attribute method, then we don't want to overwrite that.
defined = method_defined_within?(method_name, superclass, superclass.generated_attribute_methods)
base_defined = Base.method_defined?(method_name) || Base.private_method_defined?(method_name)
defined && !base_defined || super
# If ThisClass < ... < SomeSuperClass < ... < Base and SomeSuperClass
# defines its own attribute method, then we don't want to overwrite that.
defined = method_defined_within?(method_name, superclass, Base) &&
! superclass.instance_method(method_name).owner.is_a?(GeneratedAttributeMethods)
defined || super
end
end

View file

@ -810,6 +810,24 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal "lol", topic.author_name
end
def test_inherited_custom_accessors_with_reserved_names
klass = Class.new(ActiveRecord::Base) do
self.table_name = 'computers'
self.abstract_class = true
def system; "omg"; end
def system=(val); self.developer = val; end
end
subklass = Class.new(klass)
[klass, subklass].each(&:define_attribute_methods)
computer = subklass.find(1)
assert_equal "omg", computer.system
computer.developer = 99
assert_equal 99, computer.developer
end
def test_on_the_fly_super_invokable_generated_attribute_methods_via_method_missing
klass = new_topic_like_ar_class do
def title