Как получить объекты некоторой модели и связанные с ней объекты условно через объект промежуточной модели, используя ActiveRecord - PullRequest
1 голос
/ 19 января 2011

Как я могу условно получить объекты какой-либо модели и связанные с ней объекты модели через промежуточный объект модели?Затем он будет использоваться для генерации JSON (через to_json).

Вот настройка, сделанная более общей:

class JobSet < ActiveRecord::Base
  belongs_to :job_system
  has_many :resources, through => :job_system
  has_many :jobs
  ...
end

class JobSystem < ActiveRecord::Base
  has_many :job_sets
  has_many :resources
  ...
end

class Resource < ActiveRecord::Base
  belongs_to :job_system
  has_many_and_belongs_to_many :jobs
  ...
end

class Job < ActiveRecord::Base
  belongs_to :job_system
  belongs_to :job_set
  has_many_and_belongs_to_many :resources
  ...
end

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

ОБНОВЛЕНИЕ : даже если с ресурсом не связано никаких заданий, я все равно хочу его получитьс остальными ресурсами.Цель состоит в том, чтобы отобразить все ресурсы с назначенными им заданиями.

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

Есть ли хорошее название для этого типа проблемы?Есть ли простой способ сделать это?

ОБНОВЛЕНИЕ 2 : Кажется, есть решения, которые хорошо работают в контроллере, но я использую to_json в представлении, чтобы предварительно загрузить элемент холста,Кажется, автоматически включаются все задания, когда я делаю это:

var resources = <%= @resources.to_json(:include => {:jobs => {:only => :id}}) %>; 

Может ли ручной JOIN SQL помочь с этим?

Ответы [ 2 ]

1 голос
/ 19 января 2011

Я думаю, я знаю, что вы после. Единственное, о чем я бы вас просил, это о том, что если у ресурса нет заданий в этом конкретном наборе заданий, его все равно следует включить?

В любом случае, вот один из способов сделать это:

@resources = Resource.all(:include => :jobs,
                          :conditions => ["jobs.job_set_id = ?", @job_set.id])

Это НЕ будет включать ресурсы, у которых нет заданий, связанных с @ job_set

Итак, я совершенно не прав в своих предположениях, или это было то, что вы после?

Редактировать

Хорошо, это было сложнее, чем я думал. Есть несколько решений, но ни одно из них мне не нравится. Вы можете сделать так:

@resources = Resource.all

@resources.each do |resource|
  resource.jobs.all(:conditions => ["jobs.job_set_id = ?", @job_set_id])
end

Но это приведет к тому, что проблема количества запросов 1 + n окажет давление на вашу базу данных.

Вы также можете сделать так:

@resources = Resource.all(:include => :jobs)

@resources.each do |resource|
  resource.jobs.select{ |job| job.job_set_id == @job_set_id }
end

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

Проблема с поиском лучшего решения, на мой взгляд, заключается в том, что это то, что должно быть указано в условии SQL JOIN, но я не думаю, что ActiveRecord позволяет нам изменять это в сочетании с активной загрузкой.

0 голосов
/ 19 января 2011

Вы должны быть в состоянии сделать это довольно простым способом, но вам может понадобиться набор в определенном формате или структуре, отличной от приведенной здесь:

@resources = @job_set.resources.include(:jobs)

Как примечание, я бы рекомендовал не использовать объявления стиля has_many_and_belongs_to_many в Rails 1. Используемые ими таблицы соединений не основаны на моделях, и ими очень трудно манипулировать, особенно если с ними связаны метаданные, по сравнению с более современным подходом модели соединений. Вы просто создаете модель с именем JobResource или ResourceJob в зависимости от того, как вы хотите расставить приоритеты, и строите две belongs_to взаимосвязи, чтобы объединить их вместе.

...