Let's say I have a Gift
object with @name = "book"
& @price = 15.95
. What's the best way to convert that to the Hash {name: "book", price: 15.95}
in Ruby, not Rails (although feel free to give the Rails answer too)?
问题:
回答1:
class Gift
def initialize
@name = "book"
@price = 15.95
end
end
gift = Gift.new
hash = {}
gift.instance_variables.each {|var| hash[var.to_s.delete("@")] = gift.instance_variable_get(var) }
p hash # => {"name"=>"book", "price"=>15.95}
Alternatively with each_with_object
:
gift = Gift.new
hash = gift.instance_variables.each_with_object({}) { |var, hash| hash[var.to_s.delete("@")] = gift.instance_variable_get(var) }
p hash # => {"name"=>"book", "price"=>15.95}
回答2:
Just say (current object) .attributes
.attributes
returns a hash
of any object
. And it's much cleaner too.
回答3:
Implement #to_hash
?
class Gift
def to_hash
hash = {}
instance_variables.each {|var| hash[var.to_s.delete("@")] = instance_variable_get(var) }
hash
end
end
h = Gift.new("Book", 19).to_hash
回答4:
Gift.new.instance_values # => {"name"=>"book", "price"=>15.95}
回答5:
For Active Record Objects
module ActiveRecordExtension
def to_hash
hash = {}; self.attributes.each { |k,v| hash[k] = v }
return hash
end
end
class Gift < ActiveRecord::Base
include ActiveRecordExtension
....
end
class Purchase < ActiveRecord::Base
include ActiveRecordExtension
....
end
and then just call
gift.to_hash()
purch.to_hash()
回答6:
class Gift
def to_hash
instance_variables.map do |var|
[var[1..-1].to_sym, instance_variable_get(var)]
end.to_h
end
end
回答7:
If you are not in an Rails environment (ie. don't have ActiveRecord available), this may be helpful:
JSON.parse( object.to_json )
回答8:
You can use as_json
method. It'll convert your object into hash.
But, that hash will come as a value to the name of that object as a key. In your case,
{'gift' => {'name' => 'book', 'price' => 15.95 }}
If you need a hash that's stored in the object use as_json(root: false)
. I think by default root will be false. For more info refer official ruby guide
http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json
回答9:
You can write a very elegant solution using a functional style.
class Object
def hashify
Hash[instance_variables.map { |v| [v.to_s[1..-1].to_sym, instance_variable_get v] }]
end
end
回答10:
You should override the inspect
method of your object to return the desired hash, or just implement a similar method without overriding the default object behaviour.
If you want to get fancier, you can iterate over an object's instance variables with object.instance_variables
回答11:
Recursively convert your objects to hash using 'hashable' gem (https://rubygems.org/gems/hashable) Example
class A
include Hashable
attr_accessor :blist
def initialize
@blist = [ B.new(1), { 'b' => B.new(2) } ]
end
end
class B
include Hashable
attr_accessor :id
def initialize(id); @id = id; end
end
a = A.new
a.to_dh # or a.to_deep_hash
# {:blist=>[{:id=>1}, {"b"=>{:id=>2}}]}
回答12:
Might want to try instance_values
. That worked for me.
回答13:
Produces a shallow copy as a hash object of just the model attributes
my_hash_gift = gift.attributes.dup
Check the type of the resulting object
my_hash_gift.class
=> Hash
回答14:
You should try Hashie, a wonderful gem : https://github.com/intridea/hashie
回答15:
If you need nested objects to be converted as well.
# @fn to_hash obj {{{
# @brief Convert object to hash
#
# @return [Hash] Hash representing converted object
#
def to_hash obj
Hash[obj.instance_variables.map { |key|
variable = obj.instance_variable_get key
[key.to_s[1..-1].to_sym,
if variable.respond_to? <:some_method> then
hashify variable
else
variable
end
]
}]
end # }}}
回答16:
Gift.new.attributes.symbolize_keys