注文機能の流れ
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をつけることで日本語化出来る。
不具合発生!!
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 %>
エラー発生!!
ビューに@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文の条件式が間違えているのではないか?
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といったモデルに直接メソッドを使えなかった。
エラー発生!!
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が上書きされてる
原因:
@ 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種類の商品を保存できるようになった
エラー発生!!
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!にする
エラーメッセージを日本語化する
ja.ymlの記述を変更する(enumの記述は一旦、消す)
ja:
activerecord:
errors:
messages:
record_invalid: "バリデーションに失敗しました: %{errors}"
Createの際のエラーUser translation missing: ja.activerecord.errors.models.company.attributes.user.required
より、order_detail.rbにoptional: trueをつけて、解決
=> つまり、optional: trueは紐づけられた外部キーの値が存在しない値やnilの場合でも、
データベースに保存することができるオプション
=>外部キーであるorder_idに値が入ってないのでは?
確認してみると、、、
$ 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;
order_idがやっぱり空になっている
コントローラに↓を記述して解決
@ 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(:合計したいカラム) %>
で合計を表示できる
エラー発生!!
この時、
<%= 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_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