2016-04-29 50 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