Объединение пользовательских соединений с регулярными соединениями рельсов - PullRequest
2 голосов
/ 07 апреля 2011

У меня есть модели foo, bar и baz, вот так

# has a field join_condition_string
class Foo < AR::Base
    :has_many :bar
end

# Has a field exclusion_critera
class Bar < AR::Base
    :belongs_to foo
end

# has a fields condition_string, exclusion_criteria
class Baz < AR::Base
end

Я хочу иметь возможность получать Foo на основе критериев как Bar, так и Baz.Поэтому мне нужно присоединиться к обеим моделям.Я хочу присоединиться к Bar, используя rails magic,

Foo.find(:all, :joins => :bar)

И я хочу присоединиться к Baz, используя пользовательское объединение.

Foo.find(:all, :joins=>"left join baz on baz.condition_string = foo.join_condition_string")

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

Я пытался сделать наивную вещь и объединить два условия в массиве, но безрезультатно.

Foo.find(:all, :joins=>["left join baz ...", :bar])

документы утверждают, что я могу сделать Foo.find(:all, :joins => :bar, :joins => "left join baz ..."), но это не похоже на то, что это должно работать (и это не работает в рельсах 2.3.8), потому что аргументы для поиска заключены в хеш и первое:присоединения потеряны.

Конечно, я всегда мог объединить два в одну строку: объединения.Тем не менее, как эти два вызова могут быть объединены с как можно меньшим необработанным SQL?Любые идеи?

РЕДАКТИРОВАТЬ: принятый ответ действительно отвечает на мой вопрос, но я все еще думаю, что мог бы быть лучший способ.

РЕДАКТИРОВАТЬ 2: Как упомянул rubyprince, это было решено в рельсах>= 3.0.0

1 Ответ

2 голосов
/ 07 апреля 2011

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

class Foo < AR::Base
  has_many :bars
  named_scope :joined_bars, :joins => :bars
  named_scope :joined_baz, :joins => "LEFT JOIN baz on ..."
end

Тогда вы можете вызвать его в контроллере, как это

Foo.joined_bars.joined_baz

Вы можете добавить любые условия или другие параметры к выбранному, как это

Foo.joined_bars.joined_baz.all(:conditions => ..,
                               :limit => ..)

Это создаст один SQL-запрос со всеми объединениями, где, предел и т. Д.

...