Можно ли использовать условие с количеством в отношении has_many? - PullRequest
3 голосов
/ 21 марта 2012

У меня есть список проектов, и я хочу отображать только те проекты, в которых есть задачи. Можно ли использовать условие с количеством в отношении has_many?

# get my project list
Project.includes(:tasks).where(...)

class Project < ActiveRecord::Base
  has_many :tasks

class Task < ActiveRecord::Base
  belongs_to :project

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

Ответы [ 3 ]

1 голос
/ 21 марта 2012

Если вопрос так прост, как следует из заголовка, не уверен, почему это не сработает:

Project.joins(:tasks)

Если не указано иное, объединение будет внутренним объединением и, таким образом, исключает любыерезультаты, проекты которых не имеют задач, поэтому, возможно, это все, что вам нужно ... если вы хотите отобразить все проекты с задачами.

если у вас есть какое-то условие (например, проекты,статус активен) вы также можете указать условие типа

Project.joins(:tasks).where("status = 'active')

Или я что-то пропустил?

1 голос
/ 21 марта 2012

Поскольку вы уже готовы загрузить задачи для проекта, вы можете использовать следующую инструкцию, чтобы получить проекты с задачами.

# get my project list
Project.includes(:tasks).where("tasks.id IS NOT NULL")

Это работает, потому что includes использует LEFT OUTER JOIN.

С другой стороны, если вы не хотите загружать задачи, вы можете использовать joins, так как он использует INNER JOIN.

Project.joins(:tasks).where(...)
1 голос
/ 21 марта 2012

Директива includes часто указывает на простую загрузку этих ассоциаций, а не JOIN их в базе данных, так что вы не можете выполнить условия здесь без дополнительной работы.

В одну сторонуЭто хорошо масштабируется, если использовать функцию counter_cache ассоциации, чтобы у вас всегда был числовой счетчик количества задач.Вы даже можете добавить к ним индекс, чтобы еще больше повысить производительность вашего запроса.

Альтернативой является попытка работать в обратном направлении из таблицы tasks, например:

Project.where('id IN (SELECT DISTINCT project_id FROM tasks)')

Предположительно у вас есть индекс project_id в вашей таблице tasks, чтобы сделать эту операцию довольно недорогой.

...