【Ruby on rails】過去一週間でいいねの合計カウントが多い順に投稿を表示する方法
初めに
プログラミングスクールに通い始めて2ヶ月目です。
読書本シェアアプリを作っています^^
自身の忘備録として記事を更新していきます!
アソシエーション
has_many :books, dependent: :destroy
has_many :favorites, dependent: :destroy
belongs_to :user
has_many :favorites, dependent: :destroy
has_many :favorited_users, through: :favorites, source: :user
belongs_to :user
belongs_to :book
userモデル,bookモデル,favoriteモデルのアソシエーションが完成しました。
has_many :favorited_users, through: :favorites, source: :user
はfavoritesモデルを介してuserモデルのデータを持ってくるという記述になります。
この解釈が正しいかわかりませんがそんな感じです。笑
コントローラー
def index
to = Time.current.at_end_of_day
from = (to - 6.day).at_beginning_of_day
@books = Book.includes(:favorited_users).
sort_by {|x|
x.favorited_users.includes(:favorites).where(created_at: from...to).size
}.reverse
@book = Book.new
end
今回はeach文でビューページに投稿された内容を一覧表示しています。
いいね数が多い順で表示させるためにコントローラー内で条件を定義してあげます。
上から順番に見ていきましょう。
to = Time.current.at_end_of_day
Time.current はconfig/application.rbに設定してあるタイムゾーンを元に現在日時を取得しています。
at_end_of_day は1日の終わりを23:59に設定しています。
from = (to - 6.day).at_beginning_of_day
()内はなんとなく分かりますね。
at_beginning_of_day は1日の始まりの時刻を0:00に設定しています。
上記2行を要約すると
一週間分のデータとってきたよーって感じです。笑
@books = Book.includes(:favorited_users).
今までは@books = Book.all で投稿されたデータを全て取得していましたが、どうやら誰が投稿したかという情報をユーザーテーブルに毎回取りに行っているそうです。
そこで includesの登場です。先程book.rbで記述した
has_many :favorited_users, through: :favorites, source: :user
のおかげでユーザーの情報がfavorited_usersに格納されていて、includesの引数に入れてあげることで、事前にユーザーのデータを読み込ませてあげることができます。これで無駄にSQL文が発行されなくなります。
sort_by {|x|
x.favorited_users.includes(:favorites).where(created_at: from...to).size
}.reverse
sort_byメソッドを使っていいね数を少ない順に取り出しています。
ブロック変数 |x| を定義してあげないと、2よりも10,11の方が小さいと判定されてしまうのでこのように対処するそうです。
ただ、このままだと少ない順に表示されてしまうので最後にreverseをつけてあげましょう。
これで昇順、降順を入れ替えることができます。
sort_byではなくsortを使って記述することもできます。
sort {|a,b|
a.favorited_users.includes(:favorites).where(created_at: from...to).size <=>
b.favorited_users.includes(:favorites).where(created_at: from...to).size
}.reverse
UFO演算子を使ってaとbを比較して返す記述方法です。
個人的にはsort_byの方が分かりやすくて記述も少ないので好きです。
それぞれのメリットデメリットはどうなのか把握できてないので気になる方は調べてみてください。
参考までにlink貼っておきます。
以上になります。
最後に
同じような場面で悩んでる方の助けになれば幸いです。
今後もゆるく投稿していこうと思います!
最後まで読んでいただきありがとうございました^^