2016-04-29 54 views
1

我得到一個不應該ping視圖中的數據庫...但想知道正確的解決方案。在我的一個觀點中,我需要根據每個子女item獲取有關@order,它的子女items以及另一個模型Amount的信息。事情是這樣的:如何避免在視圖中打數據庫

<% @order.items.each do |item| %> 
    <td><%= item.name %></td> 
    <td><%= Refund.where(item_id:item.id).first.amount %></td> 
    <td><%= Amount.where(item_id: item.id).first.amount %></td> 
<% end %> 

爲了避免在視圖中點擊分貝的緣故,我已經想到的唯一的解決辦法是建立在控制器中的所有相關數據的一個巨大的哈希值,然後訪問從視圖。因此,這將是這樣的:

# controller (writing quickly, code may not be totally right, hopefully you get gist 
data = Hash.new 
data["items"] = [] 
@order.items.each do |item| 
    item_hash = { 
    "name" => item.name, 
    "amount" => Amount.where(item_id: item.id).first.amount, 
    "refund" => Refund.where(item_id:item.id).first.amount 
    } 
    data["items"] << item_hash 
end 

# view code 
<% data["items"].each do |item| %> 
    <td><%= item["name"] %></td> 
    <td><%= item["refund"] %></td> 
    <td><%= item["amount"] %></td> 
<% end %> 

而且我知道這麼討厭這種類型的問題...但我真正需要知道的是......最好的解決辦法?還是有最佳做法?我問的原因是因爲它在視圖中看起來非常乾淨,但在控制器中非常龐大,而且當你有一套更加複雜的嵌套表時(這實際上就是這樣)(即data哈希將是相當時髦的放在一起)

+0

記住'{}'和'Hash.new'一樣好,簡潔得多。 – tadman

+0

物品,退款和金額之間的關聯是什麼?一對一,一對多?即項目has_one:退款?你的問題表明物品可能有很多退款,但我的問題是這是你的意圖嗎? – jverban

回答

5

首先我會使用項目和其他2類之間的關係,這樣就可以做

item.refund 
item.amount 

而不是Refund.where(...)。你可以進一步定義方法,如

def refund_amount 
    refund.amount 
end 

而且類似的其他一個(希望拿出比amount_amount一個更好的名字。

這樣可以使你既視圖和控制器乾淨的,但它不會是到目前爲止,所有的方法都涉及每個項目運行2個數據庫查詢,這對我來說是真正的問題 - 這些超出的查詢是發生在視圖中還是控制器不太重視。您可以使用Active Record的包含機制來避免這種情況:

Item.include(:amount,:refund).where("your conditions here") 

將加載散列的命名關聯,而不是一次加載一個,因爲每個項目都被訪問。

+0

對不起,我在深夜問了這個問題,以至於很愚蠢,這些協會已經到位,所以我可以做一個'item.refund'。我明白你在說什麼,感謝提醒你使用'include'。我會保持唯一的觀點,謝謝! – james