cvshepherd
cvshepherd

Reputation: 4007

returning struct data as a hash in ruby

Is there a valid reason for there not being a method to return the data of a standard ruby struct as a hash (member, value pairs)? Seeing that structs and hashes have very similar use cases, I'm surprised that no such method exists. Or does it, and I'm just too blind?

It's easy to implement (and i have done so for now), but lack of such functionality in the standard libs, has me thinking that I might have not really grasped the concept of structs in ruby.

Upvotes: 29

Views: 13124

Answers (4)

tokland
tokland

Reputation: 67910

Ruby <= 1.9.3 has OpenStruct#marshall_dump and Struct#each_pair:

Person = Struct.new(:name, :age)
person = Person.new("Jamie", 23)
person_hash = Hash[person.each_pair.to_a]
#=> {:age=>23, :name=>"Jamie"}

Ruby 2.0 provides Struct#to_h and OpenStruct#to_h:

Person = Struct.new(:name, :age)
person = Person.new("Jamie", 23)
person_hash = person.to_h
#=> {:age=>23, :name=>"Jamie"}

Upvotes: 48

peter
peter

Reputation: 42207

The accepted answer did not work for me, i used the following instead

require 'ostruct'
require 'date'

lid = OpenStruct.new(:status=>0,:rowversion=>0,:cre_dt=>DateTime.now.to_date,:cre_user=>'9999999')
p Hash[lid.each_pair.to_a] #=> {}
p lid.marshal_dump #=>{:status=>0, :rowversion=>0, :cre_dt=>#<Date: 2014-03-03 ((2456720j,0s,0n),+0s,2299161j)>, :cre_user=>"9999999"}

Upvotes: 0

Dave Newton
Dave Newton

Reputation: 160321

I guess I don't know why you'd want to do it either, but:

s.members.inject({}) { |m, f| m[f] = s[f]; m }

Or, using each_with_object:

s.members.each_with_object({}) { |m, h| h[m] = s[m] }

Upvotes: 2

David Grayson
David Grayson

Reputation: 87541

I don't think the use cases for hashes and structs are very similar. A hash lets you store a variable number of key-value pairs, and is suitable for storing thousands of pairs if a you want. No particular key is guaranteed to be present. With a Struct, you always know what the set of "keys" will be and it is usually small (less than 20).

Hashes can be used to associate some piece of information with a large number of different objects. Hashes be used to specify optional parameters to a function. Structs can be used when you want to keep some well-defined pieces of information together in one object.

I've never wanted to convert from the struct to a hash so I'm wondering why you do.

EDIT 1: Did you know you can use this un-hash-like syntax with Structs?

P = Struct.new(:x,:y)
p = P.new(1,2)
p.x  # => x

EDIT 2: Hashes can also be used to look up objects quickly. obj_hashed_by_name[name] can be much faster than obj_array.find { |a| a.name == name }.

Upvotes: 4

Related Questions