LoginSignup
0
0

いいねの合計カウントが多い順に投稿を表示する

Last updated at Posted at 2023-07-04

今回は、本の投稿一覧ページで、過去一週間でいいねの合計カウントが多い順に投稿を表示して行きます!

初めに 

本投稿アプリ作成中!
:shamrock: 前提条件
・device導入 ・Bootstrap導入
・ユーザー機能実装済(Userモデル)
・投稿機能実装済(Bookモデル)
・いいね機能実装済 (favoriteモデル)


:shamrock: アソシエーション追加

:star:has_many :favorited_users, through: :favorites, source: :user を追記します。

この関連付けは、多対多の関係を持つモデル間の関連付けを簡潔に表現するためのコードであり、中間テーブルを介して関連するモデルにアクセスすることができるようにします。

:snowflake:through: :favorites, source: :user
(投稿モデルが直接ユーザーモデルにアクセスすることができるようにする。)
:snowflake:through: :favorites
(中間テーブルを指定しています。中間テーブルは、投稿とユーザーの関連付けを繋ぐ役割を果たす)

この関連付けを使うことで、投稿モデルからfavorited_usersというメソッドを呼び出すことができます。これにより、投稿にお気に入りをしたユーザーのリストを取得することができます。

book_rbに以下のように追加

class Book < ApplicationRecord
  belongs_to :user
   has_many :book_comments, dependent: :destroy
   has_many :favorites, dependent: :destroy
+  has_many :favorited_users, through: :favorites, source: :user
   
  validates :title,presence:true
  validates :body,presence:true,length:{maximum:200}
  
  def favorited_by?(user)
    favorites.exists?(user_id: user.id)
  end

favorite.rb (今回は特に追加なし)

favorite.rb
class Favorite < ApplicationRecord
  belongs_to :user
  belongs_to :book
end

user.rbになければ以下のように追加する。

 has_many :books
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
         
+  has_many :books, dependent: :destroy
  has_many :book_images, dependent: :destroy
  has_many :book_comments, dependent: :destroy
  has_one_attached :profile_image
+  has_many :favorites, dependent: :destroy   

:shamrock:コントローラ

books_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 {|a,b| 
        b.favorited_users.includes(:favorites).where(created_at: from...to).size <=> 
        a.favorited_users.includes(:favorites).where(created_at: from...to).size
      }
    @book = Book.new
    @user = current_user

:star: to 変数は現在の日時の終わりを表し、from 変数はそれから6日前の日時の始まりを表しています。

to  = Time.current.at_end_of_day
 from  = (to - 6.day).at_beginning_of_day

:star:Bookモデルのデータを取得し、それに関連するfavorited_users(いいねをしたユーザー)のデータも同時に取得しています。
その後、sortメソッドを使用してデータの並び替えを行っています。
ブロック内のコード |a,b| は、2つのBookオブジェクトを比較して、どちらのオブジェクトがより多くのいいねを持っているかを判断しています。

 @books = Book.includes(:favorited_users).
      sort {|a,b| 

:star:b.favorited_users.includes(:favorites).where(created_at: from...to).size は、
オブジェクトbに関連するfavorited_users(いいねをしたユーザー)の中で、指定された期間(fromからto)に作成されたいいねの数を取得しています。
:point_up:具体的には、includes(:favorited_users) がプリロードの処理を行っています。

:star:同様に、a.favorited_users.includes(:favorites).where(created_at: from...to).size は、
オブジェクトaに関連するfavorited_usersの中で、指定された期間に作成されたいいねの数を取得しています。
そして、これらのいいねの数を比較して、並び替えの基準となる値を返しています。<=>演算子は比較演算子であり、左辺と右辺を比較し、結果に基づいてソートの順序を決定します。

 b.favorited_users.includes(:favorites).where(created_at: from...to).size <=> 
 a.favorited_users.includes(:favorites).where(created_at: from...to).size

:beginner:リファレンスマニュアル
https://docs.ruby-lang.org/ja/latest/method/Array/i/sort.html

:question:プリロードとは
関連するデータを効率的に取得するための手法です。
プリロードを使用すると、事前に関連するデータをまとめて取得することができます。これにより、データベースへのアクセス回数を減らし、処理速度を向上させることができます。上記のコードでは、 Book.includes(:favorited_users) という部分がプリロードの例です。これにより、Bookオブジェクトと関連するfavorited_users(いいねをしたユーザー)のデータを一括で取得しています。

0
0
0

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
0
0