<<前 [TOP] 次>>
カートを空にする機能を実装するにはカートにリンクを追加し、カートコントローラの「destroy()」メソッドを修正してセッションをクリーンにしなければなりません。
まずは「button_to()」メソッドを使ってページにボタンを配置します。
「C:\Rails6\work\shop\app\views\carts」フォルダにある「show.html.erb」ファイルを以下のように編集します。
【C:\Rails6\work\shop\app\views\carts\show.html.erb】
<% if notice %> <aside id="notice"><%= notice %></aside> <% end %> <h2>カートの内容</h2> <ul> <% @cart.line_items.each do |item| %> <li><%= item.quantity %> × <%= item.good.title %></li> <% end %> </ul> <%= button_to 'カートを空にする', @cart, method: :delete, data: { confirm: '本当によろしいですか?' } %>
コントローラでは「destroy()」メソッドを修正します。
ユーザの同意を得てカートを削除し、セッションからカートを削除したうえで通知メッセージ付きのインデックスページにリダイレクトするようにします。
「C:\Rails6\work\shop\app\controllers」フォルダにある「carts_controller.rb」ファイルを以下のように編集します。
変更した部分は「destroy()」メソッドのみです。
【C:\Rails6\work\shop\app\controllers\carts_controller.rb】
class CartsController < ApplicationController before_action :set_cart, only: [:show, :edit, :update, :destroy] rescue_from ActiveRecord::RecordNotFound, with: :invalid_cart # GET /carts # GET /carts.json def index @carts = Cart.all end # GET /carts/1 # GET /carts/1.json def show end # GET /carts/new def new @cart = Cart.new end # GET /carts/1/edit def edit end # POST /carts # POST /carts.json def create @cart = Cart.new(cart_params) respond_to do |format| if @cart.save format.html { redirect_to @cart, notice: 'カートを作成しました。' } format.json { render :show, status: :created, location: @cart } else format.html { render :new } format.json { render json: @cart.errors, status: :unprocessable_entity } end end end # PATCH/PUT /carts/1 # PATCH/PUT /carts/1.json def update respond_to do |format| if @cart.update(cart_params) format.html { redirect_to @cart, notice: 'カートが更新されました。' } format.json { render :show, status: :ok, location: @cart } else format.html { render :edit } format.json { render json: @cart.errors, status: :unprocessable_entity } end end end # DELETE /carts/1 # DELETE /carts/1.json def destroy @cart.destroy if @cart.id == session[:cart_id] session[:cart_id] = nil respond_to do |format| format.html { redirect_to market_index_url, notice: 'カートが空になりました。' } format.json { head :no_content } end end private # Use callbacks to share common setup or constraints between actions. def set_cart @cart = Cart.find(params[:id]) end # Only allow a list of trusted parameters through. def cart_params params.fetch(:cart, {}) end def invalid_cart logger.error "無効なカート(#{params[:id]})にアクセスしようとしました。" redirect_to market_index_url, notice: '無効なカートです。' end end
これで「カートを空にする」ボタンを押すとカートの内容が破棄されてカタログページに戻ります。
そこには「カートが空になりました。」というメッセージが表示されます。
動作の確認が取れたので、商品をカートに入れた時に出る「品目が作成されました。」という不要なメッセージが表示されないようにします。
これは「line_items_controller.rb」の「create()」メソッドを以下のように編集するだけです。
「notice: '品目が作成されました。'」の部分を削除しています。
【C:\Rails6\work\shop\app\controllers\line_items_controller.rb】
class LineItemsController < ApplicationController include CurrentCart before_action :set_cart, only: [:create] before_action :set_line_item, only: [:show, :edit, :update, :destroy] # GET /line_items # GET /line_items.json def index @line_items = LineItem.all end # GET /line_items/1 # GET /line_items/1.json def show end # GET /line_items/new def new @line_item = LineItem.new end # GET /line_items/1/edit def edit end # POST /line_items # POST /line_items.json def create good = Good.find(params[:good_id]) @line_item = @cart.add_good(good) respond_to do |format| if @line_item.save format.html { redirect_to @line_item.cart } format.json { render :show, status: :created, location: @line_item } else format.html { render :new } format.json { render json: @line_item.errors, status: :unprocessable_entity } end end end # PATCH/PUT /line_items/1 # PATCH/PUT /line_items/1.json def update respond_to do |format| if @line_item.update(line_item_params) format.html { redirect_to @line_item, notice: '品目が更新されました。' } format.json { render :show, status: :ok, location: @line_item } else format.html { render :edit } format.json { render json: @line_item.errors, status: :unprocessable_entity } end end end # DELETE /line_items/1 # DELETE /line_items/1.json def destroy @line_item.destroy respond_to do |format| format.html { redirect_to line_items_url, notice: '品目を破棄しました。' } format.json { head :no_content } end end private # Use callbacks to share common setup or constraints between actions. def set_line_item @line_item = LineItem.find(params[:id]) end # Only allow a list of trusted parameters through. def line_item_params params.require(:line_item).permit(:good_id, :cart_id) end end
最後にカートの表示を整えます。
まずは「C:\Rails6\work\shop\app\views\carts」フォルダにある「show.html.erb」ファイルの編集です。
【C:\Rails6\work\shop\app\views\carts\show.html.erb】
<% if notice %> <aside id="notice"><%= notice %></aside> <% end %> <h2>カートの内容</h2> <table> <tr><th>商品名</th><th>数量</th><th>金額</th></tr> <% @cart.line_items.each do |line_item| %> <tr> <td><%= line_item.good.title %></td> <td class="quantity"><%= line_item.quantity %></td> <td class="price"><%= number_to_currency(line_item.total_price) %></td> </tr> <% end %> <tfoot> <tr> <th colspan="2">合計:</th> <td class="price"><%= number_to_currency(@cart.total_price) %></td> </tr> </tfoot> </table> <%= button_to 'カートを空にする', @cart, method: :delete, data: { confirm: '本当によろしいですか?' } %>
ここで利用した「total_price()」メソッドを「line_itemモデル」に記述します。
「C:\Rails6\work\shop\app\models」フォルダにある「line_item.rb」ファイルを以下のように編集します。
【C:\Rails6\work\shop\app\models\line_item.rb】
class LineItem < ApplicationRecord belongs_to :good belongs_to :cart def total_price good.price * quantity end end
同じく「total_price()」メソッドを「cartモデル」にも記述します。
「C:\Rails6\work\shop\app\models」フォルダにある「cart.rb」ファイルを以下のように編集します。
【C:\Rails6\work\shop\app\models\cart.rb】
class Cart < ApplicationRecord has_many :line_items, dependent: :destroy def add_good(good) current_item = line_items.find_by(good_id: good.id) if current_item current_item.quantity += 1 else current_item = line_items.build(good_id: good.id) end current_item end def total_price line_items.to_a.sum {|item| item.total_price } end end
最後にスタイルシートを編集します。
「C:\Rails6\work\shop\app\assets\stylesheets」フォルダにある「carts.scss」ファイルを以下のように編集します。
【C:\Rails6\work\shop\app\assets\stylesheets\carts.scss】
// Place all the styles related to the carts controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: https://sass-lang.com/ .carts { td.price { font-weight: bold; text-align: right; } tfoot { th, th.price { padding-top: 1em; } th { text-align: right; } } input[type="submit"] { background-color: #ffd700; border-radius: 0.454em; border: solid thin #696969; color: black; font-size: 1em; padding: 0.354em 2em; margin-top: 1em; } input[type="submit"]:hover { background-color: #f5deb3; } }
ブラウザの表示を確認します。
↓↓クリックして頂けると励みになります。