假设我有一个&的Gift
对象。将其转换为Ruby中的Hash 而不是Rails 的最佳方法是什么(尽管也可以给Rails答案)?@name = "book"
@price = 15.95
{name: "book", price: 15.95}
Gift
是完全一样@nash定义,除2)确定,实例变量可以有读者访问器。3)礼物中的所有属性。
假设我有一个&的Gift
对象。将其转换为Ruby中的Hash 而不是Rails 的最佳方法是什么(尽管也可以给Rails答案)?@name = "book"
@price = 15.95
{name: "book", price: 15.95}
Gift
是完全一样@nash定义,除2)确定,实例变量可以有读者访问器。3)礼物中的所有属性。
Answers:
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}
或者使用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}
var.to_s.delete("@")
用var[1..-1].to_sym
得到的符号。
gift.instance_variables.each_with_object({}) { |var,hash| hash[var.to_s.delete("@")] = gift.instance_variable_get(var) }
和摆脱尾随; hash
each
。map
而且inject
功能更强大 这是我对Ruby的一种设计标准:, map
并inject
通过实现each
。这简直是糟糕的计算机科学。
hash = Hash[gift.instance_variables.map { |var| [var.to_s[1..-1], gift.instance_variable_get(var)] } ]
只说(当前对象) .attributes
.attributes
返回hash
any object
。而且它也更清洁。
.values
:sequel.jeremyevans.net/rdoc/classes/Sequel/Model/...
instance_values
可以用于所有红宝石对象,以实现类似的输出。
实施#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
Use :: for describing class methods, # for describing instance methods, and use . for example code
来源:ruby-doc.org/documentation-guidelines.html)另外,官方文档(例如ruby CHANGELOG,github.com / ruby / ruby / blob / v2_1_0 / NEWS)也#
用于实例方法和点。类方法非常一致。
each_with_object
以下instance_variables.each_with_object(Hash.new(0)) { |element, hash| hash["#{element}".delete("@").to_sym] = instance_variable_get(element) }
Gift.new.instance_values # => {"name"=>"book", "price"=>15.95}
instance_values
。请注意,Matt要求使用Ruby方式,尤其不是Rails。
您可以使用as_json
方法。它将您的对象转换为哈希。
但是,该哈希将作为该对象名称的值作为键。就你而言
{'gift' => {'name' => 'book', 'price' => 15.95 }}
如果需要存储在对象中的哈希,请使用as_json(root: false)
。我认为默认情况下root将为false。有关更多信息,请参考官方红宝石指南
http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json
对于活动记录对象
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
然后打电话
gift.to_hash()
purch.to_hash()
如果您不在Rails环境中(即没有ActiveRecord可用),这可能会有所帮助:
JSON.parse( object.to_json )
您应该重写inspect
对象的方法以返回所需的哈希值,或者仅实现类似的方法而不重写默认的对象行为。
如果想变得更高级,可以使用object.instance_variables遍历对象的实例变量。
递归使用对象转换为哈希“哈希的”宝石(https://rubygems.org/gems/hashable) 例
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}}]}
如果还需要转换嵌套对象。
# @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 # }}}
Gift.new.attributes.symbolize_keys
要在没有Rails的情况下执行此操作,一种干净的方法是将属性存储在常量上。
class Gift
ATTRIBUTES = [:name, :price]
attr_accessor(*ATTRIBUTES)
end
然后,要将的实例转换Gift
为Hash
,您可以:
class Gift
...
def to_h
ATTRIBUTES.each_with_object({}) do |attribute_name, memo|
memo[attribute_name] = send(attribute_name)
end
end
end
这是执行此操作的好方法,因为它将仅包含您在上定义的内容attr_accessor
,而不是每个实例变量。
class Gift
ATTRIBUTES = [:name, :price]
attr_accessor(*ATTRIBUTES)
def create_random_instance_variable
@xyz = 123
end
def to_h
ATTRIBUTES.each_with_object({}) do |attribute_name, memo|
memo[attribute_name] = send(attribute_name)
end
end
end
g = Gift.new
g.name = "Foo"
g.price = 5.25
g.to_h
#=> {:name=>"Foo", :price=>5.25}
g.create_random_instance_variable
g.to_h
#=> {:name=>"Foo", :price=>5.25}
我开始使用结构来简化哈希转换。我没有使用裸结构,而是从哈希派生了我自己的类,这使您可以创建自己的函数,并记录类的属性。
require 'ostruct'
BaseGift = Struct.new(:name, :price)
class Gift < BaseGift
def initialize(name, price)
super(name, price)
end
# ... more user defined methods here.
end
g = Gift.new('pearls', 20)
g.to_h # returns: {:name=>"pearls", :price=>20}