-
Notifications
You must be signed in to change notification settings - Fork 32
Recursively converting child hash attributes to OpenStruct. #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Hi @hsbt , Did you get a chance to review this PR? What do you think about the changes? Regards, |
No maintainer or someone to have decision, but before going forward I'd suggest two things:
Additionally, as being a new feature this should be proposed via https://bugs.ruby-lang.org ticket, will be discussed there (if not rejected before). |
It's fine to propose a feature/change without having tests, etc., as a way to first check if the feature is acceptable or not. In this case I believe it isn't, for compatibility reasons. In the example above, |
@marcandre Thanks for the response!! I completely agree with your feedback. But there are a lot of people out there expecting OpenStruct to recursively convert a child hash to another OpenStruct object. So, why not provide them with an option to recursively convert child hash objects to OpenStruct object? Maybe allowing users to pass additional options to constructor would help? Like this:
|
Adding a The official forum to get a new feature accepted is https://bugs.ruby-lang.org/ . Best thing at this point would be to make the feature request there to see if there are any objections. If you'd like to work on the implementation, you can amend this PR too. You'll need tests, also I'd use |
@marcandre Thanks! Like you suggested I will create a feature request on https://bugs.ruby-lang.org/ 😃 |
lib/ostruct.rb
Outdated
if hash | ||
hash.each_pair do |k, v| | ||
k = k.to_sym | ||
@table[k] = v | ||
@table[k] = (recursive && v.is_a?(Hash)) ? OpenStruct.new(v, recursive: true) : v |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
recursive
is not defined as a keyword argument.
lib/ostruct.rb
Outdated
if hash | ||
hash.each_pair do |k, v| | ||
k = k.to_sym | ||
@table[k] = v | ||
@table[k] = (recursive && v.is_a?(Hash)) ? OpenStruct.new(v,true) : v |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I pointed out, best use respond_to?(:to_hash)
instead of is_a?(Hash)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry missed that. Updated the code!
…nstead of is_a?(Hash)
+1 for the PR |
lib/ostruct.rb
Outdated
@@ -88,12 +87,13 @@ class OpenStruct | |||
# | |||
# data # => #<OpenStruct country="Australia", capital="Canberra"> | |||
# | |||
def initialize(hash=nil) | |||
def initialize(hash=nil, is_recursive=false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be more readable to use a keyword argument I'd say
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated! Thanks :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we use keyword argument the below test will fail:
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.sort)
end
But for better readability I changed the constructor to this:
def initialize(hash=nil, options={recursive: false})
@table = {}
@recursive = options.fetch(:recursive, false)
if hash
hash.each_pair do |k, v|
k = k.to_sym
@table[k] = (@recursive && v.respond_to?(:to_hash)) ? OpenStruct.new(v,true) : v
end
end
end
bd2c661
to
696ba34
Compare
Just FYI, A feature request has been created here https://bugs.ruby-lang.org/issues/15225 |
lib/ostruct.rb
Outdated
if hash | ||
hash.each_pair do |k, v| | ||
k = k.to_sym | ||
@table[k] = v | ||
@table[k] = (@recursive && v.respond_to?(:to_hash)) ? OpenStruct.new(v,true) : v |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OpenStruct.new(v, options)
or OpenStruct.new(v, recursive: true)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it should be OpenStruct.new(v, options)
. Will update the PR in a bit.
lib/ostruct.rb
Outdated
@@ -202,7 +202,7 @@ def method_missing(mid, *args) # :nodoc: | |||
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)] = (@recursive && args[0].respond_to?(:to_hash)) ? OpenStruct.new(args[0],true) : args[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
OpenStruct.new(v, recursive: true)
Hi there! Any news? |
I updated https://bugs.ruby-lang.org/issues/15225 |
This PR can enable something like this: