2014-10-30 64 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>