Использование OR с запросами в области
В Rails3 у меня есть:
Class Teacher
# active :boolean
has_and_belongs_to_many :subjects
Class Subject
# active :boolean
has_and_belongs_to_many :teachers
Я пытаюсь построить область Учителя, которая возвращает все Teachers
которые active
или связаны с Subject
то есть active
,
Эти области работают индивидуально, но как объединить их как единую область с операционными системами?
scope :active_teachers, where(active: true)
scope :more_active_teachers, joins(:subjects).where(:subjects => {active: true})
Я попробовал это без успеха:
scope :active_teachers, where(active: true).or(joins(:subjects)
.where(:subjects => {active: true}))
ОБНОВИТЬ:
Я думал, что у меня есть решение, но оно больше не лениво загружается, дважды попадает в базу данных и, что самое важное, возвращает массив, а не объект AR!
scope :active_teachers, where(active: true) |
joins(:subjects).where(:subjects => {active: true})
4 ответа
У тебя есть Squeel
to your rescue. Подробнее здесь.
Using that, you could define something like:
class Teacher
...
scope :active_teachers, joins{subjects}.where {(active == true) | (subjects.active == true)}
...
end
Я думаю, что краткий ответ: ты не можешь.
Ориентация в коде может прервать ленивую загрузку... на самом деле это никак не обойти, так как вам нужна база данных для оценки. ActiveRecord не может выполнять оценки в областях, не выполняя каждый подпункт отдельно.
Примерно так должно работать следующее:
joins(:subjects).where("subjects.active = true OR teachers.active = true")
Не так элегантно, но может быть включено в метод для повторного использования.
Вы можете решить эту проблему, перейдя на AREL. Смотрите этот вопрос так, как это сделать.
Или из исходного кода AREL README.md. Я думаю (но не проверил), что это приведет к следующему для вашего конкретного примера.
teachers.where(teachers[:active].eq(true).or(subjects[:active].eq(true)))
Удачи!
Для этого есть запрос на извлечение rails ( https://github.com/rails/rails/pull/9052), но тем временем кто-то создал патч обезьяны, который вы можете включить в свои инициализаторы, что позволит вам сделать это. это и до сих пор дает вам ActiveRecord::Relation
:
https://gist.github.com/j-mcnally/250eaaceef234dd8971b
С этим вы сможете или ваши прицелы, как это
Teacher.active_teachers.or.more_active_teachers
или напишите новую область
scope :combined_scopes, active_teachers.or.more_active_teachers