Ruby-on-rails 要散列的 Rails 对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3872236/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:19:26  来源:igfitidea点击:

Rails Object to hash

ruby-on-railsruby

提问by ben morgan

I have the following object that has been created

我有以下已创建的对象

@post = Post.create(:name => 'test', :post_number => 20, :active => true)

Once this is saved, I want to be able to get the object back to a hash, e.g. by doing somthing like:

保存后,我希望能够将对象恢复为散列,例如通过执行以下操作:

@object.to_hash

How is this possible from within rails?

这怎么可能从轨道内?

回答by Swanand

If you are looking for only attributes, then you can get them by:

如果您只查找属性,则可以通过以下方式获取它们:

@post.attributes

回答by Raf

In most recent version of Rails (can't tell which one exactly though), you could use the as_jsonmethod :

在最新版本的 Rails 中(虽然不知道是哪一个),您可以使用以下as_json方法:

@post = Post.first
hash = @post.as_json
puts hash.pretty_inspect

Will output :

将输出:

{ 
  :name => "test",
  :post_number => 20,
  :active => true
}

To go a bit further, you could override that method in order to customize the way your attributes appear, by doing something like this :

更进一步,您可以覆盖该方法以自定义属性的显示方式,方法如下:

class Post < ActiveRecord::Base
  def as_json(*args)
    {
      :name => "My name is '#{self.name}'",
      :post_number => "Post ##{self.post_number}",
    }
  end
end

Then, with the same instance as above, will output :

然后,使用与上面相同的实例,将输出:

{ 
  :name => "My name is 'test'",
  :post_number => "Post #20"
}

This of course means you have to explicitly specify which attributes must appear.

这当然意味着您必须明确指定必须出现哪些属性。

Hope this helps.

希望这可以帮助。

EDIT :

编辑 :

Also you can check the Hashifiablegem.

您也可以检查Hashifiablegem。

回答by Serge Seletskyy

@object.as_json

as_json has very flexible way to configure complex object according to model relations

as_json 有非常灵活的方式可以根据模型关系配置复杂对象

EXAMPLE

例子

Model campaignbelongs to shopand has one list

模特活动属于店铺,有一个列表

Model listhas many list_tasksand each of list_taskshas many comments

模型列表有很多list_tasks并且每个list_tasks有很多注释

We can get one json which combines all those data easily.

我们可以得到一个很容易组合所有这些数据的 json。

@campaign.as_json(
    {
        except: [:created_at, :updated_at],
        include: {
            shop: {
                except: [:created_at, :updated_at, :customer_id],
                include: {customer: {except: [:created_at, :updated_at]}}},
            list: {
                except: [:created_at, :updated_at, :observation_id],
                include: {
                    list_tasks: {
                        except: [:created_at, :updated_at],
                        include: {comments: {except: [:created_at, :updated_at]}}
                    }
                }
            },
        },
        methods: :tags
    })

Notice methods: :tagscan help you attach any additional object which doesn't have relations with others. You just need to define a method with name tagsin model campaign. This method should return whatever you need (e.g. Tags.all)

注意方法: :tags可以帮助您附加任何与其他对象没有关系的附加对象。您只需要在模型活动中定义一个带有名称标签的方法。这个方法应该返回你需要的任何东西(例如Tags.all)

Official documentation for as_json

as_json 的官方文档

回答by John Cole

You can get the attributes of a model object returned as a hash using either

您可以使用以下任一方法获取作为哈希返回的模型对象的属性

@post.attributes

or

或者

@post.as_json

as_jsonallows you to include associations and their attributes as well as specify which attributes to include/exclude (see documentation). However, if you only need the attributes of the base object, benchmarking in my app with ruby 2.2.3 and rails 4.2.2 demonstrates that attributesrequires less than half as much time as as_json.

as_json允许您包含关联及其属性,并指定要包含/排除的属性(请参阅文档)。但是,如果您只需要基础对象的属性,在我的应用程序中使用 ruby​​ 2.2.3 和 rails 4.2.2 进行基准测试表明,attributes所需时间不到as_json.

>> p = Problem.last
 Problem Load (0.5ms)  SELECT  "problems".* FROM "problems"  ORDER BY "problems"."id" DESC LIMIT 1
=> #<Problem id: 137, enabled: true, created_at: "2016-02-19 11:20:28", updated_at: "2016-02-26 07:47:34"> 
>>
>> p.attributes
=> {"id"=>137, "enabled"=>true, "created_at"=>Fri, 19 Feb 2016 11:20:28 UTC +00:00, "updated_at"=>Fri, 26 Feb 2016 07:47:34 UTC +00:00}
>>
>> p.as_json
=> {"id"=>137, "enabled"=>true, "created_at"=>Fri, 19 Feb 2016 11:20:28 UTC +00:00, "updated_at"=>Fri, 26 Feb 2016 07:47:34 UTC +00:00}
>>
>> n = 1000000
>> Benchmark.bmbm do |x|
?>   x.report("attributes") { n.times { p.attributes } }
?>   x.report("as_json")    { n.times { p.as_json } }
>> end
Rehearsal ----------------------------------------------
attributes   6.910000   0.020000   6.930000 (  7.078699)
as_json     14.810000   0.160000  14.970000 ( 15.253316)
------------------------------------ total: 21.900000sec

             user     system      total        real
attributes   6.820000   0.010000   6.830000 (  7.004783)
as_json     14.990000   0.050000  15.040000 ( 15.352894)

回答by Jeffrey Harrington

There are some great suggestions here.

这里有一些很好的建议。

I think it's worth noting that you can treat an ActiveRecord model as a hash like so:

我认为值得注意的是,您可以将 ActiveRecord 模型视为散列,如下所示:

@customer = Customer.new( name: "John Jacob" )
@customer.name    # => "John Jacob"
@customer[:name]  # => "John Jacob"
@customer['name'] # => "John Jacob"

Therefore, instead of generating a hash of the attributes, you can use the object itself as a hash.

因此,您可以将对象本身用作散列,而不是生成属性的散列。

回答by Curtis Edmond

You could definitely use the attributes to return all attributes but you could add an instance method to Post, call it "to_hash" and have it return the data you would like in a hash. Something like

您绝对可以使用属性来返回所有属性,但您可以向 Post 添加一个实例方法,将其称为“to_hash”并让它以散列形式返回您想要的数据。就像是

def to_hash
 { name: self.name, active: true }
end

回答by Yuri

not sure if that's what you need but try this in ruby console:

不确定这是否是您所需要的,但在 ruby​​ 控制台中试试这个:

h = Hash.new
h["name"] = "test"
h["post_number"] = 20
h["active"] = true
h

obviously it will return you a hash in console. if you want to return a hash from within a method - instead of just "h" try using "return h.inspect", something similar to:

显然它会在控制台中返回一个哈希值。如果你想从一个方法中返回一个散列 - 而不是仅仅“h”尝试使用“return h.inspect”,类似于:

def wordcount(str)
  h = Hash.new()
  str.split.each do |key|
    if h[key] == nil
      h[key] = 1
    else
      h[key] = h[key] + 1
    end
  end
  return h.inspect
end

回答by fayvor

My solution:

我的解决方案:

Hash[ post.attributes.map{ |a| [a, post[a]] } ]

回答by Mirv - Matt

Old question, but heavily referenced ... I think most people use other methods, but there is infact a to_hashmethod, it has to be setup right. Generally, pluck is a better answer after rails 4 ... answering this mainly because I had to search a bunch to find this thread or anything useful & assuming others are hitting the same problem...

老问题,但被大量引用......我认为大多数人使用其他方法,但实际上有一种to_hash方法,必须正确设置。一般来说,在 rails 4 之后 pluck 是一个更好的答案......回答这个主要是因为我不得不搜索一堆才能找到这个线程或任何有用的东西,并假设其他人也遇到了同样的问题......

Note: not recommending this for everyone, but edge cases!

注意:不是为每个人推荐这个,而是边缘情况!



From the ruby on rails api ... http://api.rubyonrails.org/classes/ActiveRecord/Result.html...

从 ruby​​ on rails api ... http://api.rubyonrails.org/classes/ActiveRecord/Result.html...

This class encapsulates a result returned from calling #exec_query on any database connection adapter. For example:

result = ActiveRecord::Base.connection.exec_query('SELECT id, title, body FROM posts')
result # => #<ActiveRecord::Result:0xdeadbeef>

...

# Get an array of hashes representing the result (column => value):
result.to_hash
# => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
      {"id" => 2, "title" => "title_2", "body" => "body_2"},
      ...
     ] ...

回答by u445908

Swanand's answer is great.

斯瓦南德的回答很棒。

if you are using FactoryGirl, you can use its buildmethod to generate the attribute hash without the key id. e.g.

如果您使用 FactoryGirl,您可以使用它的build方法来生成没有 key 的属性哈希id。例如

build(:post).attributes