最終課題で詰まったところ(更新中)
【GitHubでの流れ】
コミット→プッシュ→プルリクエスト→レビュー修正→LGTM→マージ
→不要ブランチの削除→ GitHub Desktopでブランチをマスターに→Fecth
【カラム名のミス】
「下の名前」のカラム名を「last_name」としたままマイグレーションを行なっていたので修正。
①rails generate migration 変更前カラム名_column_to_モデル名(複数形)
→変更用のマイグレーションファイルを作成
②作成したマイグレーションファイルを編集
今回は2つのカラム名を修正。下記を記述後にrails db:migrateで完了。
Squel Proでも反映を確認した。
【マイグレーションファイルのエラー】
・マイグレーションファイルで、追加したカラム名の後にコンマを書き忘れてエラー
・原因不明でマイグレーションファイルが複数になっていた
→モデルを一度削除して再度インストール(rails d devise user)
→この際、マイグレーションファイルの状態はrake db:migrate:statusで確認した
【ユーザー管理機能のパラメーター設定】
application controllerへ下記のように記述して設定。
if~で、devise controllerの処理時限定とする。
【erbファイルのデバッグ】
erbファイルへのbinding.pry実行でエラーが発生した。
原因:pry railsのインストールやサーバーの再起動を行わずにbinding.pryを実行していたためエラーが発生した。また、erbファイルの場合はbinding.pryの記述を<% %>で囲む必要がある。
手順:Gem fileへのgem 'pry rails'の記述を行いbundle installを実行
→その後rails sを行う
【binding.pryの終了の仕方】
binding.pryの終わらせ方が分からなかった(exitで終了できなかった)
→exit!で終了できた
【ビューファイルの設置ミス】
課題用に与えられていたビューファイル(部分テンプレート)を設置する場所を誤っていた。
正:views/sharedファイルを作成して設置
誤:元々あったviews/devise/sharedファイルに設置
deviseインストールからやり直した時に、deviseがデフォルトで作成してくれるサインアップ画面のビューファイルを確認。
エラーメッセージなどの部分テンプレートの引用先がdevise/sharedとなっていた。
対して課題用のビューファイルでは、部分テンプレートの引用先がsharedの記載だけだったので判明。
(そもそもヘッダーやフッターの部分テンプレートなので、全体に適用する意味でもdeviseディレクトリ内にならないことにも気づいた)
【エラー発生時にメッセージを表示する部分テンプレート】
上記のように記載があったので、hogeを@userに変えたがエラーが発生。
Googleで「render model」と検索するとサブジェクトでf.objectが出てきて、検索結果から下記サイトを確認。
Ruby - インスタンスではなくf.objectを使う理由を知りたい|teratail
model:の後はhogeを消してそのままf.objectで良かったらしい。
【ユーザー新規登録を行っても保存されない】
ユーザー新規登録を行っても、再度ユーザー登録画面に戻される
対処:
①メールアドレスを変えた(一意性が関係しているかもと思った)
→結論関係なかった(後から確認)
②ビューファイルのフォーム名をencrypted_passwordではなくpasswordに変更した
③deviseのストロングパラメーターはemail・password・password_confirmation・encrypted_passwordは入れずにその他のカラムを指定した
④戻されたユーザー登録画面ではなく、再度サインアップページのパスを入力してページを切り替えた(localhost3000/usersのページに飛ばされていたため)
あるサイトで下記の表記を見つける。
(ただし、このサイトには間違った情報も書いてあるっぽい)
deviseでユーザー登録ができない時に疑うところ6点 - Qiita
deviseでのusersテーブルのカラム(デフォルトではencryped_password)ですが、form_withのパスワードとパスワード再入力では、それぞれカラム名をpassword、password_confimationと記述しないといけません。これはpasswordとpassword_confimationが同じかどうかをチェックし、同じならばencryped_passwordに暗号化した文字列を返すという機能がdeviseに実装されているからです。
あとで確認すること:binding.pryを行った時にpermitted:がどうなっているか・メールアドレスは変える前のもので登録できるか?飛ばされたページでも登録できていたか
【ログアウト機能実装時のエラー】
発生したエラー:下記画像のエラー(Routing Error)
エラー時の状況:link_toでログアウトの機能を実装した際に発生
確認したこと:ルーティングの設定ミスがないか・実装漏れしている設定がないか
確認方法:過去のカリキュラム・エラー文でのGoogle検索(解決せず)
解決:過去作成したアプリ(Ptotospace)の同じ箇所を撮影して見比べ
原因:不要なダブルクォーテーションがあったこと。
(ルーティングは正しかった)
配布されていたビューファイルのパスの部分が"#"になっており、
#の部分だけを修正したことで発生したエラー。
【テストコード】
誤っていた内容:FactoryBotの導入時
(Gemfileのgroup :development, test doの中に記述する必要があった)
②FactoryBot用のファイルは、
FactoryBot導入後→テストファイル作成時に自動生成されるが、導入前に作成したテストファイルに対応するものは自動生成されないので、手動で作る必要がある。
【強制的にログインページに飛ぶ】
application_controller.rbに、カリキュラムで学んだauthenticate user!を記載していた。
これを記述すると、ログインしていないユーザーを強制的にログインページに誘導できる。
今回は未ログインでもトップページは利用できる実装のため、記述不要だった。
【エラーコードの重複】
エラーコードが重複で表示される現象が発生。
バリデーションにallow_blank: trueを追記して解消。
(詳しくはテストコードのブログにまとめ)
【パスワード(確認用)】
パスワード(確認用)は、データベースに保存されない仮想の属性のため、
バリデーションを設定する必要がない。
【Fakerの設定】
Fakerで「半角英数字でメールアドレスを作成」させる際、
password { Faker::Internet.password(min_length: 6) }
としていた。
しかしこの記述では、「数字のみ」や「英字のみ」のパスワードが生成されてしまい、テストが失敗することがある。
英数字混合のpasswordを想定した上でFakerを使用する場合は、
password { '1a' + Faker::Internet.password(min_length: 6) }
のように、確実にpasswordに英数字が含まれるように指定しなければならない。
(またFakerを用いず、直接値を書き込む形でも問題ない)
【半角英数字に対するテスト】
「半角英数字での入力が必須」というテストコードを記述したが、正確性向上の為、「半角である必要がある」と「英数字である必要がある」は分けてテストした方が良い。
【バリデーションの可読性向上】
バリデーションの記述はwith_optionsを用いることでまとめられる。
可読性向上のために修正を行なった。
validates :nickname, presence: true
validates :family_name, presence: true
validates :family_name, format: { with: /\A[ぁ-んァ-ヶ一-龥々ー]+\z/ }, allow_blank: true
validates :first_name, presence: true
validates :first_name, format: { with: /\A[ぁ-んァ-ヶ一-龥々ー]+\z/ }, allow_blank: true
validates :family_name_furigana, presence: true
validates :family_name_furigana, format: { with: /\A[ァ-ヶー-]+\z/ }, allow_blank: true
validates :first_name_furigana, presence: true
validates :first_name_furigana, format: { with: /\A[ァ-ヶー-]+\z/ }, allow_blank: true
validates :birth_day, presence: true
上記を↓のように書き換えた。
【メールアドレスの一意性】
メールアドレスの一意性は、devise作成時にデフォルトで設定されているようで
特にマイグレーションファイルへの記述の必要はない。
↓マイグレーションファイルの下の方に書いてある。
【fill_inを使う際のフォーム名】
分かっていなかった点:fill_inを使う際に指定するフォーム名をどこから参照するか
確認方法:検証ツール→左上のカーソルマークのボタンを押す→そのフォームのラベル名(フォームのすぐ上にある表題のような部分)にカーソルを合わせる→<label></label>で囲まれた部分がフォーム名になる。
ただし、label内にfor='id名'が記載されている必要がある。このforを記載することでlabelとformを紐づけるため。
【resourcesの使い方】
resourcesを記述する場所と意味が分かっていなかった
記述する場所:routes.rb(controllerに記述していた)
意味:CRUDで用いられる7つのアクションをまとめて設定するためのもの
※CRUDはアプリケーションでデータの取り扱いを行う上での基本的な処理
(Create・Read・Update・Deleteの頭文字)
また、resouces onlyの設定をするときに[]で囲んでいなかったことで、
rails routesを行ったときにエラーが発生した。
【バリデーション】
文字数の指定・数値の範囲の指定について、下記サイトを参考にした。
Rails 6.1: 数値バリデーションを範囲(..)で指定できるinオプションが追加(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社
↓maximumとnumericalityを用いて記述。
【プルダウンの設定時】
プルダウン用のモデルを作成し、項目を記述して読み込みをしたがエラー発生。
理由:各プルダウンの行ごとにカンマで区切るのを忘れていた。
↓下記はきちんと区切れた記述。
※上記実装中、特定のプルダウンだけエラーになる現象が発生。
下記は修正後で、Charge.all(モデル名:charge)としているが、元々はDelivery_charge.all(モデル名:Delivery_charge)だった。
エラー内容は、Delivery_charge.alllが定義されていないという内容。
他のとの相違点は、モデル名の中にアンダースコアを入れていたこと。
ここが怪しいと思い、アンダースコアのないchargeモデルにして試してみたところ解消。
【ログアウト状態だとトップ画面に行けない】
authenticate_user!
→ログアウト状態のユーザーに対して、ユーザーログイン画面に遷移させる機能。
ただ、ログアウト状態でも使えるページを実装する場合には、
下記のように対象ページをexceptで除外する必要がある。
また、最初はこれをapplication_controller.rbに記述していたが、
products_controllerだけに機能させないといけないので
記述場所を変更した。(レビューによる修正)
【エラーメッセージが出ない】
商品出品機能実装時、未入力の状態で登録をしてもエラーメッセージが出なかった。
エラーを表示させる書き方自体は(元々テンプレートで配信されたものなので当然)正しく、
コントローラーのcreateメソッドに条件文で「保存できなかった時」にnew画面に戻る記述をすると解消した。
【パラメーターがうまく機能しない】
パラメーターの記述をした後に商品登録をしようとした際に、パラメーターがpermitされなかった。
userとアソシエーションを組んでいるにも関わらず、ストロングパラメーターにおいてユーザーをマージしていなかったことが原因だった。
【JavaScriptの実装】
価格のフォームに金額を入力すると、
販売手数料や販売利益が自動的に反映する実装。
↓application.jsにrequire("../product_price)の記載
..は1つ上のディレクトリ、product_priceはJavaScriptを記述するために手動で作成したファイル
↓手動で作成したファイルにJavaScriptのコードを記述。
1行書き込むごとに、console.log("OK")などとして動作を確認した。
(binding.pryのようなイメージ)
html.erbファイルで、application.jsを読み込むためのscriptタグの挿入を忘れていると正常に反映されないので注意する。
【レビュアーからの修正指示(ER図)】
・電話番号はstring型にする
(integer型だと0落ちという、頭の0が消える現象が起こる可能性があるため)
・テーブル名から推測できる部分は名称から省略する
(productsテーブルならproduct_nameではなくnameにするなど)
・password_confirmationは不要
(deviseのgemがあらかじめ用意している`encrypted_password`を使用しているため。
また、パスワードはセキュリティの面からも直接データベースには保存を行わず、
encrypted_passwordがユーザーの入力したパスワードを自動的に暗号化してくれている)
・referenceではなくrefirencesとする
(マイグレーション実行時にエラーとなるため)
・ActiveHashで実装する項目は、カラム名に_idをつける。
(各プルダウン項目ごとに番号を割り振って、それをデータベースに保存するため)
・誕生日のカラムはDate型にする。
(プルダウンが西暦・月・日で分かれていたので3つのカラムにしたが、1つのDateで実装可能)
・emailは一意性なので、ER図のオプションに記載する。
(ただし、機能自体はdeviseのデフォルトで備わっているので追加する必要はなく、バリデーションへの記載も不要)
【レビュアーからの修正指示(ユーザー管理機能)】
・password_confirmationにはバリデーションは設定しない。
(仮想の属性でカラムに保存しないため。同様にpasswordも保存しない。代わりに暗号化されたencrypted_passwordを保存する)
・Fakerへの設定
password { Faker::Internet.password(min_length: 6) }
この記述では、稀に「数字のみ」や「英字のみ」のパスワードが生成されてしまい、テストが失敗することが考えられる。
英数字混合のpasswordを想定した上でFakerを使用する場合は、
password { '1a' + Faker::Internet.password(min_length: 6) }
のように、確実にpasswordに英数字が含まれるように指定する。
(Fakerを用いず、直接値を書き込む形でも問題ない)
・「passwordは半角英数混合でなければ登録できない」のテストは下記の2つに分ける。(テストの正確性を向上させるため)
passwordが半角英字のみの場合は登録できない
passwordが全角の場合は登録できない
・バリデーションは「with_options」を使用することで、共通したオプションを付けることが可能となり、コードの可読性が上がるのでまとめる。
【レビュアーからの修正指示(商品出品機能)】
・active_hashで実装した項目に関しては、未選択状態の項目である「---」では保存できないことを確認する必要がある。
値に1を代入し、2以上のidが選択されないと保存できないことを確認するテストコードを実装しなければならない
・商品価格は「英数字混合では保存できないこと」のテストも必要。
・link_toの遷移先はPrefixで記述する。
【ActiveHashのプルダウン項目を別のビューに反映させる】
ActiveHashのプルダウン項目はidで保存されるので、そのまま引用してビューに反映させると単に数字として表示される。
これをプルダウン項目の表示のまま反映させることができなかった。
結論、下記のようにクラス変数にidを添字として渡すだけだった。
(delivery_charge_idはプルダウンの番号、Charge.dataは下に画像添付しているプルダウン用のモデルのクラス変数)
添字を渡すことには早めに気づいたのだが、最初は単にid = 添字としていたので、ズレが生じていたことからうまくいかなかった。
id - 1を添字として渡すことで解決した。
試したこと(binding.pryで処理を止めてコンソールに色々出力させた)
・Charge.dataと入力→配列が全て出てくる
・delivery_charge_idと入力→3が出てくる
・Charge.data[3]と入力→3つ目のハッシュが出てくる
・Charge.data[3][:name]と入力→送料込み(出品者負担)が出てくる
・Charge.data[delivery_charge_id][:name]と入力→エラー
・Charge.data[delivery_charge_id - 1 ][:name]と入力→送料込み(出品者負担)が出てくる
最後の添字に-1をするまでが長くかかった。また、delivery_charge_idは#{}で囲むのかなど、きちんと理解できていなかった点も確認をした。