Подтвердить что ты не робот

Ruby конвертирует Object в Hash

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

4b9b3361

Ответ 1

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}

Ответ 2

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

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

Ответ 3

Реализовать #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

Ответ 4

Gift.new.instance_values # => {"name"=>"book", "price"=>15.95}

Ответ 5

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

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

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

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

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

Ответ 6

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

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() 

Ответ 7

class Gift
  def to_hash
    instance_variables.map do |var|
      [var[1..-1].to_sym, instance_variable_get(var)]
    end.to_h
  end
end

Ответ 8

Если вы не находитесь в среде Rails (т.е. не имеете ActiveRecord), это может быть полезно:

JSON.parse( object.to_json )

Ответ 9

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

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

Ответ 10

Вы должны переопределить метод inspect вашего объекта, чтобы вернуть желаемый хеш, или просто реализовать аналогичный метод без переопределения поведения объекта по умолчанию.

Если вы хотите получить fancier, вы можете перебирать переменные экземпляра объекта с помощью object.instance_variables

Ответ 11

Рекурсивно конвертировать ваши объекты в хеш с помощью драгоценного камня "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}}]}

Ответ 12

Можете попробовать instance_values. Это сработало для меня.

Ответ 13

Производит мелкую копию как хэш-объект только атрибутов модели

my_hash_gift = gift.attributes.dup

Проверьте тип результирующего объекта

my_hash_gift.class
=> Hash

Ответ 15

Если вам нужны также вложенные объекты.

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

Ответ 16

Gift.new.attributes.symbolize_keys

Ответ 17

Чтобы сделать это без 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}

Ответ 18

Я начал использовать структуры для упрощения хеширования. Вместо использования простой структуры я создаю свой собственный класс, производный от хеша, это позволяет вам создавать свои собственные функции и документировать свойства класса.

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}