scope_method для возврата user_id с большинством отзывов - PullRequest
0 голосов
/ 28 апреля 2020

У меня есть схема с отзывами для моего веб-сайта.

  create_table "reviews", force: :cascade do |t|
    t.integer "stars"
    t.string "title"
    t.string "content"
    t.integer "turtle_id"
    t.integer "user_id"
  end

Я пытаюсь написать scope_method, который возвращает user_id с наибольшим количеством отзывов. Я понимаю, что должен написать запрос sql, который подсчитывает несколько экземпляров user_id, а затем возвращает user_id. Но я потерян при этом.

Это то, что у меня есть до сих пор.

 scope :most_reviews, -> { 
    where("select count(*) c from reviews group by user_id order by c desc limit 1")
  }

Затем я вызываю его с моего контроллера так:

  def index
    @most_reviewed = Review.most_reviews
    puts @most_reviewed
  end

Как я могу правильно написать этот scope_method, чтобы вернуть user_id в обзорах с наибольшим количеством обзоров (в других случаях)? Также это должен быть scope_method.

Ответы [ 2 ]

3 голосов
/ 28 апреля 2020

Если ваша конечная цель на самом деле является пользователем, вы начинаете не с того конца.

class User < ApplicationRecord
  has_many :reviews

  def self.most_reviews
    select('users.*', 'COUNT(reviews.*) AS reviews_count')
      .joins(:reviews)
      .group(:id)
      .order(reviews_count: :desc)
  end
end

scope - это просто syntacti c сахар для определения однострочника методы класса. На самом деле нет ничего особенного в методах, которые он объявляет, и использование его в случаях, когда код не помещается в одну строку, просто ухудшает читабельность.

Вы также можете установить кеш счетчика , который позволит вам упростить это до:

class Review < ApplicationRecord
  belongs_to :user, counter_cache: true
end

class User < ApplicationRecord
  has_many :reviews
  scope :most_reviews, ->{ order(reviews_count: :desc) }
end

То, что действительно вписывается в однострочную область видимости.

0 голосов
/ 01 мая 2020

Попробуйте это

Контроллер:

  def index
    @most_reviewed = Review.most_reviews.first
    puts @most_reviewed
  end

Область применения:

  scope :most_reviews, -> { select("users.id, COUNT(reviews.user_id) AS reviews_count")
      .joins(:reviews)
      .group(:id)
      .order(reviews_count: :desc)
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...