A Day In The Life

とあるプログラマの備忘録

Railsで複数行更新

表題の件ですがいろいろやり方がありますね。

RailsによるアジャイルWebアプリケーション開発にも載ってるやりかただとまずViewで

<% form_tag :action => 'update' do %>
 <% @order_details.each do |@order_detail| %>
  <%= @order_detail.product.name %>
  <%= number_to_currency(@order_detail.product.price, :unit => "&#165;", :precision => 0) %>
  <%= @order_detail.qty %>
  <%= number_to_currency(@order_detail.subtotal, :unit => "&#165;", :precision => 0) %>
  <%= check_box 'order_detail[]', :check %>
 <% end %>
<% end %>

として、ActionController

def update
 OrderDetail.update(params[:order_detail].keys, params[:order_detail].values)
 details = session[:order].order_details.reload
 redirect_to :action => 'hoge'
end

とするとうまくいきます。

Viewで"order_detail[]"と書くのがポイントです。
他にもやり方があるようで、今日keisen氏にそのやり方を教えてもらいました。

まずViewは

<% form_tag :action => 'delete' do %>
 <% @order_details.each do |@order_detail| %>
  <%= @order_detail.product.name %>
  <%= number_to_currency(@order_detail.product.price, :unit => "&#165;", :precision => 0) %>
  <%= @order_detail.qty %>
  <%= number_to_currency(@order_detail.subtotal, :unit => "&#165;", :precision => 0) %>
  <%= check_box_tag "detail[#{@detail.id.to_s}]", :check %>
 <% end %>
<% end %>

このようにしてActionController

def delete
 if params[:order_detail].nil?
  flash[:error] = '更新対象が選択されていません。'
 else
  params[:order_detail].each do |id, attr|
   OrderDetail.destroy(id.to_i)
  end
   flash[:info] = '正常に更新されました。'
 end
 redirect_to :action => 'hoge'
end

なんてできます。

Viewでcheck_box_tagを使いcomment[#{@comment.id.to_s}]と書くのがポイントです。

どちらも微妙に癖がありますので注意が必要です。

慣れればいいのでしょうけど、できればModelオブジェクトの入ったArrayがわたってきて欲しいです。