Feature #4862
closedStruct#to_hash
Description
Occasionally, it is necessary to convert a Struct to a Hash (especially when generating JSON from an Array of Structs). A Struct#to_hash method would be very useful in this situation.
class Struct
#
# Returns the Hash representation of the members and values within the struct.
#
def to_hash
new_hash = {}
each_pair do |member,value|
new_hash[member] = value
end
new_hash
end
end
Updated by rossmeissl (Andy Rossmeissl) over 12 years ago
def to_hash() Hash[members.zip(values)] end
Updated by trans (Thomas Sawyer) over 12 years ago
A Struct doesn't respond to hardly any Hash methods in general. So #to_h
seems more appropriate.
Updated by trans (Thomas Sawyer) over 12 years ago
Then again maybe I'm wrong b/c I was just surprised by the fact that a Struct doesn't have (or at least act like it has) instance_variables.
Struct.new(:a).new(1).instance_variables #=> []
Updated by Eregon (Benoit Daloze) over 12 years ago
Thomas Sawyer wrote:
Then again maybe I'm wrong b/c I was just surprised by the fact that a Struct doesn't have (or at least act like it has) instance_variables.
Struct.new(:a).new(1).instance_variables #=> []
Yeah, it is implemented with an array stored in the RStruct struct in MRI.
A Struct#to_hash method would be very useful in this situation.
I agree.
#to_hash is the right method name because there is no #to_h (but indeed it is somewhat inconsistent with #to_i, #to_int, ...)
Updated by trans (Thomas Sawyer) over 12 years ago
Despite it's implementation, I thought Struct was intended to provide a convenient way to make quick classes. Which is why I assume it would have instance variables. I can understand though that it would be implemented in another fashion for speed. But I would still think the public interface to appear as if it were a typical sort of class.
Given it's current interface it hardly resembles a Hash at all. I think #each at least should act the same as a Hash if #to_hash would be added to it, but instead it acts like an Array:
s = Struct.new(:a, :b).new(1,2)
=> #
s.map{ |a| a }
=> [1, 2]
"because there is no #to_h (but indeed it is somewhat inconsistent with #to_i, #to_int, ...)"
Not just "somewhat". So I ignore all that heehawing and define #to_h wherever it makes sense when I need it. Why #to_h should be carved out as some odd exception seems to me just a lot of needless fuss over... what?
Updated by drbrain (Eric Hodel) over 12 years ago
Struct does use instance variables, you just can't see them from ruby because they don't start with @
Updated by mame (Yusuke Endoh) over 12 years ago
- Status changed from Open to Assigned
- Assignee set to matz (Yukihiro Matsumoto)
Updated by matz (Yukihiro Matsumoto) over 12 years ago
- Status changed from Assigned to Rejected
#to_hash protocol expects the object to be hash-compatible. Struct is not the case.
Matz.