1+ # frozen_string_literal: true
2+
13require 'ostruct'
24require 'recursive_open_struct/version'
35
1214# TODO: `#*_as_a_hash` deprecated. Nested hashes can be referenced using
1315# `#to_h`.
1416
17+ # rubocop:disable Metrics/ClassLength
1518class RecursiveOpenStruct < OpenStruct
1619 include Dig if OpenStruct . public_instance_methods . include? :dig
1720
@@ -28,7 +31,9 @@ def self.default_options
2831 }
2932 end
3033
31- def initialize ( hash = nil , passed_options = { } )
34+ # rubocop:disable Lint/MissingSuper
35+ # Intentionally doesn't call super and initializes +@table+ itself.
36+ def initialize ( hash = nil , passed_options = { } )
3237 hash = hash . to_h if [ hash . is_a? ( RecursiveOpenStruct ) , hash . is_a? ( OpenStruct ) ] . any?
3338 hash ||= { }
3439
@@ -40,6 +45,7 @@ def initialize(hash=nil, passed_options={})
4045
4146 @sub_elements = { }
4247 end
48+ # rubocop:enable Lint/MissingSuper
4349
4450 def marshal_load ( attributes )
4551 hash , @options = attributes
@@ -69,17 +75,17 @@ def to_h
6975
7076 # TODO: deprecated, unsupported by OpenStruct. OpenStruct does not consider
7177 # itself to be a "kind of" Hash.
72- alias_method : to_hash, : to_h
78+ alias to_hash to_h
7379
7480 # Continue supporting older rubies -- JRuby 9.1.x.x is still considered
7581 # stable, but is based on Ruby
7682 # 2.3.x and so uses :modifiable instead of :modifiable?. Furthermore, if
7783 # :modifiable is private, then make :modifiable? private too.
78- if ! OpenStruct . private_instance_methods . include? ( :modifiable? )
84+ unless OpenStruct . private_instance_methods . include? ( :modifiable? )
7985 if OpenStruct . private_instance_methods . include? ( :modifiable )
80- alias_method : modifiable?, : modifiable
86+ alias modifiable? modifiable
8187 elsif OpenStruct . public_instance_methods . include? ( :modifiable )
82- alias_method : modifiable?, : modifiable
88+ alias modifiable? modifiable
8389 private :modifiable?
8490 end
8591 end
@@ -89,7 +95,7 @@ def [](name)
8995 v = @table [ key_name ]
9096 if v . is_a? ( Hash )
9197 @sub_elements [ key_name ] ||= _create_sub_element_ ( v , mutate_input_hash : true )
92- elsif v . is_a? ( Array ) and @options [ :recurse_over_arrays ]
98+ elsif v . is_a? ( Array ) && @options [ :recurse_over_arrays ]
9399 @sub_elements [ key_name ] ||= recurse_over_array ( v )
94100 @sub_elements [ key_name ] = recurse_over_array ( @sub_elements [ key_name ] )
95101 else
@@ -100,7 +106,7 @@ def [](name)
100106 if private_instance_methods . include? ( :modifiable? ) || public_instance_methods . include? ( :modifiable? )
101107 def []=( name , value )
102108 key_name = _get_key_from_table_ ( name )
103- tbl = modifiable? # Ensure we are modifiable
109+ tbl = modifiable? # Ensure we are modifiable
104110 @sub_elements . delete ( key_name )
105111 tbl [ key_name ] = value
106112 end
@@ -120,19 +126,20 @@ def respond_to_missing?(mid, include_private = false)
120126
121127 # Adapted implementation of method_missing to accommodate the differences
122128 # between ROS and OS.
129+ # rubocop:disable Metrics/AbcSize
130+ # rubocop:disable Metrics/PerceivedComplexity
123131 def method_missing ( mid , *args )
124132 len = args . length
125133 if mid =~ /^(.*)=$/
126- if len != 1
127- raise ArgumentError , "wrong number of arguments (#{ len } for 1)" , caller ( 1 )
128- end
134+ raise ArgumentError , "wrong number of arguments (#{ len } for 1)" , caller ( 1 ) if len != 1
135+
129136 # self[$1.to_sym] = args[0]
130137 # modifiable?[new_ostruct_member!($1.to_sym)] = args[0]
131- new_ostruct_member! ( $1 . to_sym )
138+ new_ostruct_member! ( :: Regexp . last_match ( 1 ) . to_sym )
132139 public_send ( mid , args [ 0 ] )
133- elsif len == 0
140+ elsif len . zero?
134141 key = mid
135- key = $1 if key =~ /^(.*)_as_a_hash$/
142+ key = :: Regexp . last_match ( 1 ) if key =~ /^(.*)_as_a_hash$/
136143 if @table . key? ( _get_key_from_table_ ( key ) )
137144 new_ostruct_member! ( key )
138145 public_send ( mid )
@@ -147,6 +154,8 @@ def method_missing(mid, *args)
147154 raise err
148155 end
149156 end
157+ # rubocop:enable Metrics/PerceivedComplexity
158+ # rubocop:enable Metrics/AbcSize
150159
151160 def freeze
152161 @table . each_key do |key |
@@ -160,7 +169,7 @@ def freeze
160169 # 2.4.0.
161170 def new_ostruct_member ( name )
162171 key_name = _get_key_from_table_ ( name )
163- unless self . singleton_class . method_defined? ( name . to_sym )
172+ unless singleton_class . method_defined? ( name . to_sym )
164173 class << self ; self ; end . class_eval do
165174 define_method ( name ) do
166175 self [ key_name ]
@@ -185,7 +194,12 @@ class << self; self; end.class_eval do
185194
186195 def delete_field ( name )
187196 sym = _get_key_from_table_ ( name )
188- singleton_class . __send__ ( :remove_method , sym , "#{ sym } =" ) rescue NoMethodError # ignore if methods not yet generated.
197+ begin
198+ singleton_class . __send__ ( :remove_method , sym , "#{ sym } =" )
199+ rescue StandardError
200+ # ignore if methods not yet generated.
201+ NoMethodError
202+ end
189203 @sub_elements . delete ( sym )
190204 @table . delete ( sym )
191205 end
@@ -203,8 +217,9 @@ def initialize_dup(orig)
203217 end
204218
205219 def _get_key_from_table_ ( name )
206- return name . to_s if @table . has_key? ( name . to_s )
207- return name . to_sym if @table . has_key? ( name . to_sym )
220+ return name . to_s if @table . key? ( name . to_s )
221+ return name . to_sym if @table . key? ( name . to_sym )
222+
208223 name
209224 end
210225
@@ -222,5 +237,5 @@ def recurse_over_array(array)
222237 end
223238 array
224239 end
225-
226240end
241+ # rubocop:enable Metrics/ClassLength
0 commit comments