diff --git a/lib/topic_query.rb b/lib/topic_query.rb index 57ffb9a726d..992a3c7ee0e 100644 --- a/lib/topic_query.rb +++ b/lib/topic_query.rb @@ -60,7 +60,8 @@ class TopicQuery tags match_all_tags no_subcategories - no_tags) + no_tags + exclude_tag) end def self.valid_options @@ -689,6 +690,10 @@ class TopicQuery # the following will do: ("topics"."id" NOT IN (SELECT DISTINCT "topic_tags"."topic_id" FROM "topic_tags")) result = result.where.not(id: TopicTag.distinct.pluck(:topic_id)) end + + if @options[:exclude_tag] && tag = Tag.find_by(name: @options[:exclude_tag]) + result = result.where.not(id: TopicTag.distinct.where(tag_id: tag.id).pluck(:topic_id)) + end end result = apply_ordering(result, options) diff --git a/spec/components/topic_query_spec.rb b/spec/components/topic_query_spec.rb index a7e7f2ecc01..ec216416019 100644 --- a/spec/components/topic_query_spec.rb +++ b/spec/components/topic_query_spec.rb @@ -383,6 +383,11 @@ describe TopicQuery do fab!(:no_tags_topic) { Fabricate(:topic) } let(:synonym) { Fabricate(:tag, target_tag: tag, name: 'synonym') } + it "excludes a tag if desired" do + topics = TopicQuery.new(moderator, exclude_tag: tag.name).list_latest.topics + expect(topics.any? { |t| t.tags.include?(tag) }).to eq(false) + end + it "returns topics with the tag when filtered to it" do expect(TopicQuery.new(moderator, tags: tag.name).list_latest.topics) .to contain_exactly(tagged_topic1, tagged_topic3)