diff --git a/app/logical/autocomplete_service.rb b/app/logical/autocomplete_service.rb index 833c016da..2d4f5d614 100644 --- a/app/logical/autocomplete_service.rb +++ b/app/logical/autocomplete_service.rb @@ -72,8 +72,11 @@ class AutocompleteService results = results.uniq.sort_by { |r| [r[:antecedent].length, -r[:post_count]] }.take(limit) elsif string.include?("*") results = tag_matches(string) + results = tag_other_name_matches(string) if results.blank? else - results = tag_matches(string + "*") + string += "*" + results = tag_matches(string) + results = tag_other_name_matches(string) if results.blank? results = tag_autocorrect_matches(string) if results.blank? end @@ -81,6 +84,8 @@ class AutocompleteService end def tag_matches(string) + return [] if string =~ /[^[:ascii:]]/ + name_matches = Tag.nonempty.name_matches(string).order(post_count: :desc).limit(limit) alias_matches = Tag.nonempty.alias_matches(string).order(post_count: :desc).limit(limit) union = "((#{name_matches.to_sql}) UNION (#{alias_matches.to_sql})) AS tags" @@ -100,6 +105,7 @@ class AutocompleteService end def tag_autocorrect_matches(string) + string = string.delete("*") tags = Tag.nonempty.autocorrect_matches(string).limit(limit) tags.map do |tag| @@ -107,6 +113,21 @@ class AutocompleteService end end + def tag_other_name_matches(string) + return [] unless string =~ /[^[:ascii:]]/ + + artists = Artist.undeleted.any_other_name_like(string) + wikis = WikiPage.undeleted.other_names_match(string) + tags = Tag.where(name: wikis.select(:title)).or(Tag.where(name: artists.select(:name))) + tags = tags.nonempty.order(post_count: :desc).limit(limit).includes(:wiki_page, :artist) + + tags.map do |tag| + other_names = tag.artist&.other_names.to_a + tag.wiki_page&.other_names.to_a + antecedent = other_names.find { |other_name| other_name.ilike?(string) } + { type: "tag", label: tag.pretty_name, value: tag.name, category: tag.category, post_count: tag.post_count, antecedent: antecedent } + end + end + def autocomplete_metatag(metatag, value) results = case metatag.to_sym when :user, :approver, :commenter, :comm, :noter, :noteupdater, :commentaryupdater, diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index c9fd1a7c1..603ddcecd 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -45,7 +45,7 @@ class WikiPage < ApplicationRecord def other_names_match(name) if name =~ /\*/ - subquery = WikiPage.from("unnest(other_names) AS other_name").where_ilike("other_name", name) + subquery = WikiPage.from("unnest(other_names) AS other_name").where_ilike("other_name", normalize_other_name(name)) where(id: subquery) else other_names_include(name) diff --git a/test/unit/autocomplete_service_test.rb b/test/unit/autocomplete_service_test.rb index 29d8ea6ce..eaf65235b 100644 --- a/test/unit/autocomplete_service_test.rb +++ b/test/unit/autocomplete_service_test.rb @@ -97,6 +97,33 @@ class AutocompleteServiceTest < ActiveSupport::TestCase assert_autocomplete_includes("mole_under_eye", "~/mue", :tag_query) end + should "autocomplete tags from wiki and artist other names" do + create(:tag, name: "touhou") + create(:tag, name: "bkub", category: Tag.categories.artist) + create(:wiki_page, title: "touhou", other_names: %w[東方 东方 동방]) + create(:artist, name: "bkub", other_names: %w[大川ぶくぶ フミンバイン]) + + assert_autocomplete_equals(["touhou"], "東", :tag_query) + assert_autocomplete_equals(["touhou"], "东", :tag_query) + assert_autocomplete_equals(["touhou"], "동", :tag_query) + + assert_autocomplete_equals(["touhou"], "*東*", :tag_query) + assert_autocomplete_equals(["touhou"], "東*", :tag_query) + assert_autocomplete_equals([], "*東", :tag_query) + + assert_autocomplete_equals(["touhou"], "*方*", :tag_query) + assert_autocomplete_equals(["touhou"], "*方", :tag_query) + assert_autocomplete_equals([], "方", :tag_query) + + assert_autocomplete_equals(["bkub"], "*大*", :tag_query) + assert_autocomplete_equals(["bkub"], "大", :tag_query) + assert_autocomplete_equals([], "*大", :tag_query) + + assert_autocomplete_equals(["bkub"], "*川*", :tag_query) + assert_autocomplete_equals([], "*川", :tag_query) + assert_autocomplete_equals([], "川", :tag_query) + end + should "autocomplete wildcard searches" do create(:tag, name: "mole", post_count: 150) create(:tag, name: "mole_under_eye", post_count: 100)