web-dev-qa-db-ja.com

Rubyオブジェクトをハッシュに変換

@name = "book"@price = 15.95を持つGiftオブジェクトがあるとします。それをRailsではなく、Rubyのハッシュ{name: "book", price: 15.95}に変換する最良の方法は何ですか(ただし、Railsの回答もお気軽に)。

119
ma11hew28
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}
78

(現在のオブジェクト).attributesと言うだけです

.attributesは、hashobjectを返します。そして、それもずっときれいです。

281
Austin Marusco

#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
47
levinalex
Gift.new.instance_values # => {"name"=>"book", "price"=>15.95}
40
Erik Reedstrom

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

14
vicke4

アクティブレコードオブジェクトの場合

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() 
13
class Gift
  def to_hash
    instance_variables.map do |var|
      [var[1..-1].to_sym, instance_variable_get(var)]
    end.to_h
  end
end
11
tokland

Rails環境にない場合(つまり、ActiveRecordが利用できない場合)、これは役に立つかもしれません:

JSON.parse( object.to_json )
10

機能的なスタイルを使用して、非常にエレガントなソリューションを作成できます。

class Object
  def hashify
    Hash[instance_variables.map { |v| [v.to_s[1..-1].to_sym, instance_variable_get v] }]
  end
end
6
Nate Symer

'hashable' gemを使用してオブジェクトをハッシュに再帰的に変換します( https://rubygems.org/gems/hashableExample

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}}]}
4
mustafaturan

instance_valuesを試してください。それは私のために働いた。

4
Hunter

オブジェクトのinspectメソッドをオーバーライドして、目的のハッシュを返すか、デフォルトのオブジェクトの動作をオーバーライドせずに同様のメソッドを実装する必要があります。

もっと面白くしたい場合は、 object.instance_variables を使用してオブジェクトのインスタンス変数を反復処理できます。

4
Dominic

モデル属性のみのハッシュオブジェクトとして浅いコピーを生成します

my_hash_gift = gift.attributes.dup

結果のオブジェクトのタイプを確認します

my_hash_gift.class
=> Hash
1
Sean

Gift.new.attributes.symbolize_keys

0

ハッシュ変換を簡単にするために構造体を使用し始めました。むき出しの構造体を使用する代わりに、ハッシュから派生する独自のクラスを作成します。これにより、独自の関数を作成でき、クラスのプロパティが文書化されます。

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}
0
Alex

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}
0
Vini Brasil

素晴らしい逸品、Hashieを試してみてください: https://github.com/intridea/hashie

0
andoke

ネストされたオブジェクトも変換する必要がある場合。

# @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 # }}}
0
Santiago