3
1

More than 1 year has passed since last update.

【Rails】過去一週間でいいねされた数を多い順でソートする

Posted at

初めに

プログラミング初学者2ヶ月目です。
今回が初投稿となります。
自身の忘備録として記事を更新していこうと思いますので、もし間違いなどありましたらご指摘頂けると幸いです。

アソシエーション

user.rb
has_many :books, dependent: :destroy
has_many :favorites, dependent: :destroy
book.rb
belongs_to :user
has_many :favorites, dependent: :destroy
has_many :favorited_users, through: :favorites, source: :user
favorite.rb
belongs_to :user
belongs_to :book

userモデル,bookモデル,favoriteモデルのアソシエーションが完成しました。
has_many :favorited_users, through: :favorites, source: :user
はfavoritesモデルを介してuserモデルのデータを持ってくるという記述になります。
この解釈が正しいかわかりませんがそんな感じです。笑

コントローラー

book_controller.rb
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貼っておきます。

以上になります。

最後に

初めての投稿で拙い説明、合ってるかも少し不安な点も多々有りますがご容赦いただけると幸いです。
冒頭でもお伝えした通り、間違いがあればご指摘ください。
今後も定期的に更新していけたらと思いますので、その際はよろしくお願いします。
最後までありがとうございました。

3
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1