Rails 3 условия для загруженной ассоциации - PullRequest
2 голосов
/ 04 февраля 2011

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

@post = Post.includes(:comments).where(:comments => { :approved => true }).find(1)

Это сгенерирует запрос SQL, подобный следующему:

SELECT DISTINCT `posts`.id FROM `posts`
LEFT OUTER JOIN `comments` ON `comments`.`post_id` = `posts`.`id`
WHERE (`comments`.`approved` = 1) AND (`posts`.`id` = '1')
LIMIT 1

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

Как правильно загрузить сообщение и связанные комментарии с условием для комментариев?

Обновление

Я бы по-прежнемуМне нравится слышать лучший способ сделать это, но сейчас я использую следующее, чтобы обойти это (работает с глубоко вложенной энергичной загрузкой):

@post = Post.find(1)
@comments = @post.comments.where(:approved => true).all

# allows deeper/more complex nesting without getting into SQL:
@post = Post.includes(:author => [ :websites, :photo ]).find(1)
@comments = @post.comments.includes(:editor).where(:approved => true).all

Ответы [ 2 ]

0 голосов
/ 12 февраля 2011

Обновление : Возможно, в может быть какой-то кусочек мудрости, в который входит этот пост: vs eager_load против preload .

Мне бы хотелось услышать лучший способ сделать это, но сейчас я использую следующее, чтобы обойти это (работает с глубоко вложенной энергичной загрузкой, в отличие от использования joins):

@post = Post.find(1)
@comments = @post.comments.where(:approved => true).all

# allows deeper/more complex nesting without getting into SQL:
@post = Post.includes(:author => [ :websites, :photo ]).find(1)
@comments = @post.comments.includes(:editor).where(:approved => true).all
0 голосов
/ 04 февраля 2011

Я предполагаю, что вы ищете метод joins, он позволит вам поместить ваше условие в определение соединения, а не вне его.Например:

@post = Post.joins("LEFT JOIN comments on posts.id = comments.post_id AND comments.approved = 1").first

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

К сожалению, вы должны использовать эту уродливую строку, так как joins использует INNER JOIN, еслиВы передаете массив / хэш.

Там больше о joins в направляющих рельсов

...