Skip to content
This repository has been archived by the owner on Dec 21, 2019. It is now read-only.

Commit

Permalink
Add find_related_tags method [Austin Foncaier].
Browse files Browse the repository at this point in the history
  • Loading branch information
jviney committed Mar 18, 2008
1 parent 97ed43f commit 870d449
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG
Expand Up @@ -2,6 +2,8 @@

* Add TagList#toggle [Pete Yandell].

# Add find_related_tags method [Austin Foncaier].

[30 Jan 08]

* Fix Tag.destroy_unused on Rails 2.0.
Expand Down
28 changes: 27 additions & 1 deletion lib/acts_as_taggable.rb
Expand Up @@ -29,7 +29,33 @@ def set_cached_tag_list_column_name(value = nil, &block)
end

module SingletonMethods
# Pass either a tag string, or an array of strings or tags
# Returns an array of related tags.
# Related tags are all the other tags that are found on the models tagged with the provided tags.
#
# Pass either a tag, string, or an array of strings or tags.
#
# Options:
# :order - SQL Order how to order the tags. Defaults to "count DESC, tags.name".
def find_related_tags(tags, options = {})
tags = tags.is_a?(Array) ? TagList.new(tags.map(&:to_s)) : TagList.from(tags)

related_models = find_tagged_with(tags)

return [] if related_models.blank?

related_ids = related_models.to_s(:db)

Tag.find(:all, options.merge({
:select => "#{Tag.table_name}.*, COUNT(#{Tag.table_name}.id) AS count",
:joins => "JOIN #{Tagging.table_name} ON #{Tagging.table_name}.taggable_type = '#{base_class.name}'
AND #{Tagging.table_name}.taggable_id IN (#{related_ids})
AND #{Tagging.table_name}.tag_id = #{Tag.table_name}.id",
:order => options[:order] || "count DESC, #{Tag.table_name}.name",
:group => "#{Tag.table_name}.id, #{Tag.table_name}.name HAVING #{Tag.table_name}.name NOT IN (#{tags.map { |n| quote_value(n) }.join(",")})"
}))
end

# Pass either a tag, string, or an array of strings or tags.
#
# Options:
# :exclude - Find models that are not tagged with the given tags
Expand Down
17 changes: 17 additions & 0 deletions test/acts_as_taggable_test.rb
Expand Up @@ -2,7 +2,24 @@

class ActsAsTaggableOnSteroidsTest < Test::Unit::TestCase
fixtures :tags, :taggings, :posts, :users, :photos, :subscriptions, :magazines

def test_find_related_tags_with
assert_equivalent [tags(:good), tags(:bad), tags(:question)], Post.find_related_tags("nature")
assert_equivalent [tags(:nature)], Post.find_related_tags([tags(:good)])
assert_equivalent [tags(:bad), tags(:question)], Post.find_related_tags(["Very Good", "Nature"])
assert_equivalent [tags(:bad), tags(:question)], Post.find_related_tags([tags(:good), tags(:nature)])
end

def test_find_related_tags_with_non_existent_tags
assert_equal [], Post.find_related_tags("ABCDEFG")
assert_equal [], Post.find_related_tags(['HIJKLM'])
end

def test_find_related_tags_with_nothing
assert_equal [], Post.find_related_tags("")
assert_equal [], Post.find_related_tags([])
end

def test_find_tagged_with
assert_equivalent [posts(:jonathan_sky), posts(:sam_flowers)], Post.find_tagged_with('"Very good"')
assert_equal Post.find_tagged_with('"Very good"'), Post.find_tagged_with(['Very good'])
Expand Down

0 comments on commit 870d449

Please sign in to comment.