Closed ryanjones closed 7 years ago
Just to add, same issue w/ birth_date(2i)
This isn't something that OpenStruct supports, and it isn't an edge case introduced by ROS. You can use send
or public_send
though to call methods that contain characters with special syntactic meaning to Ruby. Eg:
r = RecursiveOpenStruct.new({
"0"=>{
"id"=>"",
"coverage_id"=>"555",
"first_name"=>"Ryan ",
"last_name"=>"Jones",
"birth_date(2i)"=>"11",
"birth_date(3i)"=>"10",
"birth_date(1i)"=>"1940"
}
})
# => #<RecursiveOpenStruct 0={:id=>"", :coverage_id=>"555", :first_name=>"Ryan ", :last_name=>"Jones", :"birth_date(2i)"=>"11", :"birth_date(3i)"=>"10", :"birth_date(1i)"=>"1940"}>
r.public_send('0')
# => #<RecursiveOpenStruct id="", coverage_id="555", first_name="Ryan ", last_name="Jones", birth_date(2i)="11", birth_date(3i)="10", birth_date(1i)="1940">
r.public_send('0').public_send('birth_date(1i)')
# => "1940"
That said, I would be willing to consider a PR that optionally adds a prefix that would apply to all keys (although this could be done by preprocessing the hash before passing it to ROS). However, it would not solve your problem with birth_date(2i)
--- that would require public_send
or mangling the key through some sort of pre-processing of all keys.
A prefix would also make it easier/safer to access methods from Object/BasicObject, which might lead to less strange behavior if you try to use RecursiveOpenStruct on untrusted input (I can't think of a clear code-execution scenario, but untrusted input could certainly break code or introduce business logic bypasses if methods like class
are trusted):
r = RecursiveOpenStruct.new({ 'class' => :foo, 'bar' => :baz }, prefix_keys_with: 'prefix_')
r.class # => RecursiveOpenStruct
r.prefix_class # => :foo
Closing this issue b/c there hasn't been any activity in almost 2 years, and I have no plans to implement this feature myself.
Anyone wanting something like this with ROS: If you want/need to use characters that are not permitted in method names, or if you want to dynamically lookup values with send
/public_send
, you should use subscript notation instead. You should also think hard about whether ROS is the right tool for what you are trying to do. (IE, it might make sense as a simple mock/double with deeply nested objects and it is nice for configuration files, but it is not entirely equivalent to a JavaScript-style Object aside from trivial use-cases).
I don't think this is a problem with the gem itself, but if a hash starts with a number you can't access the RecursiveOpenStruct's below it. http://stackoverflow.com/questions/10542354/what-are-the-restrictions-for-method-names-in-ruby
It would be cool to have an option to put a string at the front (or something that allows access below). I just flipped it back to a hash and was fine.