Railsを使ったアプリケーション開発で、routesファイルのルーティング設定において注意したい点を忘れないように記事を書いてみました。初投稿および初学者のため、表現や解釈に間違いがあるかもしれませんがご容赦ください。
遭遇したエラー
ActiveRecord::RecordNotFound in UsersController
Railsのconfig/routes.rbファイルでルーティングの設定をして、指定したURLにアクセスできないエラーが発生してしまいました。
この時routesファイルとコントローラとは次のように設定していました。
# usersコントローラ
get "users/:id" => "users#show", as: "user"
get "users/close" => "users#complete"
class UsersController < ApplicationController
def show
@user = EndUser.find(params[:id])
end
def complete
end
end
今回はEndUserというモデルを用意しています。
この状態でブラウザからurlに
http://localhost:3000/users/close
と入力すると、下のようなエラーに遭遇しました。
routesファイルに記述したHTTPリクエストが上の行から当てはめられることで、users/closeのURL上でusers/:idのリクエストが先に当てはめられてusersコントローラのshowアクションが呼び出されています。:id部分にURLで入力したusers/closeのcloseという文字列が代入されています。これによりshowアクションで設定したインスタンス変数に、EndUserテーブルの中からidに"close"という文字列を持つ存在しないレコードを探して渡そうとしていたことが原因でした。
# usersコントローラ
get "users/:id" => "users#show", as: "user" #こっちから実行されるため
get "users/close" => "users#complete" #これが実行されていない
解決策
そこで、以下のようにルーティングの順番を設定し直しました。
# usersコントローラ
get "users/close" => "users#complete"
get "users/:id" => "users#show", as: "user"
completeアクションに対応するviewファイルは次のように設定しています。
<h1>退会が完了しました</h1>
もう一度ローカルサーバー上でusers/closeと入力すると、上のget "users/close"のリクエストが先に実行され、次のように正しくURLにアクセスすることができました。
まとめ
routesファイル中でurlを設定するときは、
users/close
users/:id
のようにURLの階層が同じかつ上位の階層名が同じ場合は階層名や記述する順番に気をつけることでエラーの予防や解消に繋がりそうです。