一括でレコードをアレコレするやり方。なお割と力技。
それぞれやりたい事は以下。
①カートを空にする =Userに紐づくCartレコードを全削除
②カートに入ってる商品を注文する =複数のCartレコードを使って複数のOrderProductレコードを作成する。
③注文情報と注文商品情報をまとめて変更する =親要素と子要素を一括でupdateをかける
前提ーー
Cartモデル、OrderProductモデルには以下のカラムがある
・product_name
・quantity
・price
・order_id(OrderProductのみ)
・status(OrderProductのみ)
Orderモデル
・user_id
・status
User<Cart,Order
Order<OrderProduct が1対他の関係。
#①カートを空にする
delete_allメソッドを使う。これを使うとUserに紐づいたCartレコードを全て削除できる。
似たようなものでDestroy_allがあるけどこちらはUserに紐づいた全てのレコードが削除されるらしい。つまりこの前提だとOrderレコードまで消えるっぽい。
actionはdestroyを個別削除に使っていたので新しく作成する。
delete 'public/carts' => "public/carts#delete_all"
def delete_all
@user = current_user
@user.carts.delete_all
end
<%= link_to "カートを空にする", public_carts_path, method: :delete %>
#②カートに入ってる商品を注文する
ここでやりたい挙動は
1、Orderレコードを新しく作成
2、そのIDを使ってOrderProductを作成
def create
@user = current_user
@order = Order.new
@order.user_id = current_user.id
@order.save!
@user.carts.each do |cart|
order_product = OrderProduct.new
order_product.order_id = @order.id
order_product.quantity = cart.quantity
order_product.product_name = cart.product_name
order_product.total = cart.product.price
order_product.save
end
end
もっと大量のデータを扱う場合は別のやり方があると思う。
.eachで回すのはナンセンスだけどやり方調べる時間がなかった。
#③注文情報と注文商品情報をまとめて変更する
これが一番難しかった。何なら今でもいまいち理解できてない。
def update
@order = Order.find(params[:id])
@order.update(order_params)
end
private
def order_params
params.require(:order).permit(:user_id,:status, order_products_attributes: [:id, :status, :_destroy])
end
accepts_nested_attributes_for :order_products
<%= form_for [@order] do |f| %>
<%= f.select :status, ['入金待ち', '入金確認', '製作中', '発送準備中', '発送済み'], {}, class: "dropdown" %>
<%= f.fields_for :order_products do |order_product| %>
<%= order_product.select :status, ['着手不可', '製作待ち', '製作中', '製作完了'] %>
<% end %>
<%= f.submit "更新" %>
<% end %>
order_products_attributes: [:id, :status, :_destroy]
まず一番にcontrollerのこいつ。order_paramsに入りこんでるこいつ。attributesを使うならこれとモデルへの記述が必要でidと_destroyは形式として突っ込むらしい。何故かはよくわからない。
それからfields_for。これをform_forの中にとりあえず入れると、そこで子要素を編集できる。fields_forをかけると子要素のレコードを繰り返し持ってこれるので.eachはいらない。ただし