【Rails】ルーティングのネスト
今回、ルーティングのネストという方法を
説明していきたいと思います。
例えばコメント投稿機能を付けたい時、
新してくCommentモデルを作成して、テーブルも作成しますね。
そしてルーティングしたい時、今まで同様にroutes.rbに記述します。
resourcesの中で、コメント機能が実行するアクションはcreateアクションなので、only : createと指定しましょう。
さてここで一つ。
パスを確認すると、どの投稿に対するコメントなのかを示す情報はありません。
コメントする際には必ず紐づく投稿がありますよね。
ではどのようにして、どの投稿に対するコメントなのかを
パスから判断したらいいでしょうか。
ここで使用する方法がルーティングのネストです。
これは入れ子構造で示す方法です。
routes.rbを再度編集しましょう。
resources : posts do
resources : comments , only : : create
end
resources : users , only : : show
こういった形で、ルーティングの中にルーティングを記述します。
ネストを利用することでモデルと結びついている別のモデルのid情報が
送れるようになるのです。
つまりまとめると、ルーティングをネストさせる一番の理由は
アソシエーション先のレコードのidを
paramsに追加してコントローラーに送るためです。
今回はコメントと結びつく投稿のidをparamsに追加することができました。
そしてもちろんcreateアクションを定義する際にも
ストロングパラメーターを使用して保存できるカラムを指定します。
新たにcomment_paramsメソッドを定義しましょう。
def create
comment = Comment . create ( comment_params )
redirect_to " /posts/#{comment . post . id }"
end
private
def comment_params
params.require( : comment ). permit ( :text ) . merge ( user_id : current_user.id , post_id : params [ : post_id ] )
end
user_idカラムにはログインしているユーザーのidを保存し、
post_idカラムはparamsで渡されるようにするので、params [ : post_id ]として保存します。
そしてここ何?!と思ったかた多いかと思いますが、
redirect_to " /posts/#{comment.post.id }"
これは「コメントを保存したら投稿の詳細画面に戻ってね」と指示してます。
redirect_toの後にはルーティングのURLやPrefixを記述したら、
そのアクションが実行されます。
パスの部分はコメントと結びつく投稿のidを記述し、
その投稿の詳細画面に遷移するよう記述されてます。
ここからは追加でコメント機能を実装する際に必要な知識を追記します。
ビューにて対応する投稿の詳細画面で結び付けて表示させたい場合、
ビューを呼び出す前のコントローラーが実行されている時点で、
まずコメントのレコードをデータベースから取得します。
なのでpostsコントローラーのshowメソッドを編集しましょう。
def show
@comment = Comment.new
@comments = @post.comments.include( : user )
end
showは詳細画面を表示するアクションですね。
postsのshow.html.erbにコメントフォームを実装した際に、
comments#createを実行するリクエストを実行するために
インスタンス変数を生成しておきます。
またpostsテーブルとcommentsテーブルはアソシエーションが組まれているので
@post.commentsとすることで@postへ投稿された全てのコメントを取得できます。
さらにビューでは誰のコメントか明らかにするため、
アソシエーションを使ってユーザーのレコードを取得する処理を繰り返します。
このときN+1問題が発生するので、includesメソッドを使って解決しています。
これでコントローラーで、特定の投稿に対するコメントの全レコードを
取得することができたのでビューで表示しましょう。
<div class = " comments">
<h1><コメント一覧></h1>
<% if @comments %>
<% @comments . each do | comment | %>
<p>
<strong><%= link_to comment . user . nickname , "/users/#{ comment . user_id} " %> : </strong>
</p>
<% end %>
<% end %>
<% div %>
@commentsには複数のコメントのレコードが含まれているので、
配列の形にしてeachメソッドを使って表示させます。
またlink_toメソッドで作ったリンクの表示名は
コメントしたユーザーの名前になっています。
そしてパスにはコメントしたユーザーのidを記述しています。
こうすることでコメントを投稿したユーザーのidをparamsで扱えるようにしています。
以上がコメント実装機能で使えるルーティングのネストと
その他の設定でした!