kent備忘ログ

お仕事と趣味生活と

12月の振り返り(複数テーブルによるアソシエーションと値の参照・更新についての理解)

12月に取り組んだ学習を振り返りです。表向きはRailsのWebアプリ制作でしたが、中身はDBに関するテーブル同志のお互いの関連付けと、それぞれのレコードの値取得方法や更新方法を調べることが大半でした。

12月上旬

まず始めに、既に常套手段となっているショッピングカートを用いた、商品の追加機能を実装しました。
  • Rails上でDBの値を取得・更新出来るように、モデルにお互いのテーブルの関連付けを行いました。
  • 今回は多対多のテーブル同士の間に中間テーブルを先に作成しておき、関連を持たせるお互いのmodelファイルにhas_manyとbelongs_toの記載します。

item.rb

class Item < ApplicationRecord
# アソシエーションの記載
  has_many :cart_items, dependent: :destroy
# アクティブストレージ対応の為記載(先月記事参照)
  has_one_attached :imageend

cart_item.rb

class CartItem < ApplicationRecord
  belongs_to :item
  belongs_to :cartend

cart.rb

class Cart < ApplicationRecord
  has_many :cart_items, dependent: :destroyend

また、お互いの関係が今回の場合のように一対多の場合は.buildメソッド、一対一の場合は.build_メソッドを使用すれば、所属テーブルの外部キーに親モデルのidを持たせることができます。

ターミナル(rails console)

@cart = Cart.find(params[:id])
@cart_items = @cart.cart_items.build # 一対多の場合、親モデル.子モデル.buildという形式
# インスタンスの中身
@cart_item
=> id: nil,
cart_id: 1,
item_id: nil,
name: nil,
quantity: nil,
created_at: nil,
updated_at: nil

# 一対一の場合(例えば商品と画像)
@item = Item.find(params[:id])
@image = @item.build_image # 親モデル.build_所属モデル

ただ、ここからテーブルの値取得方法に関して、RailsのクエリメソッドとSQLのクエリ文の違いに悩まされることのなりました。(そもそもSQLの理解が不足していた部分もあるかもしれませんが、現在も勉強中です…)

12月中旬

モデルの関連付けに続いて、URIとHTTPメソッドによるルーティングを学びました。

今回は商品をカートに追加するという動きの為、通常のCRUDのルーティングとは違った実装を迫られました。そこでmemberとcollectionという記述を学びました。

  • 2つの違いとして、memberは特定のレコード参照の為idを付与、collectionはidを付与しないところにあります。

routes.rb

resources :items do
  collection do
    get 'cart_items', to: 'cart_items#index'
  end
end

=> items/item:id/cart_items

resources :items do
  member do
    get 'cart_items', to: 'cart_items#index'
  end
end

=> items/cart_items

この関係を学んだことにより、単純なCRUD構造のページのルーティングだけでなく、ショッピングカート機能のようなアクションを用いた動作も実現できるようになりました。

12月下旬

商品の注文を確定させる為、購入の際行うチェックアウト機能を実装しました。同時に注文確認メールを送信するmailerの実装と使い方を学びました。
  • 始めに別のpaymentテーブルを用意し、そこに注文毎の注文者情報を保存させるようにしました。

  • その上でカート商品購入の際、氏名やメールアドレスを記入し、購入ボタンを押すと、記載されたメールアドレス宛に注文確認メールが送信します。

  • 送信機能には外部連携としてmailgunを使用。Active Storage実装の際に学んだ環境変数railsルートディレクトリ直下の.envファイルに記載し、herokuとGitHub Actionsにも値をセット、デプロイしました。

.env

MAILGUN_API_KEY=xx…
MAILGUN_DOMAIN=xx…
MAILGUN_PUBLIC_KEY=xx…
MAILGUN_SMTP_LOGIN=xx…
MAILGUN_SMTP_PASSWORD=xx…
MAILGUN_SMTP_PORT=xx…
MAILGUN_SMTP_SERVER=xx…
YOUR_HEROKU_APP=xx…

payment_controller.rb

# payment_controller.rb(メソッド化してモデルに切り出し)
 @payment.send_order_email

payment.rb

# payment.rb
 def send_order_email
    OrderMailer.creation_email(self).deliver_now
 end  

mailers/order_mailer.rb

class OrderMailer < ApplicationMailer
  default from: 'demo@abc.com'

  def creation_email(payment)
    @payment = payment
    mail(
      subject: '注文確認メール',
      to: @payment.email
    )
  end
end

views/order_mailer/creation_email.html.erb

<h2><%= @payment.name %> 様</h2>
<p>この度は、御購入ありがとうございました。<br>
  以下の内容でご注文承らせて頂きます。</p>
<p>決済番号:<%= @payment.id %></p>

<p>請求額:<%= number_to_currency(sum, format: "%u%n", unit: "¥") %></p>
ショッピングカート機能・チェックアウト機能を追加できたので課題提出→LGTMを頂けました。