プログラミング学習 備忘録

Railsを学習していく上での技術メモ。学んだことや解決したエラーなどを記録していきます。

ajaxでのコメント機能実装時のエラー②(UrlGenerationError)

UrlGenerationError

今回の実装において最も苦戦したエラー。 一見簡単そうに見えるエラーなのだが、かなりの曲者だった。

     # ActionController::UrlGenerationError:
     #   No route matches {:action=>"show", :controller=>"comments", :id=>nil}, missing required keys: [:id]

簡単にいうと、「必要なidが渡されていないので、commentsコントローラーのshowアクションにルーティングできないよ〜」ということらしい。

しかし、今回コメントはboards/showの中に埋め込んでいるためcommentsのビューファイルが不要なので実装しておらず、commentsコントローラーのshowアクションも当然未実装。。。どういうことなの。

rails routesで現在のルーティングを調べてみる。

                  comment GET    /comments/:id(.:format)                                                                  comments#show
                          PATCH  /comments/:id(.:format)                                                                  comments#update
                          PUT    /comments/:id(.:format)                                                                  comments#update
                          DELETE /comments/:id(.:format)                                                                  comments#destroy

Showアクションへのpathであるcomment_pathと同じものはこの4種類。 この中で、deleteアクションへのリンクだけlink_toメソッドでmethod: :delete, remote: trueを使って実装したのでここが怪しいと推測。

Rspecのファイルをアプリケーション内に落とし、ローカル環境で回してみた。

  1) コメント コメントのCRUD コメントの作成 コメントの作成に失敗すること
     Failure/Error: <%= link_to comment_path(comment), method: :delete, remote: true do %>

     ActionView::Template::Error:
       No route matches {:action=>"show", :controller=>"comments", :id=>nil}, missing required keys: [:id]

     [Screenshot]: tmp/screenshots/failures_r_spec_example_groups_nested_3_crud_nested_2_コメントの作成に失敗すること_105.png

やはり推測通り、原因は<%= link_to comment_path(comment), method: :delete, remote: true do %>で間違い無いらしい。 なんらかの理由でgetリクエストも送られているみたい。

しかし、このコードの何が間違っているのか全く分からず… そもそも削除機能自体は正しく実装されており、ajaxでも正しく動作し、またデータベースからもしっかりと削除されているのを確認している。

comment_path(comment) => comment_path(comment.id)に変更 ②comment_path(comment) => /comments/#{comment.id}/に変更

上記の2つを試しても駄目だった。

ちなみに、showアクションと簡単なビューを作成し、method: :deleteを削除してgetリクエストを送ってみると、ちゃんと適切なコメントが表示された。 comment_path(comment)でちゃんと:id渡せてるやん。。。

お手上げかと思われたが、ここで妙なことに気づく。

1) コメント コメントのCRUD コメントの作成 コメントの作成に失敗すること

コメントの削除に成功すること というテスト項目で、このコードが指摘されるのはわかるが、なんでこのテスト項目でこのコードが指摘される? 試しにcommentのbodyが空の状態で投稿してみる。

f:id:yukimura907:20201109212423p:plain

f:id:yukimura907:20201109212529p:plain

なんと同じメッセージが表示されている!!!!

適切な例外処理ができていないことが原因???? ということで、create.jsをifで分岐させてエラーメッセージを表示させることに。

$('#js-table-comment').prepend("<%= j(render 'comment',{ comment: @comment }) %>");
$('#comment_body').val('')
$("#error_messages").remove()
<% if @comment.errors.present? %>
  $("#new_comment").prepend("<%= j(render('shared/error_messages', object: @comment)) %>")
<% else %>
  $('#js-table-comment').prepend("<%= j(render 'comment',{ comment: @comment }) %>");
  $('#comment_body').val('')
<% end %>

さぁどうだろう・・・

f:id:yukimura907:20201109212610p:plain

エラー出てない!!!!!!

恐る恐るrspecを回してみると・・・

test@tesutonoMacBook-Air 552_yukimura907_runteq_learning_basic % bundle exec rspec
.....................Capybara starting Puma...
* Version 3.12.1 , codename: Llamas in Pajamas
* Min threads: 0, max threads: 4
* Listening on tcp://127.0.0.1:51124
.....................................

Finished in 22.15 seconds (files took 3.01 seconds to load)
58 examples, 0 failures

成功!!!


スタバでガッツポーズした。



今回のエラーを通して、本当に厄介なのはメッセージとは全く違うコードが原因で引き起こされているエラーだと気づいた。 我ながらよくこのエラーを自力解決できたなーと思う。 意地でも自力走破してやろうと半ば躍起になっているが、そのおかげで自走力がだいぶ付いてきた気がする。