実現したいこと
ブログアプリのindexページに全ユーザーの投稿が表示されるが、各投稿の「このユーザーの投稿一覧へ」をクリックすると、そのユーザーの記事だけ表示されるページに移動したい
実現するためにやったこと
①routes.rbファイルに、resourcesで作られるアクションにオリジナルのアクションを追加
→後から見直すと何をしたいのか不明ですが、当時はこれでアクションを追加すればパラメーターとしてuser_idが発生するのだと思っていた
get '/user/user_id', to: 'blogs#user'
②blogs_controller.rbファイルに下記を追加。whereメソッドでuser_idを指定しようとしています。
def index_user
@blogs = Blog.where(user_id:params[:user_id])
end
③コンソールにて。rails routesでPrefixを確認してユーザーごとの投稿一覧へのリンク設定
<%= link_to 'このユーザーの投稿一覧へ', index_user_blog_path(blog.user_id) %>
発生したエラー
具体的なエラーは発生していないが、クリックして移動した先のページに何も表示されない。実質エラー。
確認したこと
③をクリックした際のコンソールの内容を確認。
"user_id"IS NULL と書いてあります!つまり user_id にはなんらかの理由でパラメーター(Parameters: {"id"=>"5"}みたいなやつ)が送られていないということになります。コンソールを細かくチェックしてもパラメーターが送られてきた形跡はありません。
②をチェックしてみましたが、whereの使い方などに問題はなさそうです。
最後にチェックしたのが①です。そもそも、resourcesで設定したアクションの他に追加する場合、 collection doを使います。今回なぜそうしなかったかというと、上にも書いたようにuser_idを指定する必要があったためです(collection doはid指定ができない)。
分かったこと
上記調べた結果を元に、routes設定に問題がありそうだと仮定。そもそも、resourcesで設定したアクションのほかに追加する場合collectionがあるのだから、idが必要な場合にも同じようなメソッドがあってもいいはず。。。と思って調べたらありました。
https://railsguides.jp/routing.html
ちょっと分かりにくいですが、要するに下記とのことでした。
collection do: idを伴わない新たなroutingを設定
member do: idを伴う新たなroutingを設定
member do
get :index_user
end
こういうことのようです。これでコンソールを確認してみると。。。
パラメーターが送られてきています。ただ、この場合 "user_id" ではなく "id" です。rails routesでは
index_user_blog GET /blogs/:id/index_user(.:format) blogs#index_user
このようになっていますので、送られてくるのは user_id ではなく idで問題ないようです。 blogs_controllerの記述を user_id から id に変更します。
(変更前)
def index_user
@blogs = Blog.where(user_id:params[:user_id])
end
(変更後)
def index_user
@blogs = Blog.where(user_id:params[:id])
end
これでようやく、ユーザーごとの投稿一覧が表示されました。忘れないように①の get '/user/user_id', to: 'blogs#user' は削除。
Railsガイドを参照しました(説明がちょっと難しかったですが)。
https://railsguides.jp/routing.html
下記、Railsガイドより抜粋。
2.10.1 メンバールーティングを追加する
メンバー (member) ルーティングを追加したい場合は、memberブロックをリソースブロックに1つ追加します。
resources :photos do
member do
get 'preview'
end
end
上のルーティングはGETリクエストとそれに伴う/photos/1/previewを認識し、
リクエストをPhotosコントローラのpreviewアクションにルーティングし、
リソースid値をparams[:id]に渡します。同時に、preview_photo_urlヘルパーと
preview_photo_pathヘルパーも作成されます。
memberルーティングブロックの内側では、認識させるHTTP動詞をルーティング名ごとに指定します。
指定可能なHTTP動詞はget、patch、put、post、deleteです。
memberルーティングが1つだけしかない場合は、以下のようにルーティングで:onオプションを指定することで
ブロックを省略できます。
resources :photos do
get 'preview', on: :member
end
:onオプションを省略しても同様のmemberルーティングが生成されます。
この場合リソースidの値の取得にparams[:id]ではなくparams[:photo_id]を使う点が異なります。
ルーティングヘルパーも、preview_photo_urlがphoto_preview_urlに、preview_photo_pathが
photo_preview_pathにそれぞれリネームされます。