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

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

Ruby on Rails 6.0によるWebアプリケーション開発29 チェックアウト機能の実装

<<前  [TOP]  次>>


今度は買い手がカートに入れた商品を実際に購入できるようにチェックアウト機能を実装します。
まずは「order」モデルを作成し、line_itemsテーブルを更新します。
コマンドプロンプトで「bin」フォルダに移動し、「rails generate scaffold Order name address:text email pay_type:bigint」と入力してOrderモデルを作成します。

Orderモデルの作成
Orderモデルの作成


途中「scaffolds.scss」を上書きするか聞いてくるので「n」と入力して上書きしないようにします。
上書きをしない「n」
上書きをしない「n」


次に「add_order_to_line_item.rb」というマイグレーションファイルを作成します。
コマンドプロンプトで「bin」フォルダに移動し、「rails generate migration add_order_to_line_item order:references」と入力します。
マイグレーションの作成
マイグレーションの作成


Orderモデルで「pay_type(支払い方法)」の記述をしておきます。
「C:\Rails6\work\shop\app\models」フォルダにある「order.rb」ファイルを以下のように編集します。


【C:\Rails6\work\shop\app\models\order.rb】

class Order < ApplicationRecord
	enum pay_type: {
		"現金" => 0,
		"クレジットカード" => 1,
		"着払い" => 2
	}
end



作成されたマイグレーションファイルを編集します。
「C:\Rails6\work\shop\db\migrate」フォルダにある「add_order_to_line_item.rb」ファイルを編集します。


【C:\Rails6\work\shop\db\migrate\add_order_to_line_item.rb】

class AddOrderToLineItem < ActiveRecord::Migration[6.0]
  def change
    add_reference :line_items, :order, null: true, foreign_key: true
    change_column :line_items, :cart_id, :bigint, null: true
  end
end



変更したマイグレーションを適用します。
コマンドプロンプトで「bin」フォルダに移動して「rails db:migrate」と入力します。

マイグレーションの適用
マイグレーションの適用


注文受付フォームの作成を行います。
まずはショッピングカートに「注文する」ボタンを追加します。
「C:\Rails6\work\shop\app\views\carts」フォルダにある「_cart.html.erb」ファイルを以下のように編集します。
「<%= button_to '注文する', new_order_path, method: :get, class: "checkout" %>」の記述を追加しました。


【C:\Rails6\work\shop\app\views\carts\_cart.html.erb】

<article>
	<% if notice %>
		<aside id="notice"><%= notice %></aside>
	<% end %>

	<h2>カートの内容</h2>

	<table>
		<tr>
			<th>商品名</th>
			<th>数量</th>
			<th>価格</th>
		</tr>

		<%= render(cart.line_items) %>

		<tfoot>
			<tr>
				<th colspan="2">合計:</th>
				<td class="price"><%= number_to_currency(@cart.total_price) %></td>
			</tr>
		</tfoot>
	</table>

	<div class="action">

	<%= button_to 'カートを空にする', @cart, method: :delete, data: { confirm: '本当によろしいですか?' } %>

	<%= button_to '注文する', new_order_path, method: :get, class: "checkout" %>


	</div>

</article>



次にコントローラに記述を追加します。
カートに商品が入っていることを確認し、カートに何もない場合はユーザをカタログページにリダイレクトして何が起きたかを通知します。
これによりユーザがチェックアウトページのURLを直接指定して結果的に空の注文が作成されるという事態を防止できます。
「C:\Rails6\work\shop\app\controllers」フォルダにある「orders_controller.rb」ファイルを以下のように編集します。


【C:\Rails6\work\shop\app\controllers\orders_controller.rb】

class OrdersController < ApplicationController

  include CurrentCart
  before_action :set_cart, only: [:new, :create]
  before_action :ensure_cart_isnt_empty, only: :new
  before_action :set_order, only: [:show, :edit, :update, :destroy]

  # GET /orders
  # GET /orders.json
  def index
    @orders = Order.all
  end

  # GET /orders/1
  # GET /orders/1.json
  def show
  end

  # GET /orders/new
  def new
    @order = Order.new
  end

  # GET /orders/1/edit
  def edit
  end

  # POST /orders
  # POST /orders.json
  def create
    @order = Order.new(order_params)

    respond_to do |format|
      if @order.save
        format.html { redirect_to @order, notice: 'Order was successfully created.' }
        format.json { render :show, status: :created, location: @order }
      else
        format.html { render :new }
        format.json { render json: @order.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /orders/1
  # PATCH/PUT /orders/1.json
  def update
    respond_to do |format|
      if @order.update(order_params)
        format.html { redirect_to @order, notice: 'Order was successfully updated.' }
        format.json { render :show, status: :ok, location: @order }
      else
        format.html { render :edit }
        format.json { render json: @order.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /orders/1
  # DELETE /orders/1.json
  def destroy
    @order.destroy
    respond_to do |format|
      format.html { redirect_to orders_url, notice: 'Order was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_order
      @order = Order.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def order_params
      params.require(:order).permit(:name, :address, :email, :pay_type)
    end

    def ensure_cart_isnt_empty
	if @cart.line_items.empty?
		redirect_to market_index_url, notice: 'カートは空です。'
	end
    end

end



これで「注文する」ボタンを押すと注文画面に移動できるようになりました。

注文するボタンを押す
注文するボタンを押す


カートが空の状態で「http://localhost:3000/orders/new?」アドレスにアクセスすると「カートが空です」というフラッシュメッセージが表示されて商品カタログページにリダイレクトします。
商品カタログにリダイレクト
商品カタログにリダイレクト


ビューの変更をします。
まずは「C:\Rails6\work\shop\app\views\orders」フォルダにある「new.html.erb」ファイルの変更です。


【C:\Rails6\work\shop\app\views\orders\new.html.erb】

<section class="shop_form">
	<h1>お客様情報を入力してください。</h1>
	<%= render 'form', order: @order %>
</section>



同じフォルダにある「_form.html.erb」ファイルの編集です。


【C:\Rails6\work\shop\app\views\orders\_form.html.erb】

<%= form_with(model: order, local: true) do |form| %>
  <% if order.errors.any? %>
    <div id="error_explanation2">
      <h2><%= pluralize(order.errors.count, "error") %> この注文の保存ができません。</h2>

      <ul>
        <% order.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :氏名 %>
    <%= form.text_field :name, size: 40 %>
  </div>

  <div class="field">
    <%= form.label :住所 %>
    <%= form.text_area :address, rows: 3, cols: 40 %>
  </div>

  <div class="field">
    <%= form.label :email %>
    <%= form.text_field :email, size: 40 %>
  </div>

  <div class="field">
    <%= form.label :支払い方法 %>
    <%= form.select :pay_type, Order.pay_types.keys, prompt: '支払い方法を選択してください。' %>
  </div>
<br>
  <div class="actions">
    <%= form.submit '注文を確定する' %>
  </div>
<% end %>



CSSファイル「application.css」に記述を追加します。


【C:\Rails6\work\shop\app\assets\stylesheets\application.css】

.shop_form {
	padding: 0 1em;
}

input[type="submit"] {
	font-weight: bold;
	margin-top: 1em;
}

#error_explanation2 {
  width: 450px;
  padding: 7px 7px 0;
  margin-bottom: 20px;

}

#error_explanation2 h2 {
    text-align: left;
    font-weight: bold;
    padding: 5px 5px 5px 15px;
    font-size: 12px;
    margin: -7px -7px 0;
    background-color: #20b2aa;
    color: #fff;
}



これでフォームを使う準備は完了です。

ブラウザの表示
ブラウザの表示


Orderモデルに検証コードを追加します。


【C:\Rails6\work\shop\app\models\order.rb】

class Order < ApplicationRecord
	enum pay_type: {
		"現金" => 0,
		"クレジットカード" => 1,
		"着払い" => 2
	}

	validates :name, :address, :email, presence: true
	validates :pay_type, inclusion: pay_types.keys

end



「ja.yml」ファイルにorderテーブルのフィールドを追加して日本語化します。


【C:\Rails6\work\shop\config\locales\ja.yml】

ja:
 activerecord:
  attributes:
   good:
     title: '商品名'
     description: '詳細'
     image_url: '画像URL'
     price: '価格'

ja:
 activerecord:
  attributes:
     order:
       name: '氏名'
       address: '住所'
       email: 'email'
       pay_type: '支払い方法'



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

バリデーション
バリデーション


<<前  [TOP]  次>>