例えば、postモデルを親としてitemモデルのルーティングを以下のようにネストした場合、
resources :posts do
resources :items
end
showページ、およびeditページを表示した際にネストしたitemモデルのルーティングのURLのidが入れ替わって表示される(idパラメータが正常に受け取れない)という問題が発生してしまいました。
【例】
(こう表示したいのに)
http://localhost:3000/posts/1/items/123
(こう表示されてしまう)
http://localhost:3000/posts/123/items/1
本来、itemモデル(itemsコントローラー)のshowページ、およびeditページにおけるルーティングは以下のようになるかと思いますが、
post_item_path GET /posts/:post_id/items/:id/(.:format) items#show
edit_post_item_path GET /posts/:post_id/items/:id/edit(.:format) items#edit
実際には上記の:post_id
と:id
が入れ替わってURL欄に表示されてしまうのです。
本記事はその問題へのトラブルシューティングです。
ネストしたルーティングのULRのidが前後入れ替わる問題発生
問題の概要は先ほど説明したとおりですが、
例えば、itemモデルのshowページにアクセスするとしましょう。
itemモデルのshowページにアクセスするためにはpost_id
とitem_id
がそれぞれ必要になりますが、
post_id
とitem_id
がそれぞれ以下の値のとき、
- post_id:1
- item_id:123
showページに表示されるURLは以下のようになるはずです。
【期待するURL】
http://localhost:3000/posts/1/items/123
しかし、実際にはURL欄に以下のように表示されてしまいます。
【実際に表示されるURL】
http://localhost:3000/posts/123/items/1
これを、ルーティングに置き換えて見てみると、
【こうしたいのに】
http://localhost:3000/posts/:post_id/items/:id
【実際はこのような表示になる】
http://localhost:3000/posts/:id/items/:post_id
このように、post_id(:post_id)とitem_id(:id)が前後入れ替わってしまっていますね。
問題の解決策
post_item_path GET /posts/:post_id/items/:id/(.:format) items#show
ネストされたitemモデルのルーティングに則り、URLの左から順にpost_id(:post_id)、item_id(:id)と表示されるようにしたいので、
showページへのパスを貼る際に、itemモデルのshowページ(もしくはeditページ)へのパスの引数に、以下のようにidの順番を指定すればOKです。
# 同一URLにidを左から順に表示させるよう、以下のようにidの順番を指定
<%= link_to "◯◯", post_item_path(@item.post_id, @item.id) %>
こうすることで、同一URL内に複数のidパラメータが存在する場合も、狙い通りの順番でidを表示させることができます。
【パスにidの順番を指定することで解決】
http://localhost:3000/posts/:post_id/items/:id
editページへのパスも同様にします。
# editパスも同様にidの順番を指定
<%= link_to "◯◯", edit_post_item_path(@item.post_id, @item.id) %>
あとは、items_controller.rb
に以下のコードを追記すれば指定したパスにアクセスできるようになります。
class ItemsController < ApplicationController
before_action :set_post
before_action :set_item, only: %i[ show edit update destroy ]
・・・
private
def set_post
@post = Post.find(params[:post_id])
end
def set_item
@item = Item.find(params[:id])
end
・・・
end
以上です。
コメント