Rails: возвращает отдельные объекты, хотя бы с одной ассоциацией удовлетворяющие условию

#ruby-on-rails #rails-activerecord

#ruby-on-rails #rails-activerecord

Вопрос:

Хорошо, у меня есть 3 таблицы:

  • lessons : в котором много new_words
  • new_words : которые принадлежат уроку и имеют word_type столбец (глагол, прилагательное, существительное и т.д.)
  • verb_forms :
    • с каждым новым словом, которое имеет, word_type = Verb будет связано 1 verb_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 }