diff --git a/app/assets/javascripts/autocomplete.js b/app/assets/javascripts/autocomplete.js index e1320e0c7..a4a64893d 100644 --- a/app/assets/javascripts/autocomplete.js +++ b/app/assets/javascripts/autocomplete.js @@ -173,11 +173,9 @@ } $.ajax({ - url: "/tags.json", + url: "/tags/autocomplete.json", data: { - "search[order]": "count", "search[name_matches]": term + "*", - "limit": 10 }, method: "get", success: function(data) { @@ -185,6 +183,7 @@ return { type: "tag", label: tag.name.replace(/_/g, " "), + antecedent: tag.antecedent_name, value: tag.name, category: tag.category, post_count: tag.post_count @@ -202,7 +201,16 @@ } Danbooru.Autocomplete.render_item = function(list, item) { - var $link = $("").text(item.label); + var $link = $(""); + + if (item.antecedent) { + var antecedent = item.antecedent.replace(/_/g, " "); + var arrow = $("").html(" → ").addClass("autocomplete-arrow"); + $link.append(document.createTextNode(antecedent)); + $link.append(arrow); + } + + $link.append(document.createTextNode(item.label)); $link.attr("href", "/posts?tags=" + encodeURIComponent(item.value)); $link.click(function(e) { e.preventDefault(); diff --git a/app/assets/stylesheets/common/autocomplete.css.scss b/app/assets/stylesheets/common/autocomplete.css.scss index 1f82f36ba..8fef7e117 100644 --- a/app/assets/stylesheets/common/autocomplete.css.scss +++ b/app/assets/stylesheets/common/autocomplete.css.scss @@ -5,4 +5,8 @@ .ui-menu-item a { padding: 1px .2em; } + + .autocomplete-arrow { + color: black; + } } \ No newline at end of file diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index e62e17776..56c24ffdf 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -17,6 +17,16 @@ class TagsController < ApplicationController end end + def autocomplete + @tags = Tag.names_matches_with_aliases(params[:search][:name_matches]) + + respond_with(@tags) do |format| + format.xml do + render :xml => @tags.to_xml(:root => "tags") + end + end + end + def search end diff --git a/app/logical/daily_maintenance.rb b/app/logical/daily_maintenance.rb index 6a22800e8..3440d9105 100644 --- a/app/logical/daily_maintenance.rb +++ b/app/logical/daily_maintenance.rb @@ -12,5 +12,6 @@ class DailyMaintenance TagSubscription.process_all ApiCacheGenerator.new.generate_tag_cache ForumSubscription.process_all! + TagAlias.update_cached_post_counts_for_all end end diff --git a/app/models/tag.rb b/app/models/tag.rb index 780c9b700..96707aef9 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -673,6 +673,23 @@ class Tag < ActiveRecord::Base q end + + def names_matches_with_aliases(name) + query1 = Tag.select("tags.name, tags.post_count, tags.category, null AS antecedent_name") + .search(:name_matches => name, :order => "count").limit(10) + + name = name.mb_chars.downcase.to_escaped_for_sql_like + query2 = TagAlias.select("tags.name, tag_aliases.post_count, tags.category, tag_aliases.antecedent_name") + .joins("INNER JOIN tags ON tags.name = tag_aliases.consequent_name") + .where("tag_aliases.antecedent_name LIKE ? ESCAPE E'\\\\'", name) + .where("tags.name NOT LIKE ? ESCAPE E'\\\\'", name) + .where("tag_aliases.post_count > 0") + .order("tag_aliases.post_count desc") + .limit(20) # Get 20 records even though only 10 will be displayed in case some duplicates get filtered out. + + sql_query = "((#{query1.to_sql}) UNION ALL (#{query2.to_sql})) AS unioned_query" + Tag.select("DISTINCT ON (name, post_count) *").from(sql_query).order("post_count desc").limit(10) + end end def editable_by?(user) diff --git a/app/models/tag_alias.rb b/app/models/tag_alias.rb index 483f0b0d6..7741644da 100644 --- a/app/models/tag_alias.rb +++ b/app/models/tag_alias.rb @@ -254,4 +254,8 @@ class TagAlias < ActiveRecord::Base update_forum_topic_for_reject destroy end + + def self.update_cached_post_counts_for_all + execute_sql("UPDATE tag_aliases SET post_count = tags.post_count FROM tags WHERE tags.name = tag_aliases.consequent_name") + end end diff --git a/config/routes.rb b/config/routes.rb index 8a7e65f92..51f97bd80 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -213,6 +213,9 @@ Rails.application.routes.draw do resource :source, :only => [:show] resources :tags do resource :correction, :only => [:new, :create, :show], :controller => "tag_corrections" + collection do + get :autocomplete + end end resources :tag_aliases do resource :correction, :controller => "tag_alias_corrections" diff --git a/db/migrate/20150403224949_add_antecedent_name_pattern_index_and_post_count_to_tag_aliases.rb b/db/migrate/20150403224949_add_antecedent_name_pattern_index_and_post_count_to_tag_aliases.rb new file mode 100644 index 000000000..abb854ddd --- /dev/null +++ b/db/migrate/20150403224949_add_antecedent_name_pattern_index_and_post_count_to_tag_aliases.rb @@ -0,0 +1,14 @@ +class AddAntecedentNamePatternIndexAndPostCountToTagAliases < ActiveRecord::Migration + def up + execute "set statement_timeout = 0" + execute "create index index_tag_aliases_on_antecedent_name_pattern on tag_aliases (antecedent_name text_pattern_ops)" + add_column :tag_aliases, :post_count, :integer, :null => false, :default => 0 + add_index :tag_aliases, :post_count + end + + def down + execute "set statement_timeout = 0" + execute "drop index index_tag_aliases_on_antecedent_name_pattern" + remove_column :tag_aliases, :post_count + end +end