sugulogの日記

Rails、ルーティングのネスト!コメント機能を実装しよう!!

スポンサードリンク

f:id:sugulog:20201101160845p:plain
こんにちは、すぐるです!

sugulogをお読みいただきありがとうございます!!

このブログは、「 過去の無知な自分に向けてわかりやすく説明するなら?? 」を基準に書いています。

少しでもお役に立てれば幸いです。

 

今回は、Railsのルーティングのネストということで

  • コメント機能の実装

について簡単に解説します!!

その為このブログを読むことで、ルーティングのネストについて理解できるのはもちろん、コメント機能の実装についても理解が深まります。

是非最後までご愛読ください。

 

今回は、

  • コメントモデルの作成

  • ルーティングのネスト

  • コメント機能の実装

の順で解説していきます。

また、前回のブログの内容を引き継いで記述しています。

そのため、前回のブログを必ず1度読んでからお読みください。

sugulog.hatenadiary.jp

では早速、みていきましょう!!

・コメントモデルの作成

コメントはツイートとは別機能です。

そのためまずは、rails g model commentを実行しモデルを作成しましょう。

次に今回マイグレーションファイルには、以下のように記述しました。

f:id:sugulog:20201101005931p:plain

コメントを保存するカラムとしてtext型のtextを定義しました。

またコメントはどのツイートに対してされたものなのか、誰がしたものなのかといった情報も必要です。

そのためtweetのid、userのidを保存するカラムも定義しています。

ではrails db:migrateを実行しテーブルを作成しましょう。

コメント機能はツイートとユーザー情報を必要とするため、次にアソシエーションを定義していきます。

まず1つのツイートは複数のコメントを所有できますが、1つのコメントは1つのツイートに対し投稿されます。

また1人のユーザーは複数のコメントを所有できますが、1つのコメントは1人のユーザーによって投稿されます。

 そのためアソシエーションは、以下のように記述しました。

f:id:sugulog:20201101013410p:plain

f:id:sugulog:20201101013225p:plain

f:id:sugulog:20201101013317p:plain

・ルーティングのネスト

ルーティングをネストすることで親のidを子のパスに含めることができる。

idをパスに含めることでアソシエーション先のレコードのidをparamsに追加してコントローラーに送り、コントローラーで取得することができるようになります。

では実際にネストして記述していきましょう!

f:id:sugulog:20201101014855p:plain

4〜6行目に注目してください。

親のルーティングにdo〜endを記述し、その中に子のルーティングを記述していきます。

今回、コメントは投稿の詳細ページから投稿するためnewアクションでのインスタンス生成、新規投稿ページを実装せず、createアクションのみを定義しています。

また親のtweetsに対し子のcommentsをネストしています。

そのためcommentsのパスには、ツイートのidを含んだパスが形成されます。

実際にrails routesでみてみましょう。

f:id:sugulog:20201101021127p:plain

パスにtweet_idが含まれていることが確認できますね!!

・コメント機能の実装

次にrails g controller commentsコントローラーを作成し、以下のように記述しました。

f:id:sugulog:20201101044856p:plain

mergeにおけるidの取得としては、ユーザーidはcurrent_user.idで取得し、ツイートのidはパスに含まれるidをparamsから取得しています。

その際にparamsの取得方法としてtweet.idではなくtweet_idと指定しているのは、先ほどのルーティングでのパスで確認できたように、tweet_idという形でパスにidを与えているからです。

またコメント投稿後、コメントしたツイートの詳細ページへredirect_toすることで、コメント投稿後のビューをコメントしたツイートの詳細ページに指定しています。

次にツイートの詳細ページにフォームを作成するために、以下のように記述しました。

f:id:sugulog:20201101034446p:plain

16〜23行目に注目してください。

まず17行目のif文でcurrent_userと指定することで、現在ログイン中のユーザーのみにフォームを表示させることができます。

そして18行目ではmodelの後に@tweetと@commentの2つを指定しています。

これはルーティングをネストさせたためコメントのパスには、tweetとcommentの2つの情報が含まれているからです。

また現時点では@commentを定義していないので、この後定義する必要があります。

ということで次にコメントが投稿された後表示させるコードを、投稿詳細ページに記述していきます。

その際コントローラーに、以下の記述を追加しました。

f:id:sugulog:20201101041911p:plain

31〜34行目に注目してください。

まず32行目ではツイート詳細ページのフォームからcommentsのcreateを実行するリクエストを飛ばすため、Comment.newでインスタンス変数を定義しています。

また33行目では@tweet.commentsとすることで@tweetにはツイートのidが入っているため、そのツイートに対するコメント全てを取得します。

またincludesメソッドを使い、コメントのユーザーidを取得する際のN+1問題を解決しています。

では最後にコメントが投稿された後表示させるコードを、以下のように記述しました。

f:id:sugulog:20201101045153p:plain

23〜33行目に注目してください。

まずは25行目でif @commentsとすることで、該当するコメントがあれば表示されるように定義しています。

後はコメントがあった際に該当する全てのコメントを@commentsで取得しているので、eachでそのコメントを1つずつ取得し表示させています。

また28行目ではlink_toで表示させたコメント投稿者のnicknameから、該当するユーザーのマイページへアクセスできるように記述しています。

その際に引数としてcomment.user_idを定義することで、ユーザーのidを取得しています。

では最後に、コメントを投稿した際にしっかりと表示されるか確認しましょう!!

f:id:sugulog:20201101155656p:plain

 

以上、今回のブログでした。

ルーティングのネストについて理解でき、コメント機能の実装についても理解が深まりましたか??

アソシエーションやルーティングのネストなど複雑な概念との関係性が少し難しいですが、1つずつしっかりと理解し深めていきましょう(≧∀≦)/

 

最後に!!

今後も、「 過去の無知な自分に向けてわかりやすく説明するなら?? 」を基準にブログを書いていきます。

少しでも気になった方はお試しでもいいので1度、読者登録お願いします!

またTwitterでもプログラミングに関することを中心に情報を発信してます。

宜しければそちらのフォローもお願いします。

最後までご愛読いただきありがとうございました!!