From 37489346488b004c60e3a4aa297a8c80f23e7706 Mon Sep 17 00:00:00 2001 From: albert Date: Fri, 30 Sep 2011 16:40:24 -0400 Subject: [PATCH] added related tag query model, fixes to related tag calculator --- app/logical/related_tag_query.rb | 46 ++++++++++++++++++ app/models/tag.rb | 8 ++-- app/models/wiki_page.rb | 10 ++++ test/unit/related_tag_query_test.rb | 74 +++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 app/logical/related_tag_query.rb create mode 100644 test/unit/related_tag_query_test.rb diff --git a/app/logical/related_tag_query.rb b/app/logical/related_tag_query.rb new file mode 100644 index 000000000..bd01c8f92 --- /dev/null +++ b/app/logical/related_tag_query.rb @@ -0,0 +1,46 @@ +class RelatedTagQuery + attr_reader :query, :category + + def initialize(query, category) + @query = query + @category = category + end + + def tags + if query =~ /\*/ + pattern_matching_tags + elsif category.present? + related_tags_by_category + else + related_tags + end + end + + def wiki_page_tags + wiki_page.try(:tags) || [] + end + +protected + + def pattern_matching_tags + Tag.name_matches(query).order("post_count desc").limit(50).sort_by {|x| x.name}.map(&:name) + end + + def related_tags + tag = Tag.named(query).first + + if tag + tag.related_tag_array.map(&:first) + else + [] + end + end + + def related_tags_by_category + RelatedTagCalculator.calculate_from_sample_to_array(query, Tag.categories.value_for(category)).map(&:first) + end + + def wiki_page + WikiPage.titled(query).first + end +end diff --git a/app/models/tag.rb b/app/models/tag.rb index 0e27d4e6f..fc590b9b2 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -2,7 +2,8 @@ class Tag < ActiveRecord::Base attr_accessible :category after_save :update_category_cache has_one :wiki_page, :foreign_key => "name", :primary_key => "title" - scope :name_matches, lambda {|name| where(["name LIKE ? ESCAPE E'\\\\'", name.to_escaped_for_sql_like])} + scope :name_matches, lambda {|name| where("name LIKE ? ESCAPE E'\\\\'", name.to_escaped_for_sql_like)} + scope :named, lambda {|name| where("name = ?", TagAlias.to_aliased([name]).join(""))} search_methods :name_matches class CategoryMapping @@ -310,8 +311,9 @@ class Tag < ActiveRecord::Base module RelationMethods def update_related return unless should_update_related? - counts = RelatedTagCalculator.calculate_from_sample(Danbooru.config.post_sample_size, name) - update_attributes(:related_tags => RelatedTagCalculator.convert_hash_to_string(counts), :related_tags_updated_at => Time.now) + self.related_tags = RelatedTagCalculator.calculate_from_sample_to_array(name).join(" ") + self.related_tags_updated_at = Time.now + save end def update_related_if_outdated diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index b4cc8da2a..3e21eff79 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -88,4 +88,14 @@ class WikiPage < ActiveRecord::Base def presenter @presenter ||= WikiPagePresenter.new(self) end + + def tags + body.scan(/\[\[(.+?)\]\]/).flatten.map do |match| + if match =~ /^(.+?)\|(.+)/ + $1 + else + match + end + end.map {|x| x.downcase.tr(" ", "_")} + end end diff --git a/test/unit/related_tag_query_test.rb b/test/unit/related_tag_query_test.rb new file mode 100644 index 000000000..81b1b983d --- /dev/null +++ b/test/unit/related_tag_query_test.rb @@ -0,0 +1,74 @@ +require 'test_helper' + +class RelatedTagQueryTest < ActiveSupport::TestCase + setup do + user = Factory.create(:user) + CurrentUser.user = user + CurrentUser.ip_addr = "127.0.0.1" + MEMCACHE.flush_all + Delayed::Worker.delay_jobs = false + end + + context "a related tag query without a category constraint" do + setup do + @post_1 = Factory.create(:post, :tag_string => "aaa bbb") + @post_2 = Factory.create(:post, :tag_string => "aaa bbb ccc") + end + + context "for a tag that already exists" do + setup do + Tag.named("aaa").first.update_related + @query = RelatedTagQuery.new("aaa", "") + end + + should "work" do + assert_equal(["aaa", "bbb", "ccc"], @query.tags) + end + end + + context "for a tag that doesn't exist" do + setup do + @query = RelatedTagQuery.new("zzz", "") + end + + should "work" do + assert_equal([], @query.tags) + end + end + + context "for a pattern search" do + setup do + @query = RelatedTagQuery.new("a*", "") + end + + should "work" do + assert_equal(["aaa"], @query.tags) + end + end + + context "for a tag with a wiki page" do + setup do + @wiki_page = Factory.create(:wiki_page, :title => "aaa", :body => "[[bbb]] [[ccc]]") + @query = RelatedTagQuery.new("aaa", "") + end + + should "find any tags embedded in the wiki page" do + assert_equal(["bbb", "ccc"], @query.wiki_page_tags) + end + end + end + + context "a related tag query with a category constraint" do + setup do + @post_1 = Factory.create(:post, :tag_string => "aaa bbb") + @post_2 = Factory.create(:post, :tag_string => "aaa art:ccc") + @post_3 = Factory.create(:post, :tag_string => "aaa copy:ddd") + @query = RelatedTagQuery.new("aaa", "artist") + end + + should "find the related tags" do + assert_equal(%w(ccc), @query.tags) + end + end +end +