したがって、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