2014-10-30 62 views
0

我的库存应用程序中有三个模型用于类别,项目和交易。我创建了一个报告,告诉我我想知道什么,但是我怀疑在视图中查询是不好的做法。我怀疑这是低效的。这是我目前的看法:查询模型以包含相关交易的总和

<table> 
    <tr> 
    <th>Category</th> 
    <th>Name</th> 
    <th>Description</th> 
    <th>Total</th> 
    </tr> 
<% @item_id_list.each do |item_id| %> 
    <% item = Item.find(item_id) %> 
    <% sum = Transaction.where(item_id: item_id).sum(:amount) %> 
    <tr> 
    <td><%= item.category.name %></td> 
    <td><%= item.name %></td> 
    <td><%= item.description %></td> 
    <td><%= sum %></td> 
    </tr> 
<% end %> 
</table> 

这里是我的电流控制器:

class ReportsController < ApplicationController 

    def current 
    @item_id_list = Transaction.uniq.pluck(:item_id) 
    end 

end 

以供参考,这里是我的架构:

ActiveRecord::Schema.define(version: 20141029181100) do 

    create_table "categories", force: true do |t| 
    t.string "name" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    create_table "items", force: true do |t| 
    t.integer "category_id" 
    t.string "name" 
    t.text  "description" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    add_index "items", ["category_id"], name: "index_items_on_category_id" 

    create_table "transactions", force: true do |t| 
    t.integer "item_id" 
    t.string "code" 
    t.date  "date" 
    t.integer "amount" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    add_index "transactions", ["item_id"], name: "index_transactions_on_item_id" 

end 

有人能提出一个更优雅从控制器获取@items列表的有效方法,其中包括相应交易的金额的计算总和,看起来像这样(总的确定使用率总和)?

#<ActiveRecord::Relation [ 
    #<Item id: 1, category_id: 1, name: "Stella 16oz", description: "Stella Tall boys", created_at: "2014-10-29 18:05:26", updated_at: "2014-10-29 18:05:26", total: 74>, 
    #<Item id: 2, category_id: 2, name: "Wine Bottle", description: "Red or White", created_at: "2014-10-29 19:59:30", updated_at: "2014-10-30 18:23:48", total: 12> 
]> 

而不是仅仅这一点:

#<ActiveRecord::Relation [ 
    #<Item id: 1, category_id: 1, name: "Stella 16oz", description: "Stella Tall boys", created_at: "2014-10-29 18:05:26", updated_at: "2014-10-29 18:05:26">, 
    #<Item id: 2, category_id: 2, name: "Wine Bottle", description: "Red or White", created_at: "2014-10-29 19:59:30", updated_at: "2014-10-30 18:23:48"> 
]> 

回答

2

你可以改变你的控制器代码这样:

class ReportsController < ApplicationController 

    def current 
    @items = Item.select('id, name, description').includes(:category, :transactions).all 
    end 

end 

然后在视图:

<table> 
    <tr> 
    <th>Category</th> 
    <th>Name</th> 
    <th>Description</th> 
    <th>Total</th> 
    </tr> 
    <% @items.each do |item| %> 
    <tr> 
     <td><%= item.category.name %></td> 
     <td><%= item.name %></td> 
     <td><%= item.description %></td> 
     <td><%= item.transactions.map(&:amount).sum %></td> 
    </tr> 
    <% end %> 
</table> 

几件事情:

  1. 查询时,您可能不想在控制器中调用.all,因为数据增长时您的页面加载时间将增加。
  2. 您可能希望修复模型类中的,以便在视图中您可以说:<%= item.category_name %>
  3. 在查询中查询被认为是不好的做法。你应该总是这样查询:<% sum = Transaction.where(item_id: item_id).sum(:amount) %>在控制器中不可见。

另外你可能希望有一个方法:transaction_amount像这样Item模型类:

def transaction_amount 
    transactions.map(&:amount).sum 
end 

所以,鉴于你可以这样做:<%= item.transaction_amount %>

然后最后你的看法会看像这样:

<table> 
    <tr> 
    <th>Category</th> 
    <th>Name</th> 
    <th>Description</th> 
    <th>Total</th> 
    </tr> 
    <% @items.each do |item| %> 
    <tr> 
     <td><%= item.category_name %></td> 
     <td><%= item.name %></td> 
     <td><%= item.description %></td> 
     <td><%= items.transaction_amount %></td> 
    </tr> 
    <% end %> 
</table>