Столы объединения - Ассоциации в Rails 3 - PullRequest
0 голосов
/ 05 февраля 2012

Например, у меня есть 2 таблицы: темы и комментарии.

тема имеет множество комментариев. комментарий принадлежит к теме.

В таблице комментариев есть столбец sender_id, в котором я сохраняю идентификатор пользователя, создавшего этот комментарий.

Задача: выбрать идентификаторы тем, которые не комментирует этот пользователь (я знаю user_id). (Я хочу сделать это одним запросом).

Раньше я так и делал. (два запроса) (Моя база данных - PostgreSQL)

incorrect_topics = Comment.select(:topic_id).where(:sender_id => user_id).map { |elem| elem.topic_id }
ids = select(:id).where(["id NOT IN (?)", incorrect_topics]).map { |elem| elem.id }

Работает нормально, но я полагаю, что если приложение станет больше, это будет серьезной проблемой.

Спасибо.

Ответы [ 2 ]

1 голос
/ 05 февраля 2012

Если вам нужны только идентификаторы, вы можете обойти все элементы ActiveRecord и сделать это вручную:

ids = connection.select_rows(%Q{
    select id
    from topics
    where id not in (
        select topic_id
        from comments
        where sender_id = #{user_id.to_i}
    )
}).map { |r| r.first.to_i }

Если вы уверены, что user_id уже является целым числом, тогда вам не нужно .to_i. Вы также можете использовать #{connection.quote(user_id)}. Вы также можете использовать тот же SQL с select_values, если хотите избежать разворачивания строк вручную с помощью map.

Если вам нужны экземпляры Topic, тогда find_by_sql будет вариантом:

topics = find_by_sql(%q{
    select *
    from topics
    where id not in (
        select topic_id
        from comments
        where sender_id = :user_id
    )
}, :user_id => user_id)

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

0 голосов
/ 05 февраля 2012

Может быть, что-то вроде этого может работать:

incorrect_topics = Comment.where('sender_id <> ?', user_id).topics

Дайте мне знать, если вам все равно поможет.

...