学生向けプログラミング入門

学生向けにプログラミングを解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails

Ruby on Rails 6.0によるWebアプリケーション開発23 カートの仕上げ

<<前  [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 %> &times; <%= 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;
	}

}



ブラウザの表示を確認します。

カートの表示
カートの表示


<<前  [TOP]  次>>