因此,如果您使用acts-as-taggable-on gem 并具有以下模型:
class User < ActiveRecord::Base
acts_as_tagger
has_many :brand_users
has_many :brands, :through => :brand_users
end
因此,您的架构中也有表,例如:
create_table "users", :force => true do |t|
t.string "name"
end
create_table "brands", :force => true do |t|
t.string "name"
end
那么下面的 SQL 查询应该有希望做你想要的(?):
SELECT brands.*
FROM brands
WHERE brands.id NOT IN (
SELECT brands.id
FROM brands
INNER JOIN brand_users ON brand_users.brand_id = brands.id
INNER JOIN taggings ON (taggings.tagger_id = brand_users.user_id AND taggings.tagger_type = 'User')
WHERE brand_users.user_id = 1 AND taggings.taggable_id = brand_users.brand_id
)
要将其转换为 Rails ORM,如果不对整个子选择 SQL 字符串进行硬编码,我将无法接近,例如:
class Brand < ActiveRecord::Base
has_many :brand_users
has_many :users, :through => :brand_users
scope :has_not_been_tagged_by_user, lambda {|user| where("brands.id NOT IN (SELECT brands.id
FROM brands
INNER JOIN brand_users ON brand_users.brand_id = brands.id
INNER JOIN taggings ON (taggings.tagger_id = brand_users.user_id AND taggings.tagger_type = 'User')
WHERE brand_users.user_id = ? AND taggings.taggable_id = brand_users.brand_id)", user.id) }
end
(我知道你可以这样做,然后使用 ruby 的.map(&:id).join(',')但如果这是一个大型应用程序,我认为你通过将其从数据库中取出并转换它会损失很多性能成一串整数并将其反馈回(据我所知)。)
然后在您的控制器中,我认为您会执行以下操作:
@brand = current_user.brands.has_not_been_tagged_by_user(current_user)
顺便说一句,我认为这实际上会执行如下 SQL(对吗?):
SELECT brands.*
FROM users
INNER JOIN brand_users ON brand_users.user_id = users.id
INNER JOIN brands ON brands.id = brand_users.brand_id
WHERE brands.id NOT IN (
SELECT brands.id
FROM brands
INNER JOIN brand_users ON brand_users.brand_id = brands.id
INNER JOIN taggings ON (taggings.tagger_id = brand_users.user_id AND taggings.tagger_type = 'User')
WHERE brand_users.user_id = 1 AND taggings.taggable_id = brand_users.brand_id
) AND users.id = 1