Activerecord: включить дополнительные условия - PullRequest
1 голос
/ 30 марта 2011

Как указать условие JOIN ON в ActiveRecord?

При использовании параметра: include для метода ActiveRecord.find созданный SQL использует операцию JOIN с предложением ON внешнего ключа = первичного ключа.,Например:

A.find(:include => :B) 

приводит к

select ... from A 
  left outer join B on B.a_id=A.id

Теперь к моему примеру:

A.find(:include => { :B => { :include => :C } } )

приводит к:

select ... from A 
  left outer join B on B.a_id=A.id 
  left outer join C on C.b_id=B.id

НоЯ хочу только некоторые записи в C, но если они не найдены, я все еще хочу A и B

Это не работает

A.find(:include => { :B => { :include => :C } },
  :condition => "C.rec<10" )

Поскольку это приводит к:

select ... from A 
  left outer join B on B.a_id=A.id 
  left outer join C on C.b_id=B.id
  where C.rec<10

Как мне поручить AcriveRecord создать такой запрос?

select ... from A 
  left outer join B on B.a_id=A.id 
  left outer join C on C.b_id=B.id and C.rec<10

Ответы [ 2 ]

1 голос
/ 20 июля 2012

Я не знаю, как добавить предложение ON с помощью методов ассоциации.

Для вашего примера, самый простой способ загружать только некоторые записи в C - это определить связь с условиями вB. (См. Раздел «Готовая загрузка ассоциаций» этой ActiveRecord :: Документации API ассоциаций .)

class A < ActiveRecord::Base
    has_many :bs
end

class B < ActiveRecord::Base
    has_many :cs
    has_many :cs_with_rec_less_than_10, :class_name => 'C', :conditions => ['rec < 10']
end

class C < ActiveRecord::Base
end

Вы можете позвонить:

A.includes(:bs => :cs_with_rec_less_than_10)

Это создаст 3 запроса, по одному на каждую таблицу, а не объединит их в 1 запрос.Например, если A и B содержат по две записи с идентификаторами 1 и 2:

SELECT "as".* FROM "as"
SELECT "bs".* FROM "bs" WHERE ("bs".a_id IN (1,2))
SELECT "cs".* FROM "cs" WHERE ("cs".b_id IN (1,2) AND (rec < 10))

Если важно сделать один запрос с использованием левых соединений, я бы написал запрос вручную, выполнив его с ActiveRecord::Base.connection.executeи обработайте результат напрямую.

0 голосов
/ 31 мая 2011

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

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

@visits = Visit.select("v.*, c.*" ).
  where("u.id = ?", session[:user_id]).
  joins( %{ as v inner join customers as c on (v.customer_id = c.id)
      inner join businesses as b on (v.business_id = b.id)
      inner join managers as m on (b.manager_id = m.id)
      inner join users as u on (m.user_id = u.id)
      } ).
  order(' v.created_at DESC')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...