it-roy-ru.com

Ruby преобразовать объект в хэш

Допустим, у меня есть Gift объект с @name = "book" & @price = 15.95. Какой лучший способ преобразовать это в хэш {name: "book", price: 15.95} в Ruby, а не в Rails (хотя не стесняйтесь и Rails ответить)?

112
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}
76
Vasiliy Ermolovich

Просто скажите (текущий объект) .attributes

.attributes возвращает hash любого object. И это тоже чище.

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

Для объектов активной записи

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
monika mevenkamp
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
Andreas Rayo Kniep

Вы можете использовать метод as_json. Это преобразует ваш объект в хеш. 

Но этот хэш придет в качестве значения имени этого объекта в качестве ключа. В твоем случае, 

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

Если вам нужен хеш, который хранится в объекте, используйте as_json(root: false). Я думаю, что по умолчанию root будет ложным. Для получения дополнительной информации обратитесь к официальному руководству Ruby

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

10
vicke4

Вы можете написать очень элегантное решение, используя функциональный стиль.

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' ( 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}}]}
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
Lalit Kumar

Вы должны попробовать 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