#ruby-on-rails #rails-activerecord
#ruby-on-rails #rails-activerecord
Вопрос:
Хорошо, у меня есть 3 таблицы:
lessons
: в котором много new_wordsnew_words
: которые принадлежат уроку и имеютword_type
столбец (глагол, прилагательное, существительное и т.д.)verb_forms
:- с каждым новым словом, которое имеет,
word_type = Verb
будет связано 1verb_form
. verb_forms
имеет столбецverb_type
, в котором указан тип глагола (1,2 или 3)
- с каждым новым словом, которое имеет,
Итак, теперь я хочу запросить все уроки, в которых есть хотя бы 1 Verb
, который имеет verb_type = 1
Пока что я заархивировал это:
class VerbForm < ApplicationRecord
belongs_to :new_word
scope :first_type, -> { where(verb_type: 1) }
end
class NewWord < ApplicationRecord
has_one :verb_form, dependent: :destroy, inverse_of: :new_word
scope :ftv, -> { verbs.joins(:verb_form).merge(VerbForm.first_type) }
end
class Lesson < ApplicationRecord
has_many :new_words
scope :with_ftvs, -> { joins(:new_words).merge(NewWord.ftv) }
end
Теперь, если я запущу Lesson.with_ftvs
, каждый урок будет отображаться несколько раз, в зависимости от количества глаголов первого типа в этом уроке (например, если в уроке 1 есть 3 глагола первого типа, то lesson 1
они возвращаются 3 раза в приведенном выше запросе)
Итак, как я могу получить список отдельных уроков?, Я попробовал этот запрос, но он вернул nil ?
scope :with_ftvs, -> { joins(:new_words).merge(NewWord.ftv).distinct }
p / s: Я всегда думал, что count
и length
это одно и то же. Но когда я пробую это с моим исходным запросом: Lesson.with_ftvs.count
vs Lesson.with_ftvs.length
, они возвращают разные значения:
Комментарии:
1.
.count
выполняет запрос SQL count — и возвращает целое число..length
извлекает записи, а затем измеряет количество элементов в коллекции..size
выполняет либо в зависимости от того, была ли коллекция уже загружена. batsov.com/articles/2014/02/17 /…2. что касается nil из distinct. какая у вас версия rails? distinct ведет себя по-разному в rails 3
Ответ №1:
В SQL соединения могут возвращать дублированные результаты, поэтому вам следует либо использовать distinct, либо группировать по некоторому столбцу.
scope :with_ftvs, -> { joins(:new_words).merge(NewWord.ftv).group("lessons.id") }
# or
scope :with_ftvs, -> { joins(:new_words).merge(NewWord.ftv).distinct }