diff --git a/ChangeLog b/ChangeLog index a44ab6c6e4..28621c3d18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Thu Dec 31 14:36:45 2015 Marc-Andre Lafortune + + * lib/ostruct.rb: Fix new_ostruct_member to correctly avoid + redefinition [#11901] + Thu Dec 31 02:45:12 2015 NARUSE, Yui * test/ruby/test_module.rb (test_classpath): r53376 may change diff --git a/lib/ostruct.rb b/lib/ostruct.rb index e7b8ed4609..e5b69608ad 100644 --- a/lib/ostruct.rb +++ b/lib/ostruct.rb @@ -168,7 +168,7 @@ class OpenStruct # def new_ostruct_member(name) name = name.to_sym - unless respond_to?(name) + unless singleton_class.method_defined?(name) define_singleton_method(name) { @table[name] } define_singleton_method("#{name}=") { |x| modifiable[name] = x } end diff --git a/test/ostruct/test_ostruct.rb b/test/ostruct/test_ostruct.rb index 8b0424d2d8..02c4c74152 100644 --- a/test/ostruct/test_ostruct.rb +++ b/test/ostruct/test_ostruct.rb @@ -164,4 +164,21 @@ class TC_OpenStruct < Test::Unit::TestCase e = assert_raise(ArgumentError) { os.send :foo=, true, true } assert_match(/#{__callee__}/, e.backtrace[0]) end + + def test_accessor_defines_method + os = OpenStruct.new(foo: 42) + assert os.respond_to? :foo + assert_equal([], os.singleton_methods) + assert_equal(42, os.foo) + assert_equal([:foo, :foo=], os.singleton_methods) + end + + def test_does_not_redefine + os = OpenStruct.new(foo: 42) + def os.foo + 43 + end + os.foo = 44 + assert_equal(43, os.foo) + end end