2017-01-18 2 views
0

Я пытался использовать эту функциональность, введенную в #645 с условными отношениями has_many ... through с небольшим успехом.Уважайте негативные условия для расширенных ассоциаций сбора

В моем случае:

  • курс обучения has_many :user_assigned_content_skills, -> { where(source: 'user') }, class_name: "ContentSkill"
  • и ContentSkill belongs_to :skill и belongs_to :course

Затем Course.ransack({user_assigned_content_skills_skill_name_not_cont: 'ruby'}).result.to_sql возвращает следующее:

"SELECT courses.* FROM courses LEFT OUTER JOIN content_skills ON content_skills.course_id = courses.id AND content_skills.source = 'user' LEFT OUTER JOIN skills ON skills.id = content_skills.skill_id WHERE (skills.name NOT ILIKE '%ruby%')"

Это снова означает ложные срабатывания, если курс имеет несколько content_skills. Любые идеи о том, как получить все курсы, не связанные с данным именем навыка?

Большое спасибо за любые идеи!

ответ

1

Вы можете получить идентификаторы курсов, связанных с заданным именем мастерства, а затем получить список курсов с идентификаторами, которые не соответствуют предыдущему найденному. Вы даже можете сделать это как один составной SQL-запрос.

Course.where.not(id: Course.ransack({user_assigned_content_skills_skill_name_cont: 'ruby'}).result) 

Это будет генерировать SQL как это:

SELECT courses.* 
FROM courses 
WHERE courses.id NOT IN (
    SELECT courses.id FROM courses 
    LEFT OUTER JOIN content_skills ON content_skills.course_id = courses.id AND content_skills.source = 'user' 
    LEFT OUTER JOIN skills ON skills.id = content_skills.skill_id 
    WHERE (skills.name ILIKE '%ruby%') 
)