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


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


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

order.rb
```Ruby
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

```Ruby
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
```Ruby
 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を実装する)

```Ruby
gem "enum_help"
```

###### (2) enumを定義する
order.rb
```Ruby
支払い方法
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
```Ruby
製作ステータス
  enum manufacture_status:
        {
          impossible_manufacture:0,
          waiting_manufacture:1,
          manufacturing:2,
          finish:3
        }
```
## 2 日本語化させる 
Railsアプリケーションを日本語化させるために国際化i18nを用いる
###### (1)Railsアプリケーションのデフォルトの言語を日本語にする
config/application.rb
```Ruby
  config.i18n.default_locale = :ja
  config.i18n.load_path += Dir[Rails.root.join('config/locales/*.yml').to_s]
```

###### (2)ymlファイルを作成する
```Ruby
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をつけることで日本語化出来る。

## <font color="Red">不具合発生!!</font>:scream:
### order_status , payment_method , order_detailのうちどれかが日本語化されない

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

```Ruby
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

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

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

  end
end
```

###### (2)ビューファイルを作成する
```Ruby
<%= 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 %>
```

#### <font color="Red">ポイント</font>
1
```Ruby
<%= f.radio_button :payment_method, "credit_card" %>
```
ラジオボタンを作成する。
payment_methodというカラムにcredit_cardという値を代入する


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

3
```Ruby
<%= 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
```Ruby
　def full_address
    '〒' + postal_code + ' ' + address + ' ' + name
  end
```

## 4 注文情報確認画面を作成する
###### (1)コントローラにアクションを定義する

orders_controller.rb
```Ruby

 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
```

この時のパラメータは
```Ruby
"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
```Ruby
 <ActionController::Parameters {"payment_method"=>"transfer", "postal_code"=>"", "address"=>"", "name"=>""} permitted: true>
```

#### <font color="Red">ポイント</font>
select_addressの値によって、不足している情報が変わっているので
if文で条件分岐させ、不足しているカラムに値を代入する。

```Ruby
  if params[:order][:select_address] == "0"
```
この時のparams
```Ruby
"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文の中に↓を記述

```Ruby
@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
```




```Ruby
elsif params[:order][:select_address] == "1"
```
この時のparams

```Ruby
"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が空 => 入れる必要がある。
```Ruby
セレクトボックスで取得したaddress_idを用いて選択したaddressを代入
 @address = Address.find(params[:order][:address_id])
 
 @order.postal_code = @address.postal_code
 @order.address = @address.address
 @order.name = @address.name
```
```Ruby
 elsif params[:order][:select_address] == "2"
```
この時のparams
```Ruby
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>
```
```Ruby
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より、入れる必要がある。
```Ruby
@order.end_user_id = current_end_user.id
```
###### 残りの記述
```Ruby
カート内商品の情報を取得
@cart_items = current_end_user.cart_items

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

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

confirm.html.erb
```Ruby
<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 %>

```

#### <font color="Red">ポイント</font>
###### 1 小計を表示させる方法
```Ruby
1 <% @sum = 0 %> :@sum = 0 を定義する
2 <% @sum += cart_item.subtotal %> :@sumにcart_item.subtotalを足す
3 <%= @sum %>　:表示する
```

###### 2 hidden_fieldについて
hidden_fieldを用いることでブラウザにフォームを表示せずに
データを送ることが出来る。
```Ruby
<%= f.hidden_field :保存したい値が入るカラム名, value: 値 %>
```
schema.rbより
```Ruby
 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を作成する必要がある。
よって、↓のように記述すれば良い
```Ruby
<%= 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 %>
```
## <font color="Red">エラー発生!!</font>:scream:
#### ビューに@order.address @order.name が表示されない

```Ruby
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]の値を確認してみると、、、、
```Ruby
pry(#<Public::OrdersController>)> params[:order][:select_address]
=> "0"
```

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

if文を下記のように修正し解決!
```Ruby
if params[:order][:select_address] == "0"
```

## 4 注文機能を作成する
##### (1)hidden_fieldから送られたデータを保存する。

###### コントローラにアクションを定義する
```Ruby
 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


```
#### <font color="Red">ポイント</font>
##### 1 空のインスタンスに情報を入れる
```Ruby
 order = Order.new(order_params)
```
order_params
```Ruby
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
```Ruby
 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)
```Ruby
 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

```Ruby
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
```
よって、これらのカラムに値を保存する必要がある　

```Ruby
 @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 カート内商品の情報を全て削除する
```Ruby
CartItem.destroy_all
```

##### 4 カートが空なら注文入力画面に進むことや、注文の作成処理をしない

```Ruby
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といったモデルに直接メソッドを使えなかった。

## <font color="Red">エラー発生!!</font>:scream:
#### 2種類以上の商品を注文できない!?



```Ruby
      @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
```

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

```SQL
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を作る必要がある。

```Ruby
  @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

```

この時ターミナルは、、、
```SQL
 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種類の商品を保存できるようになった

## <font color="Red">エラー発生!!</font>:scream:
#### OrderDetailがcreateできず、rollbacktransactionが起こる
ターミナル
```SQL
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/f18e2792-2da1-e675-d8c7-c73d2c6e72c5.png)

エラーメッセージを日本語化する
ja.ymlの記述を変更する(enumの記述は一旦、消す)
```Ruby
ja:
  activerecord:
  errors:
    messages:
      record_invalid: "バリデーションに失敗しました: %{errors}"
```

本来のエラーメッセージが表示される
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/6d578bb5-728d-215f-65ee-aa9d35945fde.png)


[Createの際のエラーUser translation missing: ja.activerecord.errors.models.company.attributes.user.required](https://teratail.com/questions/199168)

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

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

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

確認してみると、、、

```SQL
 $ 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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/dd74023f-7a2c-b719-285a-cdec9fc3be84.png)

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

コントローラに↓を記述して解決
```
 @ order_details.order_id = order.id
```

# 注文履歴 作成

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

admin/homes_controller.rb
```Ruby
def top
    @orders = Order.all
end
```

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

###### (2)ビューファイルを編集する

```Ruby
注文履歴一覧
<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>
```

#### <font color="Red">ポイント</font>
##### 1 created_atを使って時刻を表示させる方法

###### (1) タイムゾーンを日本時間にする

config/application.rb
```Ruby
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メソッドを用いる
(ア)ビューに以下のように記述する
```Ruby
 <%=  l モデル名.created_at %>
```

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

config/application.rb

```Ruby
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
```Ruby
、、、、、、ここから、、、、、、、、、
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(:合計したいカラム) %>
```

で合計を表示できる

## <font color="Red">エラー発生!!</font>:scream:

![error.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/7a72bf1d-9faa-ed5f-c533-b4e0c5706ae0.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)アクションを定義する
```Ruby
class Admin::OrdersController < ApplicationController
  def show
    @order_details = OrderDetail.where(order_id: params[:id])
    @order = Order.find(params[:id])
  end
end
```

###### (2)ビューファイルを作成する
```Ruby
注文履歴詳細

<%= 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 %>
```

#### <font color="Red">ポイント</font>

###### 1　注文履歴詳細の商品一覧の表示の仕方 

```Ruby
class Admin::OrdersController < ApplicationController
  def show
    @order_details = OrderDetail.where(order_id: params[:id])
    @order = Order.find(params[:id])
  end
end
```

注文履歴詳細を表示させるには、OrderDetailの情報を取得する必要がある
#### <font color="Red">OrderDetailの情報を探すには、OrderDetailのidを使う !!</font>
#### <font color="Red">しかし、今回送られてくるのはorderのid !! </font>


```
 @order_details = OrderDetail.find(params[:id])
```
↑のようにorderのidを使うと、、、
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/2b4eabac-252a-7118-1dfe-f49d2ed05149.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という情報を取得できない。)

### <font color="Red">写真より、情報の取得漏れが起きていると分かる</font>

### 今回取得したいのは、、、
## Order_detailの中のorder_idが同じもの

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

```Ruby
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
```