20201205_アウトプット(商品購入機能)

アプトプット画像

今日行ったこと 8時間

  • 商品購入機能の実装(フォームオブジェクトが保存できるようになるまで)

    新しい発見

昨日の疑問点がスッキリした!

わからないところ(どっちだっけ?と理解が曖昧なところ)

  • フォームオブジェクトのsaveメソッドに記載する内容について。usersテーブルや、itemsテーブルのモデルも必要なのかな?(今は未実装。仮説はアソシエーションで事足りる?)
    >>「不要」で実装できた。そもそも、saveメソッドの部分は「それぞれのテーブルに何のカラムを最終的に保存するか」を書く部分だと理解。

  • AciveHashのアソシエーションに、スルーいる?(今は未実装。仮説はitemsテーブルから引っ張ってきているわけではなく、prefectureモデルとしてデータを持ってきているのでいらない?)
    >>「不要」で実装できた。中間テーブルを作成した時に必要となるスルーオプションだが、ActiveHashの時にはテーブルを作らない(DBには保存しない)ため、不要だと理解。

  • link_to等で指定するプレフィックスについて。飛んだ後のページ書くんだっけ?(仮説:そのボタンを押した時に起こしたい、HTTPメソッドのプレフィックスを指定する)
    >>「そのボタンを押す」時に、起こしたいコントローラーのアクション(rails routesの右側)から左に辿っていったプレフィックスだと理解。

  • ネストが必ず必要な部分とそうでない部分の違い。
    >>「それがないと成り立たないもの」は入れ子構造になると理解。今回で言えば、「商品」がなければ「購入」もないため、ルーティングにおいて入れ子構造になる。 userは今回deviseを用いているためdevise_for :usersで事足りていることと、「ログインしないと購入できない」はルールではあるものの、「人」と「商品」は別であると理解。(つまり、ルール設定をどうするかであって、「なし」では成り立たないものでは無い)

    実装を通して理解が深まったこと

今日は3つについて理解が深まった!

ストロングパラメーター(require・permit・merge)

エラーメッセージは出ないけど「購入」ボタンを押しても、データベースに保存されない!ということが発生。
ストロングパラメーターに不要なカラムを入れていたことが原因だった。

ストロングパラメーターについて、

を制限している(許可した上でデータを運んでいる)ことは理解していたが、mergeは「?」だったことに気づいた。

mergeとは、パラムス上、必要なデータだけれども、requireで指定したモデル外にあるデータを、参照してデータにくっつけて運ぶ役割があると理解。

パラムスの図

【ここから学んだこと】
自分の想像で、パラムスはデータを運ぶリュックだとイメージしているが、そのキーは、require・permit・mergeどのポケットに入れて運ぶデータなのか、きちんと把握した上で、ストロングパラメーターに指定しないと、うまくデータが運んだり保存できないことを理解した。

またbinding.pryparamsと入力した時に、外側の波かっこ{ }は、パラムス全体を指し、その中にある波かっこ{ }はpermitの中身を表し、permitの直前にある”order_form”が今回requireで指定したいモデルになることまで把握していなかったことに気づけた。



データが読み込まれるタイミングも重要!!(コントローラー)

上記のエラーにはもう一つ原因があった。
今回、order_formというFormオブジェクトを使って、ordersテーブルpaymentsテーブルに保存される、という実装をしているのだが、 保存された後に生成されるpaymentsテーブルにあるorder_idもストロングパラメーターや、Formオブジェクトのバリデーション、attr_accessorに設定しておりエラーが発生した。



例え話でいうと、

  • 「"コーヒー牛乳"テーブル」と「"ガラスビン"テーブル」があり、「コーヒー牛乳製造機」というフォームオブジェクトを使ってそれぞれに保存しようとしていた。

  • 「"コーヒー牛乳"テーブル」の中には「コーヒー」「牛乳」「砂糖」というカラムがあり、全て揃った上で1杯分のコーヒー牛乳ができる。

  • 「”ガラスビン”テーブル」は、「ガラス瓶」「パッケージシール」「コーヒー牛乳_id」というカラムがあり、最後のidは「”コーヒー牛乳テーブル”」を参照して(中身を入れて)完成する。

という前提があったとして・・

  • Formオブジェクトである「コーヒー牛乳製造機」のキー(attr_accessor)として、「コーヒー」「牛乳」「砂糖」「ガラス瓶」「パッケージシール」「コーヒー牛乳id」と設定したら、”「コーヒー牛乳id」のキーは、「コーヒー」「牛乳」「砂糖」を運び終わって、混ぜてからでないと今はないよ!”という状況になり、エラーになったということ。

  • つまり、「コーヒー牛乳製造機」というフォームオブジェクトが、saveされるタイミングで、「コーヒー牛乳id」必要になるけれど、それを保存する前までの、ストロングパラメーター(コントローラー)・attr_accessor(フォームオブジェクト)・validates(フォームオブジェクト)に「コーヒー牛乳id」はいらないよ!”という意味。

以上。 意味不明な部分が多々あると思いますが、必要なタイミングでキーを運び、保存する設定をしないと変にバリデーションエラーが出てしまったり、保存できないというエラーが出るということを説明したく書きました💦



他のアクション使いたい時どこまで設定すればいいの?

今回の実装でずっと感じていた疑問は、itemsテーブル時に定義したインスタンス変数(@item)を、ordersテーブルにおけるコントローラーやビューで使いたい時、どこまで設定したらいいの?使えるの?という疑問。


結論からいうと、2つあり、

  • ordersコントローラーにおいて、@itemをItemモデルから見つけてくる定義が必要になってくること

  • マイグレーションファイルにおける「リファレンス」が影響してくること

だった。

ordersコントローラーにおいて、@itemをItemモデルから見つけてくる定義が必要

orders_controller.rbのindex・createアクションに、

@item = Item.find(params[:item_id])

を定義すると、

  • orders_controllerにおいて、ストロングパラメーターのmergeでメソッドでitem_id: params[:item_id]と定義できるようになる

  • ordersビューにおいて、form_withでitem_orders_path(@item)プレフィックスを指定して、データが運べたり、@item.name(商品名)と参照できるようになる



マイグレーションファイルにおける「リファレンス」が影響してくること

上記で感じたのはitem_ididだけでいいの!?ということ。 「リファレンス」が影響していた。


マイグレーションファイルにおいて、

    create_table :orders do |t|
      t.references :user, null: false, foreign_key: true
      t.references :item, null: false, foreign_key: true
      t.timestamps

といった形で、referencesforeign_key: trueを設定することにより、 コントローラーでfindしている内容が、”id”を通して「itemsテーブルの情報たち」を参照できるようになると理解。 なので、言葉通りの「id」だけでなく、商品名や画像などを取ってこれるということがわかった。
反対に言えば、マイグレーションファイルにおいて、references型ではなく、integer型でも設定できてしまう。 その際、リファレンス(参照)の意味づけがされなくなり、必要なキーを自分でordersコントローラーに設定しないといけないため注意だと理解。



感想

  • ストロングパラメーターの理解が浅かったことに気づけてよかった。

  • paymentsテーブルの都道府県が、itemsテーブルにある都道府県使えるじゃん!と後から気づき、修正する際にテストコードが役に立つことを実感したのと(直し終わった!と思ってテストコード実行したら漏れ発見)、VSコードの左上のフォルダの下にある🔍検索の置き換え機能が便利〜!😍と実感✨(慎重に置き換えしましたが😅)

  • 夜21時くらいからが一番集中できていた。昼〜夕方コードは書いていたものの「わからない」と悩みすぎて集中力が足りなかったように思う。仮説を出し尽くしてもエラーが解決できない時に、メンターさんに聞きたところは、そもそも理解が浅かった(ストロングパラメーター、コントローラーの順番も大事)。おそらく解決方法が自分で導けない「わからない」になってしまうと、集中力が切れやすいと思った。

  • 夕方ごろから全身に蕁麻疹が💦かゆい😭 エビ食べたからかな・・?🦐



これから理解したいこと(覚書用)

  • Formオブジェクト(モデルの存在しないデータを更新)


  • エラー解決

  • カラムの追加方法、ロールバック

  • 環境変数(OSの知識)

  • 環境構築、バージョン対応

  • GitHub(他のアプリケーションと連携・自分に取り入れること)

  • Herokuのデプロイ方法 👉11/15・16学習 50%進む

  • README(DB設計だけでなく、全体について取扱説明書としてどんな風に書くと良いのか)

  • リファクタリング

  • データベースをインポート、エクスポート

  • Docker

  • gimei(Gem)