A note of a person who is learning programming, SakaTaQ

ロック好きのプログラミング学習

マージ後に起きた問題(カテゴリ登録編)

某スクールのチーム開発にてフリマアプリを作成中、それぞれのメンバーがサーバーサイドで実装したものを統合した後、確認と修正をしている際にいろいろな問題にあたったので、それを対処するまでのログとして記事を書いてます。
初学者なので詳しい人からするとおかしいこと言ってるかもしれない。
コメントで指摘、助言いただければ幸いです。


結論から言うと、form_withでscopeを使っていた時に自動で生成されるHTML要素のname属性が原因だったと思われる。とりあえず経緯。


  
既に開発のメインとしているdeveloperブランチには他の3人がそれぞれブランチを切った後に、ユーザー機能、カード登録機能、商品購入機能、カテゴリ機能、出品削除機能を実装しマージ。
自分はその後に商品出品機能を実装完了し、マージ。
他の機能やページ変遷を確認し都度修正しながら、商品出品機能のカテゴリを登録できるか確認した所で問題が発生。

f:id:saka20taku43:20200419205625p:plain

何故か同じ内容が2つparamsに送信されている。しかもROLLBACKされていて意味不明。
ついでに出品機能に対してカテゴリは外部キーとして設定しているハズなのに文字列を送っている。
  
  
...あ、だからROLLBACKしたのかな?
それか2つ同じ形式の値を送った事で無効化されたとか。
route.rbとかapplication.scssで同じ事書いたら全部無視されたっけ。

初学者である自分にしてみれば意味わからんことだらけでしたが、とりあえずカテゴリ関連の記述があるコードを見ていく事に。   

controllerのストロングパラメーターとフォームは統合した際に既に修正していたので問題なさそう。 というかそこが違ってたらUnpermittedとか出るよね、多分。
っていうか、違うattributes送信したら以下のような感じでエラーメッセージが出たのは最初に確認した。

カテゴリを入力してください
Categoryを入力をしてください

これ出たときは流石にパニックになった。
...まあ、それはどうでもいいので続きを書いてく。

modelは正直関係なさそうな気がしていた。
validates間違っていたら違うエラー出そう。そして今回のROLLBACKはそれ以前にマイグレーション時に設定していたnull: falseによるものだよねきっと。

正直初日(昨日)は他にも大量にエラーが出てたのでカラム名とか弄ってたら0時過ぎてた(他の確認も並行していて10時間以上経過していた)ので一段落つけました。
分からないながらに進行していたので無意味に時間が過ぎていたような感じ。
  
で今日は朝早くに起きれなかったのでAM11時から続行(-A-;) ネスゴシタ

親カテゴリーのみで送信したり、子カテゴリーのみで送信したり孫カテゴリーまで送信したり。 その時のターミナルのエラ〜ログの違いを見て、以下のことが分かりました。

  • 何も入力されていなければ category_id=>"---" になり、item=>{...} の外側に2つ目は送信されていない

  • 親カテゴリだけなら category_id=>"親"になり item=>{}の外側に category=>"---"が生成される

  • 子カテゴリまで入力すると category_id=>"親"は変わらず item=>{}の外側に category=>"---"が生成される

  • 孫カテゴリまで入力すると category_id=>"親"は変わらず item=>{}の外側には category=>"孫"が生成される

  
親は常に送信されるが外側のカテゴリ送信については、仕様としてセレクトボックスが選択されるたびに自動で生成される中で、子から孫が生成された時に常に更新されているのが見て取れた。
つまり親はhaml上のf.selectで読み込まれる状態が続いていて、jQueryで生成された子孫は最新の物だけが読み込まれていた、と言うことになるんだよね多分。

で、そういえば送信された値が名前なのが何でなのかよく分からなかったのですが、chromeで検証している時にformで送信されるのがoptionタグのvalueだということに漸く気がついた。
そこからHTML要素を生成しているjQueryを見ることに。

jQueryは非同期でセレクトボックスを生成しているだけだと思っていたのでよく見ていなかったが、見た時に一番最初に目に入ったのが、jQueryを通して生成されるテンプレートリテラルで囲まれたHTMLの要素。

ここで生成されている要素に <option value="${category.name}" ... > とあったのでこれを .id に直した所、送信する値が名前ではなく数値に変えることができた。
...少なくとも子と孫は。

後は生成された物を検証で見ていた時にname属性の名前が親と子孫で違うのに気がついた。
そこで、子孫の name="category_id"を、親の name="item[category_id]"に変更してみた所、無事paramsの値が最新の要素である孫のみを送信できる状態にすることができ、何とか事無きを得た。   
  
  
因みにこの後、アソシエーションの関係で画像投稿に関するエラーに見舞われるのは別の話😅   

反省点

scopeを使っていることを情報として出していなかったこと、他の人がどういうコードを書いているかがよく分かっていないこと、でかなり苦しんだ土日となりました。 後はまだまだ、Railsの動きに付いていけてないのがよく分かりました。
今回は実装画面のエラーメッセージをユーザビリティを考えて日本語化していましたが、ターミナルのエラーログとか確認していると何でもかんでも翻訳すればいいもんじゃないなって思えた。

ただ、時間は掛かっても自分で解決できていると言うことにすごく自信がついた週末になりました。 今後も仮説と検証をいくつも持って常に冷静に対処できれば良いなと思いました。  
したらな!✋