Ruby将Object转换为Hash

时间:2011-02-17 14:56:45

标签: ruby object hashmap instance-variables

假设我有一个Gift对象@name = "book"& @price = 15.95。将它转换为Ruby中的Hash {name: "book", price: 15.95}的最佳方法是什么,而不是Rails(尽管也可以自由地给出Rails的答案)?

20 个答案:

答案 0 :(得分:278)

只说(当前对象).attributes

.attributes返回任意hash的{​​{1}}。而且它也更清洁。

答案 1 :(得分:76)

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 :(得分:46)

实施#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

答案 3 :(得分:38)

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

答案 4 :(得分:13)

对于活动记录对象

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

答案 5 :(得分:11)

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

答案 6 :(得分:11)

您可以使用as_json方法。它会将您的对象转换为哈希值。

但是,该哈希值将作为该对象名称的值作为键。在你的情况下,

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

如果您需要存储在对象中的哈希值,请使用as_json(root: false)。我认为默认情况下root将是false。有关更多信息,请参阅官方红宝石指南

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

答案 7 :(得分:10)

如果您不在Rails环境中(即没有ActiveRecord可用),这可能会有所帮助:

JSON.parse( object.to_json )

答案 8 :(得分:6)

您可以使用功能样式编写一个非常优雅的解决方案。

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

答案 9 :(得分:4)

您应该覆盖对象的inspect方法以返回所需的哈希,或者只是实现类似的方法而不会覆盖默认的对象行为。

如果你想变得更加漂亮,可以使用object.instance_variables

迭代对象的实例变量

答案 10 :(得分:4)

使用'hashable'gem(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}}]}

答案 11 :(得分:4)

可能想尝试instance_values。这对我有用。

答案 12 :(得分:1)

生成浅拷贝作为模型属性的哈希对象

my_hash_gift = gift.attributes.dup

检查结果对象的类型

my_hash_gift.class
=> Hash

答案 13 :(得分:0)

如果您还需要转换嵌套对象。

    <?php
        if($username && $password){
            $query  = "INSERT INTO users(username, password) ";
            $query .= "VALUES('" . $username . "', '" . $password . "')";
            $result = mysqli_query($connection,$query);

            if(!$result) {
                die('Query Failed' .mysqli_error($connection));
            }               
        }

答案 14 :(得分:0)

你应该尝试Hashie,一个很棒的宝石: https://github.com/intridea/hashie

答案 15 :(得分:0)

Gift.new.attributes.symbolize_keys

答案 16 :(得分:0)

要在没有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}

答案 17 :(得分: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}

答案 18 :(得分:0)

为了抄袭@Mr. L 在上面的评论中,尝试 @gift.attributes.to_options

答案 19 :(得分:0)

按照我无法编译的 Nate 的回答:

选项 1

class Object
    def to_hash
        instance_variables.map{ |v| Hash[v.to_s.delete("@").to_sym, instance_variable_get(v)] }.inject(:merge)
   end
end

然后你这样称呼它:

my_object.to_hash[:my_variable_name]

选项 2

class Object
    def to_hash
        instance_variables.map{ |v| Hash[v.to_s.delete("@"), instance_variable_get(v)] }.inject(:merge)
   end
end

然后你这样称呼它:

my_object.to_hash["my_variable_name"]