mirror of
https://github.com/discourse/discourse.git
synced 2024-11-29 04:48:45 +08:00
DEV: Refactor TopicQuery#default_results
to improve readability (#20800)
This commit breaks down the code in TopicQuery#default_results into smaller private methods to improve readability.
This commit is contained in:
parent
4929288bdd
commit
7c6a8f1c74
|
@ -715,65 +715,7 @@ class TopicQuery
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if SiteSetting.tagging_enabled
|
result = filter_by_tags(result)
|
||||||
result = result.preload(:tags)
|
|
||||||
|
|
||||||
tags_arg = @options[:tags]
|
|
||||||
|
|
||||||
if tags_arg && tags_arg.size > 0
|
|
||||||
tags_arg = tags_arg.split if String === tags_arg
|
|
||||||
|
|
||||||
tags_arg =
|
|
||||||
tags_arg.map do |t|
|
|
||||||
if String === t
|
|
||||||
t.downcase
|
|
||||||
else
|
|
||||||
t
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
tags_query = tags_arg[0].is_a?(String) ? Tag.where_name(tags_arg) : Tag.where(id: tags_arg)
|
|
||||||
tags = tags_query.select(:id, :target_tag_id).map { |t| t.target_tag_id || t.id }.uniq
|
|
||||||
|
|
||||||
if ActiveModel::Type::Boolean.new.cast(@options[:match_all_tags])
|
|
||||||
# ALL of the given tags:
|
|
||||||
if tags_arg.length == tags.length
|
|
||||||
tags.each_with_index do |tag, index|
|
|
||||||
sql_alias = ["t", index].join
|
|
||||||
result =
|
|
||||||
result.joins(
|
|
||||||
"INNER JOIN topic_tags #{sql_alias} ON #{sql_alias}.topic_id = topics.id AND #{sql_alias}.tag_id = #{tag}",
|
|
||||||
)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
result = result.none # don't return any results unless all tags exist in the database
|
|
||||||
end
|
|
||||||
else
|
|
||||||
# ANY of the given tags:
|
|
||||||
result = result.joins(:tags).where("tags.id in (?)", tags)
|
|
||||||
end
|
|
||||||
|
|
||||||
# TODO: this is very side-effecty and should be changed
|
|
||||||
# It is done cause further up we expect normalized tags
|
|
||||||
@options[:tags] = tags
|
|
||||||
elsif @options[:no_tags]
|
|
||||||
# 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].present? &&
|
|
||||||
!DiscourseTagging.hidden_tag_names(@guardian).include?(@options[:exclude_tag])
|
|
||||||
result = result.where(<<~SQL, name: @options[:exclude_tag])
|
|
||||||
topics.id NOT IN (
|
|
||||||
SELECT topic_tags.topic_id
|
|
||||||
FROM topic_tags
|
|
||||||
INNER JOIN tags ON tags.id = topic_tags.tag_id
|
|
||||||
WHERE tags.name = :name
|
|
||||||
)
|
|
||||||
SQL
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
result = apply_ordering(result, options)
|
result = apply_ordering(result, options)
|
||||||
|
|
||||||
all_listable_topics =
|
all_listable_topics =
|
||||||
|
@ -1202,4 +1144,56 @@ class TopicQuery
|
||||||
end
|
end
|
||||||
results
|
results
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filter_by_tags(result)
|
||||||
|
return result if !SiteSetting.tagging_enabled
|
||||||
|
|
||||||
|
tags_arg = @options[:tags]
|
||||||
|
|
||||||
|
if tags_arg && tags_arg.size > 0
|
||||||
|
tags_arg = tags_arg.split if String === tags_arg
|
||||||
|
tags_query = tags_arg[0].is_a?(String) ? Tag.where_name(tags_arg) : Tag.where(id: tags_arg)
|
||||||
|
tags = tags_query.select(:id, :target_tag_id).map { |t| t.target_tag_id || t.id }.uniq
|
||||||
|
|
||||||
|
if ActiveModel::Type::Boolean.new.cast(@options[:match_all_tags])
|
||||||
|
# ALL of the given tags:
|
||||||
|
if tags_arg.length == tags.length
|
||||||
|
tags.each_with_index do |tag, index|
|
||||||
|
sql_alias = ["t", index].join
|
||||||
|
|
||||||
|
result =
|
||||||
|
result.joins(
|
||||||
|
"INNER JOIN topic_tags #{sql_alias} ON #{sql_alias}.topic_id = topics.id AND #{sql_alias}.tag_id = #{tag}",
|
||||||
|
)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
result = result.none # don't return any results unless all tags exist in the database
|
||||||
|
end
|
||||||
|
else
|
||||||
|
# ANY of the given tags:
|
||||||
|
result = result.joins(:tags).where("tags.id in (?)", tags)
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO: this is very side-effecty and should be changed
|
||||||
|
# It is done cause further up we expect normalized tags
|
||||||
|
@options[:tags] = tags
|
||||||
|
elsif @options[:no_tags]
|
||||||
|
# the following will do: ("topics"."id" NOT IN (SELECT DISTINCT "topic_tags"."topic_id" FROM "topic_tags"))
|
||||||
|
result = result.where.not(id: TopicTag.distinct.select(:topic_id))
|
||||||
|
end
|
||||||
|
|
||||||
|
if @options[:exclude_tag].present? &&
|
||||||
|
!DiscourseTagging.hidden_tag_names(@guardian).include?(@options[:exclude_tag])
|
||||||
|
result = result.where(<<~SQL, name: @options[:exclude_tag])
|
||||||
|
topics.id NOT IN (
|
||||||
|
SELECT topic_tags.topic_id
|
||||||
|
FROM topic_tags
|
||||||
|
INNER JOIN tags ON tags.id = topic_tags.tag_id
|
||||||
|
WHERE tags.name = :name
|
||||||
|
)
|
||||||
|
SQL
|
||||||
|
end
|
||||||
|
|
||||||
|
result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user