рельсы находят: используя условия при включении одной и той же таблицы дважды через разные именованные ассоциации - PullRequest
7 голосов
/ 26 июля 2010

У меня есть сообщения, которые пользователи отправляют другим пользователям.Существует две модели -: post и: user, и: post имеет следующие именованные ассоциации:

belongs_to :from_user, :class_name => "User", :foreign_key => "from_user_id"
belongs_to :to_user, :class_name => "User", :foreign_key => "to_user_id"

Обе: user и: post имеют столбец "is_public", указывающий, что либо один пост, и / иливесь профиль пользователя может быть общедоступным или личным.

Моя цель - получить список сообщений, которые являются общедоступными И чьи получатели имеют публичные профили.В то же время я хотел бы «включить» информацию об отправителе и получателе, чтобы минимизировать количество вызовов в БД.Проблема в том, что я эффективно «включаю» одну и ту же таблицу дважды через именованные ассоциации, но в своих «условиях» мне нужно убедиться, что я фильтрую только по столбцу «is_public» получателя.

Я могуне делайте следующее, потому что «условия» не принимают имя ассоциации в качестве параметра:

Post.find(:all, :include => [ :to_user, :from_user ], 
  :conditions => { :is_public => true, :to_user => { :is_public => true }})

Таким образом, один из способов сделать это - выполнить дополнительное «соединение» с таблицей «пользователи»:

Post.find(:all, :include => [ :to_user, :from_user ], 
  :joins => "inner join users toalias on posts.to_user_id = toalias.id", 
  :conditions => { :is_public => true, 'toalias.is_public' => true })

Есть ли лучший, возможно, чище способ сделать это?

Заранее спасибо

Ответы [ 4 ]

1 голос
/ 17 октября 2012

Я не смог найти лучшего решения, чем было указано в моем вопросе. Это не зависит от того, как Rails присваивает имена / псевдонимы таблицам при компиляции запроса и, следовательно, выглядит чище, чем альтернативы (за исключением использования сторонних гемов или плагинов):

Post.find(:all, :include => [ :to_user, :from_user ],
:joins => "inner join users toalias on posts.to_user_id = toalias.id", 
:conditions => { :is_public => true, 'toalias.is_public' => true })
1 голос
/ 21 декабря 2011

Я столкнулся с той же проблемой и нашел решение после просмотра sql-запроса, сгенерированного из запроса rails, sql-запрос автоматически генерирует псевдоним. Попробуйте это,

Post.find(:all, :include => [ :to_user, :from_user ], 
       :conditions => { :is_public => true, 'to_users_posts.is_public' => true })

Это сработало для меня:

0 голосов
/ 15 февраля 2017

Мне очень нравится этот вопрос, потому что я пытался найти правильное решение около 2 часов, поэтому после нескольких советов, приведенных выше, я нашел правильное, в моем случае, решение.Мой случай: мне нужно фильтровать экземпляры по полям create_by_id / updated_by_id, чтобы поля были в каждой таблице, так что ... что я сделал В отношении 'Filterable' я написал метод, и когда мне понадобился фильтр по этим полям, я использовал это ->

key = "# {key.pluralize} _ # {name.pluralize.downcase} .email", если% w (создал_by updated_by) .include? (Ключ)

# in case with invoices key = 'updated_bies_invoices.email'

results = results.eager_load (: creation_by,: updated_by) .where ("# {key} =?", Значение)

0 голосов
/ 21 декабря 2011

Если вы на Rails 3, взгляните на squeel gem , особенно если вы часто выполняете подобные сложные соединения. Или, если вы не хотите добавлять дополнительный драгоценный камень, посмотрите на таблицу Arel в Rails 3.

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