diff options
author | Marc-Andre Lafortune <[email protected]> | 2020-09-08 17:13:29 -0400 |
---|---|---|
committer | Marc-Andre Lafortune <[email protected]> | 2020-09-14 12:46:51 -0400 |
commit | 12a2e32d43256e37d36903c5fa5fabe556337d84 (patch) | |
tree | ce3a0c6210ce740f7fd6409237fdf4c09af21d40 /lib/ostruct.rb | |
parent | 12a13eef49dd2d839f502a7d848b7d600e8b645a (diff) |
[ruby/ostruct] Add access to public instance methods in case they are overriden
Diffstat (limited to 'lib/ostruct.rb')
-rw-r--r-- | lib/ostruct.rb | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/lib/ostruct.rb b/lib/ostruct.rb index c6f3be04e3..d674274966 100644 --- a/lib/ostruct.rb +++ b/lib/ostruct.rb @@ -62,8 +62,7 @@ # first_pet # => #<OpenStruct name="Rowdy"> # first_pet == second_pet # => true # -# -# == Implementation +# == Caveats # # An OpenStruct utilizes Ruby's method lookup structure to find and define the # necessary methods for properties. This is accomplished through the methods @@ -72,10 +71,41 @@ # This should be a consideration if there is a concern about the performance of # the objects that are created, as there is much more overhead in the setting # of these properties compared to using a Hash or a Struct. +# Creating an open struct from a small Hash and accessing a few of the +# entries can be 200 times slower than accessing the hash directly. +# +# This may also be the source of incompatibilities between Ruby versions: +# +# o = OpenStruct.new +# o.then # => nil in Ruby < 2.6, enumerator for Ruby >= 2.6 +# +# Builtin methods may be overwritten this way, which may be a source of bugs +# or security issues: +# +# o = OpenStruct.new +# o.methods # => [:to_h, :marshal_load, :marshal_dump, :each_pair, ... +# o.methods = [:foo, :bar] +# o.methods # => [:foo, :bar] +# +# To help remedy clashes, OpenStruct uses only protected/private methods ending with `!` +# and defines aliases for builtin public methods by adding a `!`: +# +# o = OpenStruct.new(make: 'Bentley', class: :luxury) +# o.class # => :luxury +# o.class! # => OpenStruct +# +# It is recommended (but not enforced) to not use fields ending in `!`. +# +# For all these reasons, consider not using OpenStruct at all. # class OpenStruct VERSION = "0.2.0" + instance_methods.each do |method| + new_name = "#{method}!" + alias_method new_name, method + end + # # Creates a new OpenStruct object. By default, the resulting OpenStruct # object will have no attributes. |