search: refactor PostQueryBuilder class methods into instance methods.
* Make scan_query, parse_query, normalize_query into instance methods instead of class methods. This is to a) clean up the API and b) prepare for moving certain tag utility methods into PostQueryBuilder. * Fix a few cases where a caller used scan_query when they should have used split_query or parse_tag_edit.
This commit is contained in:
@@ -25,7 +25,7 @@ module PostsHelper
|
|||||||
return unless post_search_counts_enabled?
|
return unless post_search_counts_enabled?
|
||||||
return unless params[:action] == "index" && params[:page].nil? && params[:tags].present?
|
return unless params[:action] == "index" && params[:page].nil? && params[:tags].present?
|
||||||
|
|
||||||
tags = PostQueryBuilder.normalize_query(params[:tags])
|
tags = PostQueryBuilder.new(params[:tags]).normalize_query
|
||||||
sig = generate_reportbooru_signature("ps-#{tags}")
|
sig = generate_reportbooru_signature("ps-#{tags}")
|
||||||
render "posts/partials/index/search_count", sig: sig
|
render "posts/partials/index/search_count", sig: sig
|
||||||
end
|
end
|
||||||
@@ -63,7 +63,7 @@ module PostsHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def show_tag_change_notice?
|
def show_tag_change_notice?
|
||||||
CurrentUser.user.is_member? && PostQueryBuilder.scan_query(params[:tags]).size == 1 && TagChangeNoticeService.get_forum_topic_id(params[:tags])
|
CurrentUser.user.is_member? && PostQueryBuilder.new(params[:tags]).split_query.size == 1 && TagChangeNoticeService.get_forum_topic_id(params[:tags])
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ class TagBatchChangeJob < ApplicationJob
|
|||||||
def perform(antecedent, consequent, updater, updater_ip_addr)
|
def perform(antecedent, consequent, updater, updater_ip_addr)
|
||||||
raise Error.new("antecedent is missing") if antecedent.blank?
|
raise Error.new("antecedent is missing") if antecedent.blank?
|
||||||
|
|
||||||
normalized_antecedent = TagAlias.to_aliased(PostQueryBuilder.split_query(antecedent.mb_chars.downcase))
|
normalized_antecedent = TagAlias.to_aliased(PostQueryBuilder.new(antecedent.mb_chars.downcase).split_query)
|
||||||
normalized_consequent = TagAlias.to_aliased(PostQueryBuilder.split_query(consequent.mb_chars.downcase))
|
normalized_consequent = TagAlias.to_aliased(PostQueryBuilder.new(consequent.mb_chars.downcase).parse_tag_edit)
|
||||||
|
|
||||||
CurrentUser.without_safe_mode do
|
CurrentUser.without_safe_mode do
|
||||||
CurrentUser.scoped(updater, updater_ip_addr) do
|
CurrentUser.scoped(updater, updater_ip_addr) do
|
||||||
@@ -30,7 +30,7 @@ class TagBatchChangeJob < ApplicationJob
|
|||||||
end
|
end
|
||||||
|
|
||||||
def migrate_saved_searches(normalized_antecedent, normalized_consequent)
|
def migrate_saved_searches(normalized_antecedent, normalized_consequent)
|
||||||
tags = PostQueryBuilder.split_query(normalized_antecedent.join(" "))
|
tags = PostQueryBuilder.new(normalized_antecedent.join(" ")).split_query
|
||||||
|
|
||||||
# https://www.postgresql.org/docs/current/static/functions-array.html
|
# https://www.postgresql.org/docs/current/static/functions-array.html
|
||||||
saved_searches = SavedSearch.where("string_to_array(query, ' ') @> ARRAY[?]", tags)
|
saved_searches = SavedSearch.where("string_to_array(query, ' ') @> ARRAY[?]", tags)
|
||||||
@@ -53,7 +53,7 @@ class TagBatchChangeJob < ApplicationJob
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
repl = user.blacklisted_tags.split(/\r\n|\r|\n/).map do |line|
|
repl = user.blacklisted_tags.split(/\r\n|\r|\n/).map do |line|
|
||||||
list = PostQueryBuilder.split_query(line)
|
list = PostQueryBuilder.new(line).split_query
|
||||||
|
|
||||||
if (list & query).size != query.size
|
if (list & query).size != query.size
|
||||||
next line
|
next line
|
||||||
|
|||||||
@@ -88,8 +88,8 @@ class AliasAndImplicationImporter
|
|||||||
all
|
all
|
||||||
|
|
||||||
when :mass_update
|
when :mass_update
|
||||||
all += PostQueryBuilder.split_query(token[1])
|
all += PostQueryBuilder.new(token[1]).split_query
|
||||||
all += PostQueryBuilder.split_query(token[2])
|
all += PostQueryBuilder.new(token[2]).parse_tag_edit
|
||||||
all
|
all
|
||||||
|
|
||||||
when :change_category
|
when :change_category
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
require "strscan"
|
require "strscan"
|
||||||
|
|
||||||
class PostQueryBuilder
|
class PostQueryBuilder
|
||||||
|
extend Memoist
|
||||||
|
|
||||||
COUNT_METATAGS = %w[
|
COUNT_METATAGS = %w[
|
||||||
comment_count deleted_comment_count active_comment_count
|
comment_count deleted_comment_count active_comment_count
|
||||||
note_count deleted_note_count active_note_count
|
note_count deleted_note_count active_note_count
|
||||||
@@ -93,7 +95,7 @@ class PostQueryBuilder
|
|||||||
|
|
||||||
def attribute_matches(values, field, type = :integer)
|
def attribute_matches(values, field, type = :integer)
|
||||||
values.to_a.reduce(Post.all) do |relation, value|
|
values.to_a.reduce(Post.all) do |relation, value|
|
||||||
operator, *args = PostQueryBuilder.parse_metatag_value(value, type)
|
operator, *args = parse_metatag_value(value, type)
|
||||||
relation.where_operator(field, operator, *args)
|
relation.where_operator(field, operator, *args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -328,7 +330,7 @@ class PostQueryBuilder
|
|||||||
end
|
end
|
||||||
|
|
||||||
def build
|
def build
|
||||||
q = PostQueryBuilder.parse_query(query_string)
|
q = parse_query
|
||||||
relation = Post.all
|
relation = Post.all
|
||||||
|
|
||||||
if q[:tag_count].to_i > Danbooru.config.tag_query_limit
|
if q[:tag_count].to_i > Danbooru.config.tag_query_limit
|
||||||
@@ -608,13 +610,13 @@ class PostQueryBuilder
|
|||||||
if q[:order] == "custom" && q[:post_id].present? && q[:post_id][0] == :in
|
if q[:order] == "custom" && q[:post_id].present? && q[:post_id][0] == :in
|
||||||
relation = relation.find_ordered(q[:post_id][1])
|
relation = relation.find_ordered(q[:post_id][1])
|
||||||
else
|
else
|
||||||
relation = PostQueryBuilder.search_order(relation, q[:order])
|
relation = search_order(relation, q[:order])
|
||||||
end
|
end
|
||||||
|
|
||||||
relation
|
relation
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.search_order(relation, order)
|
def search_order(relation, order)
|
||||||
case order.to_s
|
case order.to_s
|
||||||
when "id", "id_asc"
|
when "id", "id_asc"
|
||||||
relation = relation.order("posts.id ASC")
|
relation = relation.order("posts.id ASC")
|
||||||
@@ -738,10 +740,9 @@ class PostQueryBuilder
|
|||||||
end
|
end
|
||||||
|
|
||||||
concerning :ParseMethods do
|
concerning :ParseMethods do
|
||||||
class_methods do
|
def scan_query
|
||||||
def scan_query(query)
|
|
||||||
terms = []
|
terms = []
|
||||||
query = query.to_s.gsub(/[[:space:]]/, " ")
|
query = query_string.to_s.gsub(/[[:space:]]/, " ")
|
||||||
scanner = StringScanner.new(query)
|
scanner = StringScanner.new(query)
|
||||||
|
|
||||||
until scanner.eos?
|
until scanner.eos?
|
||||||
@@ -767,8 +768,8 @@ class PostQueryBuilder
|
|||||||
terms
|
terms
|
||||||
end
|
end
|
||||||
|
|
||||||
def split_query(query)
|
def split_query
|
||||||
scan_query(query).map do |term|
|
scan_query.map do |term|
|
||||||
if term.type == :metatag && term.value.include?(" ")
|
if term.type == :metatag && term.value.include?(" ")
|
||||||
"#{term.name}:\"#{term.value}\""
|
"#{term.name}:\"#{term.value}\""
|
||||||
elsif term.type == :metatag
|
elsif term.type == :metatag
|
||||||
@@ -779,8 +780,8 @@ class PostQueryBuilder
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalize_query(query, normalize_aliases: true, sort: true)
|
def normalize_query(normalize_aliases: true, sort: true)
|
||||||
tags = split_query(query.to_s)
|
tags = split_query
|
||||||
tags = tags.map { |t| Tag.normalize_name(t) }
|
tags = tags.map { |t| Tag.normalize_name(t) }
|
||||||
tags = TagAlias.to_aliased(tags) if normalize_aliases
|
tags = TagAlias.to_aliased(tags) if normalize_aliases
|
||||||
tags = tags.sort if sort
|
tags = tags.sort if sort
|
||||||
@@ -788,11 +789,11 @@ class PostQueryBuilder
|
|||||||
tags.join(" ")
|
tags.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_tag_edit(tag_string)
|
def parse_tag_edit
|
||||||
split_query(tag_string)
|
split_query
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_query(query, options = {})
|
def parse_query
|
||||||
q = {}
|
q = {}
|
||||||
|
|
||||||
q[:tag_count] = 0
|
q[:tag_count] = 0
|
||||||
@@ -803,7 +804,7 @@ class PostQueryBuilder
|
|||||||
:exclude => []
|
:exclude => []
|
||||||
}
|
}
|
||||||
|
|
||||||
scan_query(query).each do |term|
|
scan_query.each do |term|
|
||||||
q[:tag_count] += 1 unless Danbooru.config.is_unlimited_tag?(term)
|
q[:tag_count] += 1 unless Danbooru.config.is_unlimited_tag?(term)
|
||||||
|
|
||||||
if term.type == :metatag
|
if term.type == :metatag
|
||||||
@@ -1252,5 +1253,6 @@ class PostQueryBuilder
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
memoize :scan_query, :split_query, :parse_query
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module PostSets
|
|||||||
attr_reader :tag_array, :page, :raw, :random, :post_count, :format
|
attr_reader :tag_array, :page, :raw, :random, :post_count, :format
|
||||||
|
|
||||||
def initialize(tags, page = 1, per_page = nil, raw: false, random: false, format: "html")
|
def initialize(tags, page = 1, per_page = nil, raw: false, random: false, format: "html")
|
||||||
@tag_array = PostQueryBuilder.split_query(tags)
|
@tag_array = PostQueryBuilder.new(tags).split_query
|
||||||
@page = page
|
@page = page
|
||||||
@per_page = per_page
|
@per_page = per_page
|
||||||
@raw = raw.to_s.truthy?
|
@raw = raw.to_s.truthy?
|
||||||
|
|||||||
@@ -596,7 +596,7 @@ class Post < ApplicationRecord
|
|||||||
# If someone else committed changes to this post before we did,
|
# If someone else committed changes to this post before we did,
|
||||||
# then try to merge the tag changes together.
|
# then try to merge the tag changes together.
|
||||||
current_tags = tag_string_was.split
|
current_tags = tag_string_was.split
|
||||||
new_tags = PostQueryBuilder.parse_tag_edit(tag_string)
|
new_tags = PostQueryBuilder.new(tag_string).parse_tag_edit
|
||||||
old_tags = old_tag_string.split
|
old_tags = old_tag_string.split
|
||||||
|
|
||||||
kept_tags = current_tags & new_tags
|
kept_tags = current_tags & new_tags
|
||||||
@@ -634,7 +634,7 @@ class Post < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def normalize_tags
|
def normalize_tags
|
||||||
normalized_tags = PostQueryBuilder.split_query(tag_string)
|
normalized_tags = PostQueryBuilder.new(tag_string).parse_tag_edit
|
||||||
normalized_tags = apply_casesensitive_metatags(normalized_tags)
|
normalized_tags = apply_casesensitive_metatags(normalized_tags)
|
||||||
normalized_tags = normalized_tags.map(&:downcase)
|
normalized_tags = normalized_tags.map(&:downcase)
|
||||||
normalized_tags = filter_metatags(normalized_tags)
|
normalized_tags = filter_metatags(normalized_tags)
|
||||||
@@ -1070,7 +1070,7 @@ class Post < ApplicationRecord
|
|||||||
tags = tags.to_s
|
tags = tags.to_s
|
||||||
tags += " rating:s" if CurrentUser.safe_mode?
|
tags += " rating:s" if CurrentUser.safe_mode?
|
||||||
tags += " -status:deleted" if CurrentUser.hide_deleted_posts? && !Tag.has_metatag?(tags, "status", "-status")
|
tags += " -status:deleted" if CurrentUser.hide_deleted_posts? && !Tag.has_metatag?(tags, "status", "-status")
|
||||||
tags = PostQueryBuilder.normalize_query(tags)
|
tags = PostQueryBuilder.new(tags).normalize_query
|
||||||
|
|
||||||
# Optimize some cases. these are just estimates but at these
|
# Optimize some cases. these are just estimates but at these
|
||||||
# quantities being off by a few hundred doesn't matter much
|
# quantities being off by a few hundred doesn't matter much
|
||||||
|
|||||||
@@ -136,17 +136,17 @@ class SavedSearch < ApplicationRecord
|
|||||||
def queries_for(user_id, label: nil, options: {})
|
def queries_for(user_id, label: nil, options: {})
|
||||||
searches = SavedSearch.where(user_id: user_id)
|
searches = SavedSearch.where(user_id: user_id)
|
||||||
searches = searches.labeled(label) if label.present?
|
searches = searches.labeled(label) if label.present?
|
||||||
queries = searches.pluck(:query).map { |query| PostQueryBuilder.normalize_query(query, sort: true) }
|
queries = searches.pluck(:query).map { |query| PostQueryBuilder.new(query).normalize_query(sort: true) }
|
||||||
queries.sort.uniq
|
queries.sort.uniq
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalized_query
|
def normalized_query
|
||||||
PostQueryBuilder.normalize_query(query, sort: true)
|
PostQueryBuilder.new(query).normalize_query(sort: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalize_query
|
def normalize_query
|
||||||
self.query = PostQueryBuilder.normalize_query(query, sort: false)
|
self.query = PostQueryBuilder.new(query).normalize_query(sort: false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ class Tag < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def is_single_tag?(query)
|
def is_single_tag?(query)
|
||||||
PostQueryBuilder.scan_query(query).size == 1
|
PostQueryBuilder.new(query).split_query.size == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_metatag?(tag)
|
def is_metatag?(tag)
|
||||||
@@ -256,7 +256,7 @@ class Tag < ApplicationRecord
|
|||||||
def has_metatag?(tags, *metatags)
|
def has_metatag?(tags, *metatags)
|
||||||
return nil if tags.blank?
|
return nil if tags.blank?
|
||||||
|
|
||||||
tags = PostQueryBuilder.split_query(tags.to_str) if tags.respond_to?(:to_str)
|
tags = PostQueryBuilder.new(tags.to_str).split_query if tags.respond_to?(:to_str)
|
||||||
tags.grep(/\A(?:#{metatags.map(&:to_s).join("|")}):(.+)\z/i) { $1 }.first
|
tags.grep(/\A(?:#{metatags.map(&:to_s).join("|")}):(.+)\z/i) { $1 }.first
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -854,12 +854,12 @@ class PostQueryBuilderTest < ActiveSupport::TestCase
|
|||||||
should "work" do
|
should "work" do
|
||||||
create(:tag_alias, antecedent_name: "gray", consequent_name: "grey")
|
create(:tag_alias, antecedent_name: "gray", consequent_name: "grey")
|
||||||
|
|
||||||
assert_equal("foo", PostQueryBuilder.normalize_query("foo"))
|
assert_equal("foo", PostQueryBuilder.new("foo").normalize_query)
|
||||||
assert_equal("foo", PostQueryBuilder.normalize_query(" foo "))
|
assert_equal("foo", PostQueryBuilder.new(" foo ").normalize_query)
|
||||||
assert_equal("foo", PostQueryBuilder.normalize_query("FOO"))
|
assert_equal("foo", PostQueryBuilder.new("FOO").normalize_query)
|
||||||
assert_equal("foo", PostQueryBuilder.normalize_query("foo foo"))
|
assert_equal("foo", PostQueryBuilder.new("foo foo").normalize_query)
|
||||||
assert_equal("grey", PostQueryBuilder.normalize_query("gray"))
|
assert_equal("grey", PostQueryBuilder.new("gray").normalize_query)
|
||||||
assert_equal("aaa bbb", PostQueryBuilder.normalize_query("bbb aaa"))
|
assert_equal("aaa bbb", PostQueryBuilder.new("bbb aaa").normalize_query)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -93,13 +93,13 @@ class TagTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
context "A tag parser" do
|
context "A tag parser" do
|
||||||
should "scan a query" do
|
should "scan a query" do
|
||||||
assert_equal(%w(aaa bbb), PostQueryBuilder.split_query("aaa bbb"))
|
assert_equal(%w(aaa bbb), PostQueryBuilder.new("aaa bbb").split_query)
|
||||||
assert_equal(%w(~aaa -bbb* -bbb*), PostQueryBuilder.split_query("~AAa -BBB* -bbb*"))
|
assert_equal(%w(~aaa -bbb* -bbb*), PostQueryBuilder.new("~AAa -BBB* -bbb*").split_query)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "not strip out valid characters when scanning" do
|
should "not strip out valid characters when scanning" do
|
||||||
assert_equal(%w(aaa bbb), PostQueryBuilder.split_query("aaa bbb"))
|
assert_equal(%w(aaa bbb), PostQueryBuilder.new("aaa bbb").split_query)
|
||||||
assert_equal(%w(favgroup:yondemasu_yo,_azazel-san. pool:ichigo_100%), PostQueryBuilder.split_query("favgroup:yondemasu_yo,_azazel-san. pool:ichigo_100%"))
|
assert_equal(%w(favgroup:yondemasu_yo,_azazel-san. pool:ichigo_100%), PostQueryBuilder.new("favgroup:yondemasu_yo,_azazel-san. pool:ichigo_100%").split_query)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "cast values" do
|
should "cast values" do
|
||||||
|
|||||||
Reference in New Issue
Block a user