LoginSignup
0
0

【Rails】意図していないアクションが実行されてしまう時に確認してほしいこと

Last updated at Posted at 2024-02-05

はじめに

Railsでアプリ開発をしていて、意図通りにアクションが実行されないことはよくあると思います。
その原因は様々あると思いますが、今回は未来の自分の為にいくつか例を投稿します。
ついでに初学者の方々の助けにもなれば幸いです。

ルーティングの記述の順番を確認する。

Railsのルーティングは、ルートの定義順によって評価されます。
つまり、最初にマッチしたものが実行されます。
以下の場合item_export_list_pathをリクエストすると
item#export_listではなくitem#showが実行されてしまいます。

config/routes.rb
post 'items/:id', to: 'item#show', as: 'items_show'
post 'items/item_list', to: 'item#export_list', as: 'item_export_list'

なので以下のように順番を入れ替えて修正

config/routes.rb
post 'items/item_list', to: 'item#export_list', as: 'item_export_list'
post 'items/:id', to: 'item#show', as: 'items_show'

これでitem_export_list_pathをリクエストすると
意図通りitem#export_listが実行されました。

詳しい原因はよくわかっていないのでchatgptに聞いてみた。

:id は任意の文字列にマッチするため、post 'items/:id' の方が広範なパスにマッチすると判断されます。
/items/export_list というパスが来た場合、Railsはまず最初のルートから順にマッチするかどうかを確認します。post 'items/:id' の方は :id が任意の文字列にマッチするため、このパスにもマッチしてしまいます。そのため、最初のルートがマッチしてしまい、items#show アクションが実行されてしまいます。

つまりは、/:idは文字列にもマッチすることがあり、
/items/export_list(この場合/export_listが文字列)のリクエストがより前に定義していたitems/:idと判断されitem#showが実行されたということでしょうか。
基本的に、今回のようにルーティングを設定する場合はitems/:idのようなルーティングは:id以外を渡した場合も呼ばれる可能性があるため後ろに定義しておくことが無難という考え方で問題ないのでしょうか。
なんちゃってエンジニアの私に教えていただければ幸いです。

javascriptを設定せずにlink_toを使用している場合

javascriptを設定しておらず、link_tomethod: :postなどget以外を指定している場合はデフォルトでgetリクエストが生成されるので違ったアクションが呼ばれてしまうことがあります。
javascriptを有効にした場合はjavascriptが介入して指定したHTTPメソッドでリクエストしてくれます。
javascriptを有効にしない場合はbutton_toに書きかえるか

<%= form_with(url: XXXXX_path) do |form| %>
   <input type="submit" value="button">
<% end %>

のように実装することで対応できます。

最後に

今後も開発していくなかで新しく陥ってしまった事例など出てきましたら記事に追記していこうと思います。
間違った内容や表現などありましたらご指摘いただけますと幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0