3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

6 Railsを用いた注文機能の作成方法

Last updated at Posted at 2022-11-09

注文機能の流れ

1 注文情報を入力
2 注文情報を確認
3 注文機能
4 注文完了画面

前提条件

orderモデル , order_detailモデル , カラム,アソシエーションをこのように定義しました

order.rb

class Order < ApplicationRecord

  belongs_to :end_user
  has_many :order_details

  #enumによって、数字に意味を持たせることができる
  #今回の場合、0がcredit_card 1がtransferという意味。

  #支払い方法
  enum payment_method: {credit_card: 0, transfer: 1}

 #注文ステータス
  enum order_status: {wait_payment: 0, confirm_payment: 1, making: 2, preparing_ship: 3, finish_prepare: 4}
end

order_detail.rb

class OrderDetail < ApplicationRecord

    belongs_to :order
    belongs_to :item

 #製作ステータス
    enum manufacture_status:

        {

          impossible_manufacture:0,
          waiting_manufacture:1,
          manufacturing:2,
          finish:3

        }
end

schema.rb

 create_table "order_details", force: :cascade do |t|
    t.integer "item_id"
    t.integer "order_id"
    t.integer "manufacture_status"
    t.integer "price"
    t.integer "number"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "orders", force: :cascade do |t|
    t.integer "end_user_id"
    t.integer "payment_method"
    t.integer "postage"
    t.integer "amount_requested"
    t.integer "order_status"
    t.string "postal_code"
    t.string "address"
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

1 enumを実装する

enumとは数字に意味を持たせることが出来る。
今回だと、

0 → クレジットカード
1 → 銀行振り込み

という意味を持たせることができる

(1) enum_helpの導入(enumを実装する)
gem "enum_help"
(2) enumを定義する

order.rb

支払い方法
enum payment_method: {credit_card: 0, transfer: 1}

注文ステータス
enum order_status: {wait_payment: 0, confirm_payment: 1, making: 2, preparing_ship: 3, finish_prepare: 4}

order_detail.rb

製作ステータス
  enum manufacture_status:
        {
          impossible_manufacture:0,
          waiting_manufacture:1,
          manufacturing:2,
          finish:3
        }

2 日本語化させる

Railsアプリケーションを日本語化させるために国際化i18nを用いる

(1)Railsアプリケーションのデフォルトの言語を日本語にする

config/application.rb

  config.i18n.default_locale = :ja
  config.i18n.load_path += Dir[Rails.root.join('config/locales/*.yml').to_s]
(2)ymlファイルを作成する
ja:
  enums:
    order:
      order_status:
        wait_payment: '入金待ち'
        confirm_payment: '入金確認'
        making: '製作中'
        preparing_ship: '発送準備中'
        finish_prepare: '発送済み'
      payment_method:
        credit_card: "クレジットカード"
        transfer: '銀行振込'
    order_detail:
      manufacture_status:
        impossible_manufacture: '着手不可'
        waiting_manufacture: '製作待ち'
        manufacturing: '製作中'
        finish: '製作完了'

後は、i18nをつけることで日本語化出来る。

不具合発生!!:scream:

order_status , payment_method , order_detailのうちどれかが日本語化されない

原因: jaから始まる1つの階層にまとめる必要がある。
↓のように書いてはいけない。↑のように書く

ja:  # 日本語の設定を行う
   enums:  # enumの設定を行う
     order: # モデル名(Orderモデルに対して)
       payment_method:  # カラム名(payment_methodカラムに対して)
         credit_card: 'クレジットカード'
         transfer: '銀行振込'


 ja:
   enums:
     order:
       order_status:
         wait_payment: '入金待ち'
         confirm_payment: '入金確認'
         making: '製作中'
         preparing_ship: '発送準備中'
         finish_prepare: '発送済み'

 ja:
   enums:
     order_detail:
       manufacture_status:
         impossible_manufacture: '着手不可'
         waiting_manufacture: '製作待ち'
         manufacturing: '製作中'
         finish: '製作完了'

3 注文情報入力画面を作成する

(1)コントローラにアクションを定義する

public/orders_controller.rb

class Public::OrdersController < ApplicationController
  def new
  
  フォームを作成するのに使う
    @order = Order.new

  注文情報入力画面に表示させるのに使う
    @addresses = Address.all

  end
end
(2)ビューファイルを作成する
<%= form_with model: @order, url: '/orders/confirm' , local: true do |f| %>
  <h4>支払い方法</h4>
  <%= f.radio_button :payment_method, "credit_card" %>
  <%= f.label :payment_method, "クレジットカード" %>
  <%= f.radio_button :payment_method, "transfer" %>
  <%= f.label :payment_method, "銀行振込" %>

  <h3>お届け先</h3>

  

  <p><%= f.radio_button :select_address, 0 %>自身の住所</p>
     <%= current_end_user.full_address%>
 
 登録済み住所 
  <p> <%= f.radio_button :select_address, 1 %>登録済み住所</p>
 <p><%= f.select :address_id , options_from_collection_for_select(@addresses, :id, :full_address) %></p>

 新しいお届け先
  <p> <%= f.radio_button :select_address, 2 %>新しいお届け先</p>

  <table>
    <tr>
      <td>郵便番号</td>
      <td> <%= f.text_field :postal_code %></td>
    </tr>
    <tr>
      <td>住所</td>
      <td><%= f.text_field :address %></td>
    </tr>
    <tr>
      <td>宛名</td>
      <td><%= f.text_field :name %></td>
    </tr>
  </table>

  <%= f.submit "確認画面へ進む" %>

<% end %>

ポイント

1

<%= f.radio_button :payment_method, "credit_card" %>

ラジオボタンを作成する。
payment_methodというカラムにcredit_cardという値を代入する

2

 f.radio_button :select_address

select_addressはデータベースに保存するのではなく、
orders_controller.rbの条件分岐で使うために作った一時的なカラム

3

<%= f.select :address_id , options_from_collection_for_select(@addresses, :id, :full_address) %>

セレクトボックスを作成している。

address_id: 保存したいカラム
@ address: 表示したい住所
id: address_idに保存したい@ addressのid

full_address: 郵便番号 住所 宛名を表示するメソッド

address.rb

 def full_address
    '〒' + postal_code + ' ' + address + ' ' + name
  end

4 注文情報確認画面を作成する

(1)コントローラにアクションを定義する

orders_controller.rb


 def confirm
     @order = Order.new(order_params)
    if params[:order][:select_address] == "0"
      @order.postal_code = current_end_user.postal_code
      @order.address = current_end_user.address
      @order.name = current_end_user.first_name + current_end_user.last_name
    elsif params[:order][:select_address] == "1"
       @address = Address.find(params[:order][:address_id])
       @order.postal_code = @address.postal_code
       @order.address = @address.address
       @order.name = @address.name
    elsif params[:order][:select_address] == "2"
      @order.end_user_id = current_end_user.id
    end
      @cart_items = current_end_user.cart_items
      @order_new = Order.new
      render :confirm
  end

 private

  def order_params
    params.require(:order).permit(:payment_method, :postal_code, :address, :name, :postage, :amount_requested, :end_user_id , :order_status)
  end

この時のパラメータは

"order"=><ActionController::Parameters {"payment_method"=>"transfer", "select_address"=>"0", "postal_code"=>"", "address"=>"", "name"=>""} permitted: false>, "commit"=>"確認画面へ進む", "controller"=>"public/orders", "action"=>"confirm"} permitted: false>

order_params

 <ActionController::Parameters {"payment_method"=>"transfer", "postal_code"=>"", "address"=>"", "name"=>""} permitted: true>

ポイント

select_addressの値によって、不足している情報が変わっているので
if文で条件分岐させ、不足しているカラムに値を代入する。

  if params[:order][:select_address] == "0"

この時のparams

"order"=><ActionController::Parameters {"payment_method"=>"transfer", "select_address"=>"0", "postal_code"=>"", "address"=>"", "name"=>""} permitted: false>, "commit"=>"確認画面へ進む", "controller"=>"public/orders", "action"=>"confirm"} permitted: false
postal_code , address , nameが空 => 入れる必要がある。

if文の中に↓を記述

@order.postal_code = current_end_user.postal_code
@order.address = current_end_user.address
@order.name = current_end_user.first_name + current_end_user.last_name
elsif params[:order][:select_address] == "1"

この時のparams

"order"=><ActionController::Parameters {"payment_method"=>"transfer", "select_address"=>"1", "address_id"=>"1", "postal_code"=>"", "address"=>"", "name"=>""} permitted: false>, "commit"=>"確認 画面へ進む", "controller"=>"public/orders", "action"=>"confirm"} permitted: false>

postal_code , address, nameが空 => 入れる必要がある。

セレクトボックスで取得したaddress_idを用いて選択したaddressを代入
 @address = Address.find(params[:order][:address_id])
 
 @order.postal_code = @address.postal_code
 @order.address = @address.address
 @order.name = @address.name
 elsif params[:order][:select_address] == "2"

この時のparams

order"=><ActionController::Parameters {"payment_method"=>"transfer", "address_id"=>"1", "select_address"=>"2", "postal_code"=>"123456", "address"=>"123456", "name"=>"田中正造"} permitted: false>, "commit"=>"確認画面へ進む", "controller"=>"public/orders", "action"=>"confirm"} permitted: false>
end_user_id: nil,
 payment_method: "transfer",
 postage: nil,
 amount_requested: nil,
 order_status: nil,
 postal_code: "123456",
 address: "123456",
 name: "田中正造",
 created_at: nil,
 updated_at: nil>

この時↑の@ order
end_user_idがnillより、入れる必要がある。

@order.end_user_id = current_end_user.id
残りの記述
カート内商品の情報を取得
@cart_items = current_end_user.cart_items

hidden_fieldを作るのに使う
@order_new = Order.new

注文確認画面を表示させる
render :confirm
(2)ビューファイルの作成

confirm.html.erb

<table>
  <tr>
    <td>商品名</td>
    <td>単価</td>
    <td>数量</td>
    <td>小計</td>
  </tr>

  <% @sum = 0 %>

  <% @cart_items.each do |cart_item| %>

    <tr>
      <td>
        <%= attachment_image_tag cart_item.item, :image, :fill, 300, 300, format: 'jpeg' %>
        <%= cart_item.item.name %>
      </td>
      <td><%= cart_item.item.with_tax_price %></td>
      <td><%= cart_item.amount %></td>]
      <% @sum += cart_item.subtotal %>
      <td><%= @sum %></td>
    </tr>
  <% end %>
</table>

<table>
  <tr>
    <td>送料</td>
    <td>800</td>
  </tr>
  <tr>
    <td>商品合計</td>
    <td><%= @sum %></td>
  </tr>
  <tr>
    <td>請求金額</td>
    <td><%= @sum + 800 %></td>
  </tr>
</table>

<table>
  <tr>
    <th>支払い方法</th>
    <td><%= @order.payment_method_i18n%></td>
  </tr>
  <tr>
    <th>お届け先</th>
    <td>
      <%= @order.address %>
      <%= @order.name %>
    </td>
  </tr>
</table>

<%= form_with model: @order_new , url: "/orders" , local:true do |f| %>
  <%= f.hidden_field :end_user_id, value: current_end_user.id %>
  <%= f.hidden_field :payment_method, value:  @order.payment_method %>
  <%= f.hidden_field :postage, value: 800 %>
  <%= f.hidden_field :postal_code, value: @order.postal_code %>
  <%= f.hidden_field :amount_requested, value: @sum + 800%>
  <%= f.hidden_field :address, value: @order.address%>
  <%= f.hidden_field :name, value: @order.name %>
  <%= f.hidden_field :order_status, value: "wait_payment"%>
  <%= f.submit "注文を確定する" %>
<% end %>

ポイント

1 小計を表示させる方法
1 <% @sum = 0 %> :@sum = 0 を定義する
2 <% @sum += cart_item.subtotal %> :@sumにcart_item.subtotalを足す
3 <%= @sum %> :表示する
2 hidden_fieldについて

hidden_fieldを用いることでブラウザにフォームを表示せずに
データを送ることが出来る。

<%= f.hidden_field :保存したい値が入るカラム名, value: 値 %>

schema.rbより

 create_table "orders", force: :cascade do |t|
    t.integer "end_user_id"
    t.integer "payment_method"
    t.integer "postage"
    t.integer "amount_requested"
    t.integer "order_status"
    t.string "postal_code"
    t.string "address"
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

これらの値を送るためのhidden_fieldを作成する必要がある。
よって、↓のように記述すれば良い

<%= form_with model: @order_new , url: "/orders" , local:true do |f| %>
  <%= f.hidden_field :end_user_id, value: current_end_user.id %>
  <%= f.hidden_field :payment_method, value:  @order.payment_method %>
  <%= f.hidden_field :postage, value: 800 %>
  <%= f.hidden_field :postal_code, value: @order.postal_code %>
  <%= f.hidden_field :amount_requested, value: @sum + 800%>
  <%= f.hidden_field :address, value: @order.address%>
  <%= f.hidden_field :name, value: @order.name %>
  <%= f.hidden_field :order_status, value: "wait_payment"%>
  <%= f.submit "注文を確定する" %>
<% end %>

エラー発生!!:scream:

ビューに@order.address @order.name が表示されない

if params[:order][:select_address] == 0

      binding.pry

      @order.postal_code = current_end_user.postal_code
      @order.address = current_end_user.address
      @order.name = current_end_user.first_name + current_end_user.last_name

    elsif params[:order][:select_address] == 1

binding.pryを入れても処理が止まらない
=>if文の処理が実行されていない
=>if文がfalse

=>if文の条件式が間違えているのではないか?:expressionless:
params[:order][:select_address]の値を確認してみると、、、、

pry(#<Public::OrdersController>)> params[:order][:select_address]
=> "0"

値が数字の0じゃなくて文字の0になっているだと!?

if文を下記のように修正し解決!

if params[:order][:select_address] == "0"

4 注文機能を作成する

(1)hidden_fieldから送られたデータを保存する。
コントローラにアクションを定義する
 def create
    order = Order.new(order_params)
    order.save
    @cart_items = current_end_user.cart_items.all
    
    @cart_items.each do |cart_item|
      @order_details = OrderDetail.new
      @order_details.order_id = order.id
      @order_details.item_id = cart_item.item.id
      @order_details.price = cart_item.item.price_excluding_tax
      @order_details.number = cart_item.amount
      @order_details.manufacture_status = 0
      @order_details.save!
    end
    
    CartItem.destroy_all
    redirect_to orders_completed_path

  end

private
  def order_params
    params.require(:order).permit(:payment_method, :postal_code, :address, :name, :postage, :amount_requested, :end_user_id , :order_status)
  end

 def cartitem_nill
     cart_items = current_end_user.cart_items
     if cart_items.blank?
      
   注文完了画面に遷移させる
      redirect_to cart_items_path
     end
  end


ポイント

1 空のインスタンスに情報を入れる
 order = Order.new(order_params)

order_params

order_params
=> <ActionController::Parameters {"payment_method"=>"transfer", "postal_code"=>"123456", "address"=>"123456", "name"=>"tt", "postage"=>"800", "amount_requested"=>"4100", "end_user_id"=>"1", "order_status"=>"wait_payment"} permitted: true>

Order.new

 id: nil,
 end_user_id: nil,
 payment_method: nil,
 postage: nil,
 amount_requested: nil,
 order_status: nil,
 postal_code: nil,
 address: nil,
 name: nil,
 created_at: nil,
 updated_at: nil>

Order.new(order_params)

 end_user_id: 1,
 payment_method: "transfer",
 postage: 800,
 amount_requested: 4100,
 order_status: "wait_payment",
 postal_code: "123456",
 address: "123456",
 name: "tt",
(2) order_detailsテーブルにデータを保存する。()

order_detailsテーブルに必要なデータは、、、
schema.rb

create_table "order_details", force: :cascade do |t|
    t.integer "item_id"
    t.integer "order_id"
    t.integer "manufacture_status"
    t.integer "price"
    t.integer "number"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

よって、これらのカラムに値を保存する必要がある 

 @cart_items = current_end_user.cart_items.all
    
    @cart_items.each do |cart_item|
      @order_details = OrderDetail.new
      @order_details.order_id = order.id
      @order_details.item_id = cart_item.item.id
      @order_details.price = cart_item.item.price_excluding_tax
      @order_details.number = cart_item.amount
      @order_details.manufacture_status = 0
      @order_details.save!
    end

Orderモデルの情報を利用
order_id: orderのid

Itemモデルの情報を利用
item_id: itemのid
price: itemのprice_excluding_tax

CartItemモデルの情報を利用
number: cart_item.amount

=> end_userとアソシエーションを用いて、これらの情報を入れていけば良い

3 カート内商品の情報を全て削除する
CartItem.destroy_all
4 カートが空なら注文入力画面に進むことや、注文の作成処理をしない
before_action :cartitem_nill,   only: [:new, :create]
         ,
         ,
         ,
def cartitem_nill
     cart_items = current_end_user.cart_items
     if cart_items.blank?
      redirect_to cart_items_path
     end
  end

※ CartItem.blankといったモデルに直接メソッドを使えなかった。

エラー発生!!:scream:

2種類以上の商品を注文できない!?

      @order_details = OrderDetail.new
      @order_details.order_id = order.id
 
@cart_items.each do |cart_item|
      @order_details.item_id = cart_item.item.id
      @order_details.price = cart_item.item.price_excluding_tax
      @order_details.number = cart_item.amount
      @order_details.manufacture_status = 0
      @order_details.save!
end

ターミナルを見てみると、、、

OrderDetail Create (2.6ms)  INSERT INTO "order_details" ("item_id", "order_id", "manufacture_status", "price", "number", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?)  [["item_id", 1], ["order_id", 3], ["manufacture_status", 0], ["price", 1000], ["number", 1], ["created_at", "2022-03-03 15:55:21.069568"], ["updated_at", "2022-03-03 15:55:21.069568"]]
   app/controllers/public/orders_controller.rb:117
   (5.2ms)  commit transaction
   app/controllers/public/orders_controller.rb:117
  Item Load (0.1ms)  SELECT  "items".* FROM "items" WHERE "items"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
   app/controllers/public/orders_controller.rb:110
   (0.0ms)  begin transaction
   app/controllers/public/orders_controller.rb:117
  CACHE Item Load (0.0ms)  SELECT  "items".* FROM "items" WHERE "items"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
   app/controllers/public/orders_controller.rb:117
  OrderDetail Update (0.2ms)  UPDATE "order_details" SET "item_id" = ?, "updated_at" = ? WHERE "order_details"."id" = ?  [["item_id", 2], ["updated_at", "2022-03-03 15:55:21.082964"], ["id", 4]]

OrderDetail Updateより、item_idが上書きされてる:disappointed:

原因:
@ order_details = OrderDetail.newは、商品の種類分必要 (カラムには1つしか値が入らない =>item_idは1種類=>入る商品は1種類)
each文を使って、カート内の商品の種類分@ order_details = OrderDetail.newを作る必要がある。
  @cart_items.each do |cart_item|
      @order_details = OrderDetail.new
      @order_details.order_id = order.id
      @order_details.item_id = cart_item.item.id
      @order_details.price = cart_item.item.price_excluding_tax
      @order_details.number = cart_item.amount
      @order_details.manufacture_status = 0
      @order_details.save!
    end

この時ターミナルは、、、

 OrderDetail Create (1.4ms)  INSERT INTO "order_details" ("item_id", "order_id", "manufacture_status", "price", "number", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?)  [["item_id", 2], ["order_id", 4], ["manufacture_status", 0], ["price", 1000], ["number", 1], ["created_at", "2022-03-03 16:09:43.528693"], ["updated_at", "2022-03-03 16:09:43.528693"]]
   app/controllers/public/orders_controller.rb:115
   (6.2ms)  commit transaction
   app/controllers/public/orders_controller.rb:115
  Item Load (0.1ms)  SELECT  "items".* FROM "items" WHERE "items"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   app/controllers/public/orders_controller.rb:108
   (0.0ms)  begin transaction
   app/controllers/public/orders_controller.rb:115
  Order Load (0.1ms)  SELECT  "orders".* FROM "orders" WHERE "orders"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
   app/controllers/public/orders_controller.rb:115
  CACHE Item Load (0.0ms)  SELECT  "items".* FROM "items" WHERE "items"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   app/controllers/public/orders_controller.rb:115
  OrderDetail Create (1.8ms)  INSERT INTO "order_details" ("item_id", "order_id", "manufacture_status", "price", "number", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?)  [["item_id", 1], ["order_id", 4], ["manufacture_status", 0], ["price", 1000], ["number", 1], ["created_at", "2022-03-03 16:09:43.544142"], ["updated_at", "2022-03-03 16:09:43.544142"]]

OrderDetail.Createが2つあるので2種類の商品を保存できるようになった

エラー発生!!:scream:

OrderDetailがcreateできず、rollbacktransactionが起こる

ターミナル

CACHE Item Load (0.0ms)  SELECT  "items".* FROM "items" WHERE "items"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   app/controllers/public/orders_controller.rb:115
   (0.1ms)  rollback transaction
   app/controllers/public/orders_controller.rb:115

1 原因の特定:

 @order_details.saveを
 @order_details.save!にする

エラー画面が表示される
3.PNG

エラーメッセージを日本語化する
ja.ymlの記述を変更する(enumの記述は一旦、消す)

ja:
  activerecord:
  errors:
    messages:
      record_invalid: "バリデーションに失敗しました: %{errors}"

本来のエラーメッセージが表示される
1.PNG

Createの際のエラーUser translation missing: ja.activerecord.errors.models.company.attributes.user.required

より、order_detail.rbにoptional: trueをつけて、解決

=> つまり、optional: trueは紐づけられた外部キーの値が存在しない値やnilの場合でも、
  データベースに保存することができるオプション

=>外部キーであるorder_idに値が入ってないのでは?:expressionless:

確認してみると、、、

 $ rails db
SQLite version 3.7.17 2013-05-20 00:56:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .mode line
sqlite>  select * from order_details;

4.PNG

order_idがやっぱり空になっている:sunglasses:

コントローラに↓を記述して解決

 @ order_details.order_id = order.id

注文履歴 作成

(1) アクションを編集する

admin/homes_controller.rb

def top
    @orders = Order.all
end

@ordersには、
4 注文機能で保存した情報が入る
(4 注文機能で、Orderモデル , OrderDetailモデルに情報を保存している)

(2)ビューファイルを編集する
注文履歴一覧
<table>
  <tr>
    <td>購入日時</td>
    <td>購入者</td>
    <td>注文個数</td>
    <td>注文ステータス</td>
  </tr>
    <% @orders.each do |order| %>
      <tr>
          <td>
            <%= link_to  admin_order_detail_path(order.id) do %>
              <%=  l order.created_at %>
            <% end %>
          </td>
          <td><%= order.end_user.first_name%><%= order.end_user.last_name %></td>
          <td><%= order.order_details.sum(:number) %></td>
          <td><%= order.order_status_i18n %></td>
      </tr>
    <% end %>
</table>

ポイント

1 created_atを使って時刻を表示させる方法
(1) タイムゾーンを日本時間にする

config/application.rb

require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module NaganoCake
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2
    config.i18n.load_path += Dir[Rails.root.join('config/locales/*.yml').to_s]

    ↓を追記する
    config.time_zone = 'Asia/Tokyo'

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
  end
end
(2)日本人が読みやすいフォーマットになるように、lメソッドを用いる

(ア)ビューに以下のように記述する

 <%=  l モデル名.created_at %>

(イ) アプリケーションのロケールを:jaに設定する

config/application.rb

require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module NaganoCake
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

    以下を追記する
    config.i18n.default_locale = :ja

    config.i18n.load_path += Dir[Rails.root.join('config/locales/*.yml').to_s]
    config.time_zone = 'Asia/Tokyo'

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
  end
end

(ウ) config/locales/ja.ymlに以下を記述する

config/locales/ja.yml

、、、、、、ここから、、、、、、、、、
ja:
  time:
    formats:
      default: "%Y/%m/%d %H:%M:%S"
、、、、、、ここまでを追記する、、、、、  

 enums:
    order:
      order_status:
        wait_payment: '入金待ち'
        confirm_payment: '入金確認'
        making: '製作中'
        preparing_ship: '発送準備中'
        finish_prepare: '発送済み'
      payment_method:
        credit_card: "クレジットカード"
        transfer: '銀行振込'
    order_detail:
      manufacture_status:
        impossible_manufacture: '着手不可'
        waiting_manufacture: '製作待ち'
        manufacturing: '製作中'
        finish: '製作完了'
2 商品の合計を表示させる
<%= order.order_details.sum(:number) %>

商品の個数が保存されているのはorder_detailsテーブルのnumberカラム
→アソシエーションを結んでいるため、orderという変数からnumberを持って来れる
 
注文した商品の合計はnumberというカラムの合計を表示する必要がある。
→each文を使って種類ごとの個数を出す必要はなし

<%= 、、、.sum(:合計したいカラム) %>

で合計を表示できる

エラー発生!!:scream:

error.PNG

この時、

<%= link_to l order.created_at , admin_order_detail_path(order.id) %>

↓のように修正して解決

<%= link_to  admin_order_detail_path(order.id) do %>
   <%=  l order.created_at %>
<% end %>

注文履歴詳細 作成

(1)アクションを定義する
class Admin::OrdersController < ApplicationController
  def show
    @order_details = OrderDetail.where(order_id: params[:id])
    @order = Order.find(params[:id])
  end
end
(2)ビューファイルを作成する
注文履歴詳細

<%= form_with model: @order, url: admin_orders_path, method: :patch, local: true do |f| %>
  <table>
    <tr>
      <td>購入者</td>
      <td><%= @order.end_user.first_name %><%= @order.end_user.last_name %></td>
    </tr>
    <tr>
      <td>注文日</td>
      <td><%= l @order.created_at %></td>
    </tr>
    <tr>
      <td>配送先</td>
      <td><%= @order.postal_code%><%= @order.address %><%= @order.name %></td>
    </tr>
    <tr>
      <td>支払い方法</td>
      <td><%= @order.payment_method_i18n%></td>
    </tr>
    <tr>
      <td>注文ステータス</td>
      <td>
        <%= f.select :order_status, Order.order_statuses_i18n.invert %>
        <%= f.submit "更新", class: "btn btn-success" %>
      </td>
    </tr>
  </table>
<% end %>

<table>
  <tr>
    <td>商品名</td>
    <td>単価(税込)</td>
    <td>数量</td>
    <td>小計</td>
    <td>製作ステータス</td>
  </tr>
<% @order_details.each do |order_detail| %>

<% @sum = 0 %>
<% @sum += order_detail.item.with_tax_price %>

<%= form_with model: order_detail , url: admin_order_details_path(order_detail.id) , method: :patch , local: true do |f| %>
    <table>
        <tr>
          <td><%= order_detail.item.name %></td>
          <td><%= order_detail.item.with_tax_price %></td>
          <td>
            <%= f.select :manufacture_status, OrderDetail.manufacture_statuses_i18n.invert %>
            <%= f.submit "更新", class: "btn btn-success" %>
          </td>
        </tr>
      <% end %>
      <tr>
        <td>商品合計</td>
        <td><%= @sum %>円</td>
      </tr>
      <tr>
        <td>送料</td>
        <td>800</td>
      </tr>
      <tr>
        <td>請求金額合計</td>
        <td><%= @sum + 800 %>円</td>
      </tr>
  </table>
<% end %>

ポイント

1 注文履歴詳細の商品一覧の表示の仕方
class Admin::OrdersController < ApplicationController
  def show
    @order_details = OrderDetail.where(order_id: params[:id])
    @order = Order.find(params[:id])
  end
end

注文履歴詳細を表示させるには、OrderDetailの情報を取得する必要がある

OrderDetailの情報を探すには、OrderDetailのidを使う !!

しかし、今回送られてくるのはorderのid !!

 @order_details = OrderDetail.find(params[:id])

↑のようにorderのidを使うと、、、
キャプチャ.PNG

order_detailのidが1,2にorderのidが3の情報が入っているとすると
order_detailのidが1のorderのidが3という情報しか取得できない

(params[:id]が1だと、order_detailのidが1の情報しか取得できない)
(order_detailのidが2のorderのidが3という情報を取得できない。)

写真より、情報の取得漏れが起きていると分かる

今回取得したいのは、、、

Order_detailの中のorder_idが同じもの

id以外で複数探す => whereを使う

find(params[:id]) => 情報を1つ取得
where => 情報を複数取得
2 whereの使い方
.where(探したいカラム:使いたい情報)

今回は、.where(order_id:params[:id]

3

<%= f.select :order_status, Order.order_statuses_i18n.invert %>

enumを日本語化する時、ビューに下記を加える

_i18n.invert
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?