2017-04-25 91 views
0

我使用的Active Record協會三個型號:嵌套屬性關聯的模型添加Rails中

Book Model 
has_many :checkouts 

User Model 
has_many :checkouts 

Checkout Model 
belongs_to :book 
belongs_to :user 

在我看來,我需要從檢出的書,結賬和用戶名。

通過使用Book.first.checkouts我得到:

#<ActiveRecord::AssociationRelation 
    [#<Checkout id: 30, 
    checkout_date: "2017-04-13", 
    return_date: nil, 
    book_id: 118, 
    user_id: 1, 
    created_at: "2017-04-13 17:43:07", 
    updated_at: "2017-04-13 17:43:07" 
    >,#<Checkout id: 50, 
    checkout_date: "2017-04-13", 
    return_date: nil, 
    book_id: 118, 
    user_id: 1, 
    created_at: "2017-04-14 00:33:34", 
    updated_at: "2017-04-14 00:33:34"> 
    ]> 

但是,我想用戶名,而不僅僅是ID。我試過Book.first.checkouts.map { |c| c.user.name },但它只返回名稱,我需要結帳信息的其餘部分。理想情況下,我的數據(轉換成JSON)看起來像:

{ 
    name: "Book Name", 
    checkouts: [ 
    checkout_data: "Today", 
    user_name: "Mary" 
    ] 
} 

如何添加用戶名我結賬的數據?

+0

您是否單獨顯示結帳,即'.each'循環?你應該能夠顯示'checkout.user.name' – Okomikeruko

+0

@Okomikeruko是的,單獨通過每個循環。 'checkout.user.name'起作用,但它只返回用戶名。我需要結帳和用戶名。我想知道如果我可以將它添加到虛擬屬性或類似的東西。 – BHOLT

+0

我想我試圖結合2個對象的數據:'checkouts'和'user' – BHOLT

回答

1

你可以在你的控制器試試這個:

render json: @books, include: { checkout: { only: :checkout_date, include: { user: { only: :name } } }}

+0

不知道這個!這真的很好 – BHOLT

0

你應該預裝數據,以防止(N + 1)的查詢問題, 爲特定的圖書顯示可能檢出:

book_id = <given book id> 
book = Book.find(book_id) 
checkouts = book.checkouts.includes(:user) 
return_hash = {name: book.name, checkouts: []} 
checkouts.each do |checkout| 
    return_hash[:checkouts] << { checkout_data: checkout.checkout_date, 
           user_name: checkout.user.name 
           } 
end 
+0

這是我嘗試過的,但我想知道是否有一個更簡單的方法。什麼是N + 1查詢問題? – BHOLT

+1

checkout.user將針對每個結帳觸發1個查詢到數據庫,如果您使用includes:user,那麼所有相應的用戶將在單個IN查詢中預提取 – aqfaridi

0

要包括其他解決方案,我發現這個工作得很好:

checkouts = book.checkouts.unreturned.map do |checkout| 
    checkout.attributes.merge({ user_name: checkout.user.name }) 
end 

{ checkouts: checkouts, available: book.available?, book_id: book.id } 

attributes.merge訣竅。

+0

請勿使用。 attributes.merge在一個循環中,隨着應用程序的增長,它會花費很多的執行時間,我在我的應用程序中面臨同樣的性能問題,使用ruby-prof來查看代碼中的瓶頸 – aqfaridi