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