2010-10-06 131 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"}, 
     ... 
    ] ...