@name = "book"
と@price = 15.95
を持つGift
オブジェクトがあるとします。それをRailsではなく、Rubyのハッシュ{name: "book", price: 15.95}
に変換する最良の方法は何ですか(ただし、Railsの回答もお気軽に)。
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}
(現在のオブジェクト).attributes
と言うだけです
.attributes
は、hash
のobject
を返します。そして、それもずっときれいです。
#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
Gift.new.instance_values # => {"name"=>"book", "price"=>15.95}
as_json
メソッドを使用できます。オブジェクトをハッシュに変換します。
しかし、そのハッシュはキーとしてそのオブジェクトの名前に値として来ます。あなたの場合、
{'gift' => {'name' => 'book', 'price' => 15.95 }}
オブジェクトに保存されているハッシュが必要な場合は、as_json(root: false)
を使用します。デフォルトではルートはfalseになると思います。詳細については、公式のRubyガイドを参照してください
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()
class Gift
def to_hash
instance_variables.map do |var|
[var[1..-1].to_sym, instance_variable_get(var)]
end.to_h
end
end
Rails環境にない場合(つまり、ActiveRecordが利用できない場合)、これは役に立つかもしれません:
JSON.parse( object.to_json )
機能的なスタイルを使用して、非常にエレガントなソリューションを作成できます。
class Object
def hashify
Hash[instance_variables.map { |v| [v.to_s[1..-1].to_sym, instance_variable_get v] }]
end
end
'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}}]}
instance_values
を試してください。それは私のために働いた。
オブジェクトのinspect
メソッドをオーバーライドして、目的のハッシュを返すか、デフォルトのオブジェクトの動作をオーバーライドせずに同様のメソッドを実装する必要があります。
もっと面白くしたい場合は、 object.instance_variables を使用してオブジェクトのインスタンス変数を反復処理できます。
モデル属性のみのハッシュオブジェクトとして浅いコピーを生成します
my_hash_gift = gift.attributes.dup
結果のオブジェクトのタイプを確認します
my_hash_gift.class
=> Hash
Gift.new.attributes.symbolize_keys
ハッシュ変換を簡単にするために構造体を使用し始めました。むき出しの構造体を使用する代わりに、ハッシュから派生する独自のクラスを作成します。これにより、独自の関数を作成でき、クラスのプロパティが文書化されます。
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}
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}
素晴らしい逸品、Hashieを試してみてください: https://github.com/intridea/hashie
ネストされたオブジェクトも変換する必要がある場合。
# @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 # }}}