diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | lib/ostruct.rb | 28 | ||||
-rw-r--r-- | test/ostruct/test_ostruct.rb | 6 |
3 files changed, 27 insertions, 13 deletions
@@ -1,3 +1,9 @@ +Mon Jan 5 10:57:24 2015 Nobuyoshi Nakada <[email protected]> + + * lib/ostruct.rb (modifiable?, new_ostruct_member!, table!): + append suffixes to protected methods so that they will not clash + with assigned members. [Fix GH-806] + Sun Jan 4 22:33:33 2015 Nobuyoshi Nakada <[email protected]> * test/lib/test/unit.rb (ExcludesOption): add "excludes" support diff --git a/lib/ostruct.rb b/lib/ostruct.rb index f51eb7b5db..9e2761dad9 100644 --- a/lib/ostruct.rb +++ b/lib/ostruct.rb @@ -90,7 +90,7 @@ class OpenStruct hash.each_pair do |k, v| k = k.to_sym @table[k] = v - new_ostruct_member(k) + new_ostruct_member!(k) end end end @@ -99,7 +99,7 @@ class OpenStruct def initialize_copy(orig) super @table = @table.dup - @table.each_key{|key| new_ostruct_member(key)} + @table.each_key{|key| new_ostruct_member!(key)} end # @@ -141,14 +141,14 @@ class OpenStruct # def marshal_load(x) @table = x - @table.each_key{|key| new_ostruct_member(key)} + @table.each_key{|key| new_ostruct_member!(key)} end # # Used internally to check if the OpenStruct is able to be # modified before granting access to the internal Hash table to be modified. # - def modifiable + def modifiable? begin @modifiable = true rescue @@ -156,22 +156,22 @@ class OpenStruct end @table end - protected :modifiable + protected :modifiable? # # Used internally to defined properties on the # OpenStruct. It does this by using the metaprogramming function # define_singleton_method for both the getter method and the setter method. # - def new_ostruct_member(name) + def new_ostruct_member!(name) name = name.to_sym unless respond_to?(name) define_singleton_method(name) { @table[name] } - define_singleton_method("#{name}=") { |x| modifiable[name] = x } + define_singleton_method("#{name}=") { |x| modifiable?[name] = x } end name end - protected :new_ostruct_member + protected :new_ostruct_member! def method_missing(mid, *args) # :nodoc: mname = mid.id2name @@ -180,7 +180,7 @@ class OpenStruct if len != 1 raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1) end - modifiable[new_ostruct_member(mname)] = args[0] + modifiable?[new_ostruct_member!(mname)] = args[0] elsif len == 0 @table[mid] else @@ -207,7 +207,7 @@ class OpenStruct # person.age # => 42 # def []=(name, value) - modifiable[new_ostruct_member(name)] = value + modifiable?[new_ostruct_member!(name)] = value end # @@ -255,7 +255,9 @@ class OpenStruct alias :to_s :inspect attr_reader :table # :nodoc: - protected :table + alias table! table + undef table + protected :table! # # Compares this object and +other+ for equality. An OpenStruct is equal to @@ -264,7 +266,7 @@ class OpenStruct # def ==(other) return false unless other.kind_of?(OpenStruct) - @table == other.table + @table == other.table! end # @@ -274,7 +276,7 @@ class OpenStruct # def eql?(other) return false unless other.kind_of?(OpenStruct) - @table.eql?(other.table) + @table.eql?(other.table!) end # Compute a hash-code for this OpenStruct. diff --git a/test/ostruct/test_ostruct.rb b/test/ostruct/test_ostruct.rb index 14bc2b2da8..2c0da2a419 100644 --- a/test/ostruct/test_ostruct.rb +++ b/test/ostruct/test_ostruct.rb @@ -135,4 +135,10 @@ class TC_OpenStruct < Test::Unit::TestCase e = assert_raise(ArgumentError) { os.send :foo=, true, true } assert_match(/#{__callee__}/, e.backtrace[0]) end + + def test_modifiable + os = OpenStruct.new(modifiable: true) + assert_equal true, os.modifiable + assert_nothing_raised { os.foo = true } + end end |