2016-06-30 2 views
1

У меня две модели с ассоциациями has_many through; Taskflows и Datasets. Они имеют таблицу соединений, которая называется DatasetAssignments.Как получить все ассоциации has_many из активной коллекции записей

Я получаю все Taskflows с помощью:

@taskflows = Taskflows.all

Я знаю, что это возможно, чтобы получить ассоциации из одного объекта ActiveRecord, например:

@taskflow.datasets

, но это возможно, чтобы получить все связанных Datasets от @taskflows Коллекция ActiveRecord? Такие, как @taskflows.datasets

Любая помощь будет очень признательна.

Модель:

class Dataset < ActiveRecord::Base 
    has_many :dataset_assignments 
    has_many :taskflows, :through => :dataset_assignments 
end 

class Taskflow < ActiveRecord::Base 
    has_many :dataset_assignments 
    has_many :datasets, :through => :dataset_assignments 
end 

class DatasetAssignment < ActiveRecord::Base 
    belongs_to :dataset 
    belongs_to :taskflow 
end 

ответ

3

Учитывая, что @taskflows является ActiveRecord::Relation, вы можете сделать это:

@datasets = Dataset.joins(:dataset_assignments). 
    where(dataset_assignments: {taskflow: @taskflows.joins(:datasets) }) 

или, в другом направлении:

@taskflows = Taskflow.joins(:dataset_assignments). 
    where(dataset_assignments: {dataset: @datasets.joins(:taskflows) }) 

joins генерирует INNER JOIN с помощью таблицы «многие-ко-многим» и имеет приемник, являющийся экземпляром ActiveRecord::Relation, который сохранит другие условия.

Как @oreoluwa предположил, что вы можете избежать N + 1 запросов при перечислении с помощью includes:

@taskflows = Taskflow.joins(...).includes(:datasets) 
+0

спасибо, есть ли разница между выполнением '@ datasets.joins (: taskflows)' и '@datasets .joins (@taskflows) '- @taskflows, исходящие из предыдущего запроса? – RobotEyes

+0

Держитесь, есть проблема с этим. Вы получаете те же записи классов, что и ваш ресивер. Когда '@ datasets' является ресивером, набор данных - это то, что вы получаете, но вам нужны потоки задач. –

+0

Я обновил свой ответ с правильным решением. –

1

Я не думаю, что есть способ сделать это, если у вас есть внешняя модель, давай назовем его пользователь, где:

User 
    has_many :taskflows 
    has_many :datasets, through: :taskflows 

или лучше пусть ваш DatasetAssignment принадлежит пользователю и выбирает все dataset_assignments конкретного Пользователя.

Другим подходом было бы сделать @taskflows.map(&:datasets), но это не эффективно.

Или, если вам нужно только datasets, чтобы сделать где-то и беспокоили о ЭФФЕКТИВНОСТИ, вы должны использовать AR#includes метод, как:

@taskflow.includes(:datasets)

Смежные вопросы