Step.12 類別的下拉選單 - Azraeil/JCcart_Note GitHub Wiki
接下來的使用者管理、類別管理,都是一樣的寫法去寫,現在要教如何製作快一點的類別管理,我們先做一個產生器
rails c
:001 > 10.times do |i|
:002 > Cate.create(:name => Faker::Pokemon.name)
:003?> end; true
如此我們就建了十個類別。
這邊要教用f.select來做下拉式選單
fix app/views/dashboard/admin/items/edit.html.erb
<%= form_for @item, :url => dashboard_admin_item_path, method: :patch do |f| %>
...
...
...
類別: <%= f.select Cate.all.map{|c|[c.name, c.id]} %>
<button type="submit" >送出</button>
<% end %>這邊解釋一下Cate.all.map{|c|[c.name, c.id]}這段,用f.select生成的下拉式選單,他其實是要放一個array,array裡包值[["名稱", value]]
然後點選編輯,發現又噴了,JC下辜狗關鍵字rails helper select form,點選ActionView::Helpers::FormBuilder然後看裡面的select,發現少給了name,於是改成
類別: <%= f.select :cate_id, Cate.all.map{|c|[c.name, c.id]} %>
然後重整進入編輯頁面,就能看到漂亮的下拉選單了。我們一樣能用chrome工具檢查元素查看
<select name="item[cate_id]" id="item_cate_id"><option selected="selected" value="1">大雜燴</option>
<option value="2">Omanyte</option>
<option value="3">Golbat</option>
<option value="4">Pidgeotto</option>
<option value="5">Nidoking</option>
<option value="6">Dragonair</option>
<option value="7">Blastoise</option>
<option value="8">Exeggutor</option>
<option value="9">Vulpix</option>
<option value="10">Magnemite</option>
<option value="11">Geodude</option></select>可以看到name傳了一個array進去,而option有著用faker生成的各種Pokemon name與value
完成下拉選單後,我們給幾筆資料加入類別後送出,接著我們要給頁面顯示類別,但這會有一個n+1 query的問題,我們直接上code來看吧
fix views/dashboard/admin/items/index.html.erb
<table>
<thead>
<tr>
<th>id</th>
<th>類別</th>
...
...
</tr>
</thead>
<tbody>
<% @items.each do |item| %>
<tr>
<td><%= item.id %></td>
<td><%= item.cate.name %></td>
...
...
...
</tr>
<% end %>
</tbody>
</table>然後我們去localhost:3000/dashboard/admin/items就能看到剛剛輸入的類別了,接下來我們去跑rails s的那個iTerm tab查看他的log,可以看到像下面的code
Started GET "/dashboard/admin/items" for ::1 at 2016-09-09 22:09:00 +0800
Processing by Dashboard::Admin::ItemsController#index as HTML
Manager Load (0.3ms) SELECT `managers`.* FROM `managers` WHERE `managers`.`id` = 1 ORDER BY `managers`.`id` ASC LIMIT 1
Item Load (0.3ms) SELECT `items`.* FROM `items` ORDER BY id DESC LIMIT 30 OFFSET 0
(0.2ms) SELECT COUNT(*) FROM `items`
Cate Load (0.2ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 2 LIMIT 1
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 2 LIMIT 1 [["id", 2]]
Cate Load (0.2ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 4 LIMIT 1
Cate Load (0.3ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 3 LIMIT 1
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 3 LIMIT 1 [["id", 3]]
Cate Load (0.4ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.1ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 1 LIMIT 1 [["id", 1]]
Rendered dashboard/admin/items/index.html.erb within layouts/admin (38.0ms)
Completed 200 OK in 65ms (Views: 61.2ms | ActiveRecord: 2.4ms)這個是跑index view時,為了查詢類別所花的時間,當你類別越多花的時間越多,這就是n+1 query是很嚴重的效能問題,他的解法在controller內
fix app/controllers/dashboard/admin/items_controller.rb
def index
@items = @paginate = Item.order('id DESC').includes(:cate).paginate(:page => params[:page])
end
然後重整localhost:3000/dashboard/admin/items,再去查看log
Started GET "/dashboard/admin/items" for ::1 at 2016-09-09 22:20:40 +0800
Processing by Dashboard::Admin::ItemsController#index as HTML
Manager Load (0.2ms) SELECT `managers`.* FROM `managers` WHERE `managers`.`id` = 1 ORDER BY `managers`.`id` ASC LIMIT 1
Item Load (0.5ms) SELECT `items`.* FROM `items` ORDER BY id DESC LIMIT 30 OFFSET 0
Cate Load (5.0ms) SELECT `cates`.* FROM `cates` WHERE `cates`.`id` IN (2, 4, 3, 1)
(0.4ms) SELECT COUNT(*) FROM `items`
Rendered dashboard/admin/items/index.html.erb within layouts/admin (43.7ms)
Completed 200 OK in 99ms (Views: 75.0ms | ActiveRecord: 9.8ms)這樣就很漂亮,只用了幾行SQL就取出了我們要的類別