组合范围不起作用

时间:2016-08-31 14:33:48

标签: ruby-on-rails scopes

我正在尝试将三个范围组合在一个范围内(一个范围使用另外两个范围)。

我希望获得所有没有特定类别和特定标签的视频。

视频

class Video < ActiveRecord::Base
    self.primary_key = "id"
    has_and_belongs_to_many :categories
    has_and_belongs_to_many :tags

    scope :with_categories, ->(ids) { joins(:categories).where(categories: {id: ids}) }
    scope :excluded_tags, -> { joins(:tags).where(tags: {id: 15}) }

    scope :without_categories, ->(ids) { where.not(id: excluded_tags.with_categories(ids) ) }

end

但是当我打电话时

    @excluded_categories = [15,17,26,32,35,36,37]
    @videos = Video.without_categories(@excluded_categories)

我仍然会收到标记为15的视频。

服务器正在触发的SQL查询如下所示

SELECT "videos"."video_id" FROM "videos" WHERE ("videos"."id" NOT IN (SELECT "videos"."id" FROM "videos" INNER JOIN "tags_videos" ON "tags_videos"."video_id" = "videos"."id" INNER JOIN "tags" ON "tags"."id" = "tags_videos"."tag_id" INNER JOIN "categories_videos" ON "categories_videos"."video_id" = "videos"."id" INNER JOIN "categories" ON "categories"."id" = "categories_videos"."category_id" WHERE "tags"."id" = $1 AND "categories"."id" IN (15, 17, 26, 32, 35, 36, 37)))  [["id", 15]]

我做错了吗?

2 个答案:

答案 0 :(得分:0)

 scope :excluded_tags, -> { joins(:tags).where.not(tags: {id: 15}) }

 scope :without_categories, ->(ids) { excluded_tags.with_categories(ids) }

答案 1 :(得分:0)

我认为您必须使用一个范围来排除类别,第二个范围用于排除标记,然后将它们组合起来。

scope :without_categories, ->(ids) { joins(:categories).where.not(categories: {id: ids}) }
scope :without_tags, ->(ids) { joins(:tags).where.not(tags: {id: ids}) }

然后你可以使用

@excluded_categories = [1,2,3,4]
@excluded_tags = [1,2,3,4,5,6]
@videos = Video.without_categories(@excluded_categories).without_tags(@excluded_tags)

评论后编辑

在看到查询后因为链接范围正在使用AND而生成的查询无法返回所需的结果。一种新方法是仅为此目的创建一个范围。

scope :without_categories_tags, ->
(category_ids, tag_ids) { joins( :categories, :tags).
where('categories.id NOT IN (?) OR tags.id NOT IN (?)', category_ids, tag_ids)}

你可以使用

@excluded_categories = [1,2,3,4]
@excluded_tags = [1,2,3,4,5,6]
@videos = Video.without_categories_tags(@excluded_categories,@excluded_tags)