ume

rails7 ルーティングの記載の順番で挙動が変わる件について

前書き

正しいルーティングを記載しているのに想定していたコントローラーに繋がらなくハマったので記事に残します。

ハマったこと

new_admin_product(admin/products#new ) というprefixでリクエストを送るとBのadmin/productsコントローラーのnewアクションに遷移すると想定していました。ただ実際はAのproductsコントローラーのshowアクションに遷移してしまう。 上記のルーティングで実際作成されるパスは以下になります↓

| ルート名            | HTTPメソッド | パス                         | コントローラー#アクション   |
|---------------------|--------------|------------------------------|-----------------------------|
| admin_products      | GET          | /admin/products(.:format)    | products#index              |
| admin_product       | GET          | /admin/products/:id(.:format)| products#show  ⇦このアクションにつながる             |
|                     | POST         | /admin/products(.:format)    | admin/products#create      |
| new_admin_product   | GET          | /admin/products/new(.:format)| admin/products#new ⇦このアクションにつなげたい       |
| edit_admin_product  | GET          | /admin/products/:id/edit     | admin/products#edit      |
|                     | PATCH        | /admin/products/:id(.:format)| admin/products#update      |
|                     | PUT          | /admin/products/:id(.:format)| admin/products#update      |
|                     | DELETE       | /admin/products/:id(.:format)| admin/products#destroy     |

結論

⇨namespace :admin doとscope 'admin' doのルーティングの記載の順番を入れ替える

| ルート名            | HTTPメソッド | パス                             | コントローラー#アクション   |
|---------------------|--------------|----------------------------------|-----------------------------|
| admin_products      | POST         | /admin/products(.:format)        | admin/products#create      |
| new_admin_product   | GET          | /admin/products/new(.:format)    | admin/products#new ⇦このアクションにつながる    |
| edit_admin_product  | GET          | /admin/products/:id/edit.        | admin/products#edit        |
| admin_product       | PATCH        | /admin/products/:id(.:format)    | admin/products#update      |
|                     | PUT          | /admin/products/:id(.:format)    | admin/products#update      |
|                     | DELETE       | /admin/products/:id(.:format)    | admin/products#destroy     |
|                     | GET          | /admin/products(.:format)        | products#index              |
|                     | GET          | /admin/products/:id(.:format)    | products#show               |

解説

new_admin_product(/admin/products/new) というリクエストを送信するとroutes.rbの上から順番に一致するものを探す

| ルート名            | HTTPメソッド | パス                         | コントローラー#アクション   |
|---------------------|--------------|------------------------------|-----------------------------|
| admin_products      | GET          | /admin/products(.:format)    | products#index              |
| admin_product       | GET          | /admin/products/:id(.:format)| products#show  ⇦このアクションにつながる             |
|                     | POST         | /admin/products(.:format)    | admin/products#create      |
| new_admin_product   | GET          | /admin/products/new(.:format)| admin/products#new ⇦このアクションにつなげたい       |
| edit_admin_product  | GET          | /admin/products/:id/edit     | admin/products#edit      |
|                     | PATCH        | /admin/products/:id(.:format)| admin/products#update      |
|                     | PUT          | /admin/products/:id(.:format)| admin/products#update      |
|                     | DELETE       | /admin/products/:id(.:format)| admin/products#destroy     |

上のハマったルーティングを見ると /admin/products/newが/admin/products/:idと一致すると判断されたため想定外のコントローラーのアクションに遷移しました.
なぜなら:idの中にnewが代入される. :idと聞くとadmin/products/2などのように数値 が入るイメージでしたが数値以外も代入されるそうです

まとめ

  • ルーティングの記載の順番で想定外のコントローラーにつながる

  • /admin/products/:idなどの:idには数値以外も代入される

  • ルーティングは上から順番に一致するものを探す