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
Rails Object to hash
提问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

