2010-10-06 103 views
111

我都已经创建Rails的对象哈希

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

一旦下列对象被保存,我希望能够得到目标回哈希值,例如通过做类似的东西:

@object.to_hash 

这是怎么可能从轨内?

回答

232

如果您正在寻找只有属性,那么你可以让他们:

@post.attributes 
+22

循环时,不要使用这个,[便宜的方法(http://apidock.com/rails/ActiveRecord /碱/属性#623-昂贵-方法 - )。使用as_json – AnkitG 2013-07-10 08:07:18

+3

'.to_json'将在数据库中查询模型是否完整 – ykhrustalev 2016-10-31 19:25:31

+1

适用于'joins'和'select','Person.joins(:address).select(“addresses.street,persons.name”)。find_by_id (id).attributes',将返回 '{ street:“”, name:“” }' – fangxing 2017-06-15 02:29:57

5

你肯定可以使用属性返回所有属性,但你可以添加一个实例方法后,称之为“to_hash “并让它在散列中返回你想要的数据。像

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

东西在最新版本的Rails(不能告诉一个人完全虽然),你可以使用as_json方法:

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

将输出:

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

为了进一步,您可以重写该方法来自定义您的属性出现的方式,通过这样做:

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

然后,与上述相同的情况下,将输出:

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

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

希望这会有所帮助。

编辑:

你也可以检查Hashifiable宝石。

+0

OP没有要求使用JSON,而是寻求散列。 – 2016-01-13 06:35:53

+3

@DavidHempy请在downvoting之前仔细阅读我的答案。正如我在我的示例中所显示的,这正是#as_json所做的工作,适用于:http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json。我没有选择该方法的名称。 – Raf 2016-01-14 01:06:53

2

不知道这是你需要什么,但这个尝试在Ruby控制台:

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

显然这将返回在控制台中的哈希值。如果你想从一个方法内返回哈希 - 而不是仅仅“H”尝试使用“回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 
+0

海报在Rails中询问ActiveRecord模型。 – 2013-12-31 17:28:41

0

Swanand的答案是伟大的。

如果您使用的是FactoryGirl,则可以使用其build方法生成属性哈希,而不使用密钥id。例如

build(:post).attributes 
16
@object.as_json 

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

通知方法:标签可以帮助您连接不与他人发生关系的任何其他对象。您只需要在模型活动中定义名称为标签的方法。这个方法应该返回任何你需要(例如Tags.all)为as_json

6

这里有一些很好的建议

正式文件。

我认为这是值得指出的是,你可以把一个ActiveRecord模型作为哈希像这样:

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

因此,与其生成的属性的散列值,你可以使用对象本身作为一个哈希值。

1

我的解决办法:

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

你可以得到一个模型对象的属性,无论是使用

@post.attributes 

@post.as_json 

as_json允许包括关联返回哈希及其属性以及指定要包含/排除哪些属性(请参阅documentation)。但是,如果您只需要基础对象的属性,那么在我的应用程序中使用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) 
+0

as_json将再次调用数据库查询,如果使用连接方法运行嵌套资源 – 2016-06-20 10:01:42

0

老问题,但大量引用......我想大多数人使用其他方法,但有一个逸岸方法to_hash,它必须建立正确的。一般来说,采摘4是一个更好的答案...回答这主要是因为我不得不搜索一堆,以找到这个线程或任何有用的&假设其他人正在碰到同样的问题...

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


从铁轨上... 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"}, 
     ... 
    ] ...