.pluck
возвращает массив значений, а не ActiveRecord :: Relation.
Так что когда вы делаете distinct_question_ids.select
, вы не вызываете select
ActiveRecord, а select
массива.В рамках этого выбора вы запускаете новый новый запрос к @user для каждого только что набранного идентификатора - включая те, которые отклоняются в выборе.
Вы можете создать запрос с именем distinct_questions
, который возвращаетсвязь (без отрыва!), а затем создайте correct_on_first_attempt
из этого, и я думаю, что вы избежите N + 1 запросов.
Что-то вроде этого:
class UserAnswer < ActiveRecord::Base
scope :distinct_correct, -> { includes(:multiple_choice_question)
.where(is_correct_answer: true).distinct }
scope :first_attempt_correct, -> { distinct_correct
.first.is_correct_answer }
end
class User < ActiveRecord::Base
def good_guess_count
@correct_on_first_attempt = @user.user_answers.distinct_correct.first_attempt_correct.count
end
end
Вам нужно убедиться, что .first действительно получает свою первую попытку, возможно, путем сортировки по id или create_at.
В качестве отступления, если вы явно отслеживаете номер попытки в UserAnswer, вы действительно можете это сузить:
class UserAnswer < ActiveRecord::Base
scope :correct, -> { where(is_correct_answer: true) }
scope :first_attempt, -> { where(attempt: 1) }
end
class User < ActiveRecord::Base
def lucky_guess_count
@correct_on_first_attempt = @user.user_answers.includes(:multiple_choice_question)
.correct.first_attempt.count
end
end
Если у вас нет номера попытки в вашей схеме, вы можете .order и .group получить что-то подобное.Но ... кажется, что некоторые требования вашего проекта зависят от этого порядкового номера, поэтому я рекомендую добавить его, если у вас его еще нет.
пс.Для борьбы с N + 1 запросами используйте gem bullet.Это на месте.