HABTM-запрос Rails, где условие основано на атрибуте ассоциации - PullRequest
1 голос
/ 12 марта 2011

У меня есть модели пользователей и альбомов с отношениями HABTM

class Album < ActiveRecord::Base
  has_and_belongs_to_many :users

class User < ActiveRecord::Base
  has_and_belongs_to_many(:albums)

Я бы хотел найти все альбомы, которые хранятся в базе данных, но не связаны с конкретным пользователем.

Пока мой код выглядит так:

Album.all(:order => "albums.created_at DESC", :include => "users", :limit => limit, :conditions => ["users.id != ? AND users.id IS NOT NULL", current_user.id])

но по какой-то причине это не работает. Он возвращает альбомы, связанные с current_user.

здесь взгляните на этот выходной сигнал с консоли. Проверьте идентификатор пользователя, который я сначала получаю. Тогда я выбираю альбомы, которые не должны иметь идентификатор пользователя Затем я нахожу один из перечисленных альбомов и прошу его вернуть связанных пользователей один из тех ассоциированных пользователей - тот, что сверху и не должен быть там. enter image description here

Может кто-нибудь помочь с вышесказанным?

Ответы [ 4 ]

7 голосов
/ 19 марта 2011

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

class Album < ActiveRecord::Base

  scope :without_user, lambda{|u| where("#{quoted_table_name}.id NOT IN (SELECT `albums_users`.album_id FROM `albums_users` WHERE `albums_users`.user_id = ?)", u.id) }

end

user = User.find(30)
Album.without_user(user)
2 голосов
/ 14 марта 2011

Предполагается, что вы создали таблицу album_users для хранения данных отношений:

Album.includes(:users).  
    where(["albums_users.user_id IS NULL OR albums_users.user_id != ?", user_id])

Я думаю, что он будет генерировать SQL в соответствии с

SELECT *
FROM albums LEFT OUTER JOIN albums_users ON albums.id = albums_users.album_id
WHERE albums_users.album_id IS NULL OR albums_users.album_id != #{user_id}  
1 голос
/ 12 марта 2011

Попробуйте:

:conditions => ["users.id <> ? AND users.id IS NOT NULL", current_user.id] 
0 голосов
/ 14 марта 2011

Решением, отличным от sql, будет:

Album.all.reject{|album| user.albums.include?(album)}

Очевидно, что если в вашей базе данных десятки тысяч строк, вы, возможно, не захотите этого делать.

Возможно, вам удастсячто-то вроде этого тоже:

Album.where(["id NOT IN (?)", user.albums_ids])

Но если у ваших пользователей много (скажем, сотен) альбомов, вы тоже не должны этого делать.

Просто добавьте простые решения, если выВы один из тех.

...