チェックボックスを使用したカラムの値を一括更新する方法
背景
実務で 商品のクーポンステータスを画面上から切り替えることができるようにする機能を作成することになりました。
その時の実装内容をチェックボックスのチェック状況からカラム(今回でいうとクーポンステータスを管理するカラム)の値を一括で更新する方法として記事にまとめたので、同じような実装をする時の参考にしていただけると幸いです。
完成イメージ(チェックボックスにチェックし、登録ボタンを押下することで、チェックボックスと紐づくカラムの値を更新しています。)
実装
Rails.application.routes.draw do
resources :items do
post "update_coupon_status", on: :collection
end
end
def update_coupon_status
if params[:item].present?
params[:item].each do |item_id, item_attributes|
item = Item.find(item_id)
item.update(coupon_status: item_attributes[:coupon_status])
end
end
redirect_to items_path, notice: 'クーポンステータスが更新されました。'
end
<p style="text-align: center;" id="notice"><%= notice %></p>
<div style="text-align: center;">
<h3>商品一覧</h3>
</div>
<div style="text-align: center;">
<%= form_with url: update_coupon_status_items_path, html: { style: "display: inline-block; text-align: center;" } do |f| %>
<table style="margin: auto; display: block; text-align: center;">
<thead>
<tr>
<th>商品名</th>
<th>クーポンステータス</th>
</tr>
</thead>
<tbody>
<% @items.each do |item| %>
<tr>
<td><%= item.name %></td>
<td>
<%= hidden_field_tag "item[#{item.id}][coupon_status]", "false" %>
<%= check_box_tag "item[#{item.id}][coupon_status]", "true", item.coupon_status == true, { class: "center-checkbox" } %>
</td>
</tr>
<% end %>
</tbody>
</table>
<div style="margin: auto; text-align: center;">
<%= f.submit '登録' %>
</div>
<% end %>
</div>
各ファイルを解説していきます。
config/routes.rb
このファイルは、アプリケーションのルーティングを設定するためのものです。resources :items
は、アイテムに関するRESTfulなルーティングを自動生成します。そして、post "update_coupon_status", on: :collection
は、items
リソースに対してのコレクションアクションとしてupdate_coupon_status
を追加しています。つまり、複数のアイテムをまとめて更新するアクションを定義しています。
app/controllers/items_controller.rb
このファイルは、アプリケーションのコントローラを定義するためのものです。update_coupon_status
メソッドは、クーポンステータスを更新するためのアクションです。送信されたパラメータからアイテムを取得し、それぞれのアイテムのクーポンステータスを更新します。そして、最後に商品一覧ページにリダイレクトします。
app/views/items/index.html.erb
このファイルは、商品一覧ページのビューを定義するためのものです。フォームを使って、アイテムのクーポンステータスを更新するUIを提供しています。各アイテムのクーポンステータスをチェックボックスで選択できるようにし、一括更新のためのフォームを作成しています。フォームが送信されると、update_coupon_status
アクションが呼び出されます。
ちなみにですが、上記の登録ボタンを押下し、サーバ側へデータを送信するときのパラメータは下記のような感じになります。
9: def update_coupon_status
=> 10: binding.pry
11: if params[:item].present?
12: params[:item].each do |item_id, item_attributes|
13: item = Item.find(item_id)
14: item.update(coupon_status: item_attributes[:coupon_status])
15: end
16: end
17:
18: redirect_to items_path, notice: 'クーポンステータスが更新されました。'
19: end
[1] pry(#<ItemsController>)> params
=> #<ActionController::Parameters {"authenticity_token"=>"XXXX", "item"=>{"1"=>{"coupon_status"=>"false"}, "3"=>{"coupon_status"=>"true"}, "4"=>{"coupon_status"=>"true"}, "5"=>{"coupon_status"=>"false"}, "6"=>{"coupon_status"=>"false"}}, "commit"=>"登録", "controller"=>"items", "action"=>"update_coupon_status"} permitted: false>
これにより、Ruby on Railsを使用して簡単に商品のクーポンステータスをチェックボックスで一括更新することができます。
参考
check_box_tag
form_with 配列データを送信
Discussion