プログラミング学習

Rubyやrailsについて学んだことをアウトプットしています。

【Rails エラー】指定したアクション以外に繋がってしまうルーティングエラーの原因と対処法

今回もオリジナル開発で遭遇したルーティングのエラーについて原因と対処法を見ていきます。

今回発生したのは以下のエラーです。
f:id:yusuke_learning:20211029174606p:plain これは質問投稿アプリにおいてユーザーを管理する管理者画面から質問一覧を表示するためにadmin/usersのビューファイルにquestion.html.erbを追加し、ルーティングを設定した際に発生しました。

まずは、エラーコードから原因を推測していきます。

・エラーコードから原因を読み解く


エラーコードでは

RecordNotFound in Admin::UsersController#show

と書かれているのでコントローラーのshowアクションで問題が発生していることがわかります。
さらに詳しく見ていくと

Couldn't find User with "id" = question

つまり、showアクションではオブジェクトごとのidを受け取って詳細を表示しているのですがそのidにquestionが代入されており、そんなidは見つからないと言っています。

エラーコードから読み取れた内容をまとめると

①ルーティングで指定したadmin/users#questionではなくadmin/users#showが起動している。

②idになぜかquestionが代入されている。

この2つの謎を解明できればエラーが解決できそうです。
そこでルーティングについての記述のあるroutes.rbファイルを確認してみます。

・原因を特定する


該当箇所を見るとresourcesでCRUD機能に必要なルーティングを設定し、今回新たに追加した
get"/users/question", to:"users#question"
がその下に書かれています。

f:id:yusuke_learning:20211029180643p:plain
routes.rb
コードを見ただけではなぜ"/users/question"から"users#show"が起動されるのか理解できませんでした。
ここでしばらく悩んでしまったのですが、同じようなエラーで苦しんでいる人がいないかと検索したところ以下の記事が見つかりました。

Ruby on Rails - 【Ruby on Rails】違うアクションが実行されてしまう|teratail

記事の投稿者さんも自分と同じエラーに苦しんでいました。 そして、回答を見てみると

resourcesで定義したルートの場合、hogehoge/indexはhogehoge/:idの方にヒットして、「id=indexでshowを呼び出す」という意味になります。

つまり、エラーの原因はresources :usersの下に
get"users/question", to:"users#questionを定義してしまったことによって
"users/question"がhogehoge/:idと認識されてしまったことでした。
これでなぜshowアクションに遷移したのか、そしてidになぜquestionが代入されていたのかが判明しました。

・解決策


解決策としてはresources :usersよりも上の行に追加したいルーティングを書くことです。
これによって、想定したアクションに遷移させることができました。

resourcesにこのような特徴があるとは知らなかったので今後は気を付けていきたいと思います。

以上で今回の記事を終わります!

参考記事:


Ruby on Rails - 【Ruby on Rails】違うアクションが実行されてしまう|teratail