Как можно загружать объекты с помощью пользовательского соединения в рельсах?
Фон
Обычная рельсовая загрузка коллекций работает следующим образом:
Person.find(:all, :include=>:companies)
Это генерирует некоторый sql, который делает
LEFT OUTER JOIN companies ON people.company_id = companies.id
Вопрос
Однако мне нужно настраивать соединение (это также может возникнуть, если я использовал find_by_sql
), поэтому я не могу использовать vanilla :include => :companies
Пользовательское соединение /sql доставит мне все нужные мне данные, но как я могу сообщить activerecord, что он принадлежит связанным объектам Company
, а не просто быть кучей дополнительных строк?
Update
Мне нужно добавить дополнительные условия в соединение. Что-то вроде этого:
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
Ответы
Ответ 1
Не можете ли вы добавить условия соединения с помощью ActiveRecord?
Например, у меня довольно сложный запрос с использованием нескольких зависимых записей, и он отлично работает, комбинируя условия и включающие директивы
Contractors.find(
:all,
:include => {:council_areas => :suburbs},
:conditions => ["suburbs.postcode = ?", customer.postcode]
)
Предполагая, что:
- Подрядчики have_many CouncilAreas
- СоветAreas have_many Suburbs
Это объединение возвращает Подрядчиков в пригороде, обозначенных 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')
(Примечание: я сократил список столбцов для краткости).
Ответ 2
Вы можете использовать что-то вроде следующего, чтобы получить синтаксическую магию левого внешнего соединения.
Person.reflect_on_association(:companies).options[:conditions] = 'people.magical_flag IS NULL'
Ответ 3
Я не уверен, что вы хотите (я не уверен на 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_')
Ответ 4
Можете ли вы подробнее рассказать о том, что вы пытаетесь выполнить с помощью этого запроса?
Также взгляните на параметр: join для поиска. Он позволяет указать, как вы хотите, чтобы таблицы были соединены. текст ссылки
И будьте осторожны при использовании: include, поведение немного изменится в Rails 2.1 и может вызвать некоторые проблемы при использовании в сочетании с опцией: условия, которая ссылается на включенную таблицу. текст ссылки и ссылка текст - это две статьи из Pivotal, в которых упоминается эта информация.