ben*_*gan 137 ruby ruby-on-rails
我有以下创建的对象
@post = Post.create(:name => 'test', :post_number => 20, :active => true)
Run Code Online (Sandbox Code Playgroud)
保存后,我希望能够将对象恢复为哈希值,例如通过执行以下操作:
@object.to_hash
Run Code Online (Sandbox Code Playgroud)
如何在轨道内实现这一目标?
Swa*_*and 274
如果您只查找属性,那么您可以通过以下方式获取它们:
@post.attributes
Run Code Online (Sandbox Code Playgroud)
Raf*_*Raf 41
在最新版本的Rails中(虽然无法确切知道哪一个),您可以使用以下as_json方法:
@post = Post.first
hash = @post.as_json
puts hash.pretty_inspect
Run Code Online (Sandbox Code Playgroud)
将输出:
{
:name => "test",
:post_number => 20,
:active => true
}
Run Code Online (Sandbox Code Playgroud)
为了更进一步,您可以通过执行以下操作来覆盖该方法以自定义属性的显示方式:
class Post < ActiveRecord::Base
def as_json(*args)
{
:name => "My name is '#{self.name}'",
:post_number => "Post ##{self.post_number}",
}
end
end
Run Code Online (Sandbox Code Playgroud)
然后,使用与上面相同的实例,将输出:
{
:name => "My name is 'test'",
:post_number => "Post #20"
}
Run Code Online (Sandbox Code Playgroud)
这当然意味着您必须明确指定必须出现的属性.
希望这可以帮助.
编辑:
您也可以查看Hashifiable宝石.
Ser*_*kyy 23
@object.as_json
Run Code Online (Sandbox Code Playgroud)
as_json具有根据模型关系配置复杂对象的非常灵活的方式
例
模型广告系列属于商店,有一个列表
模型列表有许多list_tasks,每个list_tasks都有很多注释
我们可以得到一个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
})
Run Code Online (Sandbox Code Playgroud)
注意方法::标签可以帮助您附加与其他对象无关的任何其他对象.您只需要在模型广告系列中定义一个带有名称标签的方法.这个方法应该返回你需要的任何东西(例如Tags.all)
as_json的官方文档
您可以使用任一方式获取作为哈希返回的模型对象的属性
@post.attributes
Run Code Online (Sandbox Code Playgroud)
要么
@post.as_json
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
小智 6
您绝对可以使用这些属性来返回所有属性,但您可以向Post添加一个实例方法,将其称为"to_hash"并让它返回您想要的哈希数据.就像是
def to_hash
{ name: self.name, active: true }
end
Run Code Online (Sandbox Code Playgroud)
这里有一些很棒的建议.
我认为值得注意的是,您可以将ActiveRecord模型视为散列,如下所示:
@customer = Customer.new( name: "John Jacob" )
@customer.name # => "John Jacob"
@customer[:name] # => "John Jacob"
@customer['name'] # => "John Jacob"
Run Code Online (Sandbox Code Playgroud)
因此,您可以将对象本身用作哈希,而不是生成属性的哈希值.