it-swarm.com.de

Ruby konvertiert Objekt in Hash

Nehmen wir an, ich habe ein Gift-Objekt mit @name = "book" & @price = 15.95. Was ist der beste Weg, das in Ruby in Hash {name: "book", price: 15.95} umzuwandeln, nicht in Rails (obwohl Sie den Rails auch eine Antwort geben können)?

111
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}

Alternativ mit 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}
76

Sagen Sie einfach (aktuelles Objekt) .attributes

.attributes gibt eine hash einer beliebigen object zurück. Und es ist auch viel sauberer.

275
Austin Marusco

#to_hash implementieren?

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

Für aktive Datensatzobjekte

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

und dann einfach anrufen

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

Wenn Sie sich nicht in einer Rails-Umgebung befinden (dh ActiveRecord nicht verfügbar ist), kann dies hilfreich sein:

JSON.parse( object.to_json )
10

Sie können die as_json-Methode verwenden. Es wird Ihr Objekt in Hash konvertieren. 

Dieser Hashwert wird jedoch als Wert für den Namen dieses Objekts verwendet. In Ihrem Fall, 

{'gift' => {'name' => 'book', 'price' => 15.95 }}

Wenn Sie einen Hash benötigen, der im Objekt gespeichert ist, verwenden Sie as_json(root: false). Ich denke, dass root standardmäßig falsch ist. Weitere Informationen finden Sie im offiziellen Ruby-Handbuch

http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json

10
vicke4

Sie können eine sehr elegante Lösung mit einem funktionalen Stil schreiben.

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

Konvertieren Sie Ihre Objekte rekursiv in Hash, indem Sie 'hashable' gem verwenden ( https://rubygems.org/gems/hashable ) Beispiel

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

Vielleicht möchten Sie instance_values versuchen. Das hat bei mir funktioniert.

4
Hunter

Sie sollten die inspect-Methode Ihres Objekts überschreiben, um den gewünschten Hash zurückzugeben, oder einfach eine ähnliche Methode implementieren, ohne das Standardobjektverhalten zu überschreiben.

Wenn Sie schicker werden möchten, können Sie die Instanzvariablen eines Objekts mit object.instance_variables durchlaufen.

4
Dominic

Erzeugt eine flache Kopie als Hashobjekt nur der Modellattribute

my_hash_gift = gift.attributes.dup

Überprüfen Sie den Typ des resultierenden Objekts

my_hash_gift.class
=> Hash
1
Sean

Gift.new.attributes.symbolize_keys

0
Lalit Kumar

Ich habe angefangen, Strukturen zu verwenden, um Hash-Konvertierungen zu vereinfachen. Anstatt eine nackte Struktur zu verwenden, erstelle ich meine eigene Klasse, die von einem Hash abgeleitet ist. Auf diese Weise können Sie Ihre eigenen Funktionen erstellen und die Eigenschaften einer Klasse dokumentieren.

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

Um dies ohne Rails zu tun, besteht eine saubere Möglichkeit darin, Attribute in einer Konstanten zu speichern.

class Gift
  ATTRIBUTES = [:name, :price]
  attr_accessor(*ATTRIBUTES)
end

Um eine Instanz von Gift in eine Hash zu konvertieren, haben Sie folgende Möglichkeiten:

class Gift
  ...
  def to_h
    ATTRIBUTES.each_with_object({}) do |attribute_name, memo|
      memo[attribute_name] = send(attribute_name)
    end
  end
end

Dies ist eine gute Möglichkeit, da nur das enthalten ist, was Sie in attr_accessor definiert haben, und nicht jede Instanzvariable.

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

Sie sollten Hashie ausprobieren, ein wunderbares Juwel: https://github.com/intridea/hashie

0
andoke

Wenn Sie auch verschachtelte Objekte konvertieren möchten.

# @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