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 :image ︙ end
cart_item.rb
class CartItem < ApplicationRecord belongs_to :item belongs_to :cart ︙ end
cart.rb
class Cart < ApplicationRecord has_many :cart_items, dependent: :destroy ︙ end
また、お互いの関係が今回の場合のように一対多の場合は.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>