Как активно загружать объекты с помощью специального соединения в рельсах? - PullRequest
30 голосов
/ 25 сентября 2008

Фон

Обычные рельсы, готовые к загрузке коллекций, работают так:

Person.find(:all, :include=>:companies)

Это генерирует некоторый sql, который делает

LEFT OUTER JOIN companies ON people.company_id = companies.id

Вопрос

Однако мне нужно пользовательское объединение (это также может возникнуть, если я использую find_by_sql), поэтому я не могу использовать ваниль :include => :companies

Пользовательское объединение / sql даст мне все данные, которые мне нужны, но как я могу сказать activerecord, что он принадлежит связанным объектам Company, а не просто как куча дополнительных строк?

Обновление

Мне нужно поставить дополнительные условия в объединении. Примерно так:

SELECT blah blah blah
LEFT OUTER JOIN companies ON people.company_id = companies.id AND people.magical_flag IS NULL 
<Several other joins>
WHERE blahblahblah

Ответы [ 4 ]

7 голосов
/ 25 сентября 2008

Не можете ли вы добавить условия объединения с помощью ActiveRecord?

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

Contractors.find(
  :all, 
  :include => {:council_areas => :suburbs},
  :conditions => ["suburbs.postcode = ?", customer.postcode]                 
)    

Предполагая, что:

  1. Подрядчики имеют множество советов.
  2. Совет Районы имеют множество пригородов

Это объединение возвращает подрядчиков в пригороде, обозначенных customer.postcode .

Сгенерированный запрос выглядит так:

SELECT contractors.*, council_areas.*, suburbs.*
FROM `contractors` 
LEFT OUTER JOIN `contractors_council_areas` ON `contractors_council_areas`.contractor_id = `contractors`.id 
LEFT OUTER JOIN `council_areas` ON `council_areas`.id = `contractors_council_areas`.council_area_id 
LEFT OUTER JOIN `council_areas_suburbs` ON `council_areas_suburbs`.council_area_id = `council_areas`.id 
LEFT OUTER JOIN `suburbs` ON `suburbs`.id = `council_areas_suburbs`.suburb_id WHERE (suburbs.postcode = '5000')

(Примечание: я отредактировал список столбцов для краткости).

3 голосов
/ 15 марта 2010

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

Person.reflect_on_association(:companies).options[:conditions] = 'people.magical_flag IS NULL'
2 голосов
/ 06 декабря 2012

Я не уверен, что это то, что вы хотите (я не уверен на 100%, что понял ваш вопрос и что вы хотите достичь), но:

Как насчет предоставления :joins и :includes?

Person.find( :all, :joins => 'LEFT OUTER JOIN companies ON people.company_id = companies.id AND _pass_custom_conditions_here_', :includes => :companies )

или AR3 путь:

Person.includes(:companies).joins('LEFT OUTER JOIN companies ON people.company_id = companies.id AND _pass_custom_conditions_here_')

1 голос
/ 25 сентября 2008

Не могли бы вы подробнее рассказать о том, что именно вы пытаетесь выполнить с помощью этого запроса?

Также обратите внимание на параметр: join для поиска. Это позволяет вам указать, как вы хотите, чтобы таблицы соединялись. текст ссылки

И будьте осторожны при использовании: include, поведение немного меняется в Rails 2.1 и может вызвать некоторые проблемы при использовании вместе с опцией: condition, которая ссылается на включенную таблицу. текст ссылки и текст ссылки - две статьи из Pivotal, в которых упоминается эта ошибка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...