<<前 [TOP] 次>>
今度は買い手がカートに入れた商品を実際に購入できるようにチェックアウト機能を実装します。
まずは「order」モデルを作成し、line_itemsテーブルを更新します。
コマンドプロンプトで「bin」フォルダに移動し、「rails generate scaffold Order name address:text email pay_type:bigint
」と入力してOrderモデルを作成します。
途中「scaffolds.scss」を上書きするか聞いてくるので「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: '支払い方法'
ブラウザの表示を確認してみます。
↓↓クリックして頂けると励みになります。