本のレビューアプリ作成中、ログインユーザーの最新投稿を取得する方法が複数あったので、それぞれの簡単な使い方と違いについて備忘録としてまとめました。
【前提】
- rails_6.0.0_
- mysql2
- gem 'devise'を使用してログイン機能を実装済み
【目的】
- current_userの最新投稿を取得すること
- ビューで最終投稿日時を表示すること
【結論】 : current_userに紐づく投稿を配列取得し、「.last」で取り出す
@last_review = Review.where(user_id: current_user.id).last
whereメソッドでcurrent_userに関連する投稿を取得して、lastメソッドで最後の投稿のみを切り出します。
<%= @last_review.created_at %>
コントローラーで定義したインスタンス変数@last_reviewに対して、created_atカラムの情報を表示させます。
正直、自分が考えうる方法ではこの方法が最も記述が少なく、処理も早いので、今後これ以外使うことはなさそうです。
それでは、時系列順にこの結論に至った経緯を記載します。(1〜3まで)
1 : 配列のまま取得して、eachで1周だけ回す
はじめに思いついたのがこの方法です。
@last_reviews = Review.where(user_id: current_user.id).order(created_at: :desc).limit(1)
whereメソッドで投稿者がcurrent_userである投稿を配列で取得
.order(created_at: :desc)の部分で降順(新しい順)に並べ替え
.limit(1)で配列の先頭1つに限定
という流れです。
<% @last_reviews.each do |last-review| %>
<%= last_review.created_at %>
<% end %>
取得した配列をeachで一覧表示します。今回は中身が一つだけなので、一回の繰り返しです。
.limit(1)で最新の投稿を取得するこの方法だと、配列ごと取得する形になるので、ビューファイルでeach文を使う必要があります。
最新の投稿5件を表示させたい時などはこの方法を使う事になりそうですが、今回は1件だけなので正直、長い&読みにくいと感じました。
2 : .sliceを使用して、配列から投稿を1つだけ切り取る
@last_review = Review.where(user_id: current_user.id).order(created_at: :desc).slice(0)
先ほどの.limit(1)の部分を.slice(0)に変更して、配列から先頭の1要素を切り出します。
配列ではなく最新の投稿情報のみをインスタンス変数に定義しており、これならばeach文を用いる事なく投稿情報をビューファイルに表示する事ができます。
<%= @last_review.created_at %>
先ほどよりはスッキリしましたが、「引数に、切り出す配列の要素の番号や範囲を指定する」というsliceの性質上、配列の中身を降順に並べ替える必要があります。
3 : .lastを使用して、配列の末尾の要素を取り出す
@last_review = Review.where(user_id: current_user.id).last
.lastを用いる事で配列の末尾の要素のみを取り出す事ができます。
.slice(0)との違いとして、要素の範囲指定をしないので降順に並べ替えるが必要がなく、より短い&読みやすい記述になります。
(先頭の要素を取り出したい場合は.firstを使用します)
<%= @last_review.created_at %>
ビューファイルは先ほどと同じです。
##【まとめ】
ログインユーザーの最新投稿を取得して表示させる方法を3つご紹介しました。
- 配列のまま取得して、eachで1周だけ回す
- sliceを使用して、配列から投稿を1つだけ切り取る
- lastを使用して、配列の末尾の要素を取り出す
今回は最新投稿の1件以外は不要、且つ、並べ替えの記述を省くために、最後に紹介した.lastを採用しました。(私が思いつかなかっただけで他にも方法は様々あると思います... )
【最後に】
個人的な感想ですが、いろいろなやり方がある中でも自分なりに最適な方法を選ぶ過程はプログラミングの楽しみの一つだなと実感しました。今後も、何か発見できたらその都度アウトプットしていきたいと思っています。
ここまでお付き合いいただき、ありがとうございました。