[前][次][番号順一覧][スレッド一覧]

ruby-changes:62959

From: Marc-Andre <ko1@a...>
Date: Tue, 15 Sep 2020 05:11:01 +0900 (JST)
Subject: [ruby-changes:62959] 606c009ce2 (master): [ruby/ostruct] Avoid self calling our public methods.

https://git.ruby-lang.org/ruby.git/commit/?id=606c009ce2

From 606c009ce24bd8e9e07ecb8f920a77c005062ff5 Mon Sep 17 00:00:00 2001
From: Marc-Andre Lafortune <github@m...>
Date: Mon, 14 Sep 2020 13:48:29 -0400
Subject: [ruby/ostruct] Avoid self calling our public methods.

Found because `json` has a bad example in its test suite.
This implementation still offers better encapsulation.

diff --git a/lib/ostruct.rb b/lib/ostruct.rb
index d674274..9b44d4a 100644
--- a/lib/ostruct.rb
+++ b/lib/ostruct.rb
@@ -124,7 +124,7 @@ class OpenStruct https://github.com/ruby/ruby/blob/trunk/lib/ostruct.rb#L124
     @table = {}
     if hash
       hash.each_pair do |k, v|
-        self[k] = v
+        set_ostruct_member_value!(k, v)
       end
     end
   end
@@ -218,7 +218,7 @@ class OpenStruct https://github.com/ruby/ruby/blob/trunk/lib/ostruct.rb#L218
       if len != 1
         raise ArgumentError, "wrong number of arguments (given #{len}, expected 1)", caller(1)
       end
-      self[mname]= args[0]
+      set_ostruct_member_value!(mname, args[0])
     elsif len == 0
     elsif @table.key?(mid)
       raise ArgumentError, "wrong number of arguments (given #{len}, expected 0)"
@@ -262,6 +262,8 @@ class OpenStruct https://github.com/ruby/ruby/blob/trunk/lib/ostruct.rb#L262
     new_ostruct_member!(name)
     @table[name] = value
   end
+  alias_method :set_ostruct_member_value!, :[]=
+  private :set_ostruct_member_value!
 
   # :call-seq:
   #   ostruct.dig(name, *identifiers) -> object
diff --git a/test/ostruct/test_ostruct.rb b/test/ostruct/test_ostruct.rb
index d07fef3..560979e 100644
--- a/test/ostruct/test_ostruct.rb
+++ b/test/ostruct/test_ostruct.rb
@@ -246,4 +246,22 @@ class TC_OpenStruct < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ostruct/test_ostruct.rb#L246
     os = OpenStruct.new(method: :foo)
     assert_equal(os.object_id, os.method!(:object_id).call)
   end
+
+  def test_mistaken_subclass
+    sub = Class.new(OpenStruct) do
+      def [](k)
+        __send__(k)
+        super
+      end
+
+      def []=(k, v)
+        @item_set = true
+        __send__("#{k}=", v)
+        super
+      end
+    end
+    o = sub.new
+    o.foo = 42
+    assert_equal 42, o.foo
+  end
 end
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]