16
votes

So after searching for a tagging gem for my rails app I found the amazing acts-as-taggable gem. Installing it and playing around I discovered that it keeps all the Tags inside a tag db which just holds the Tag.name without the context, instead the context is held in the :through relationship db ( taggings ). For most purposes I can see this being perfect. Except with my app I want to be able to offer the user the ability to tag based on an pre-existing tags ( eg not allow them to create their own ) and acts-as-taggable doesn't have the ability to search all tags within one context built in ( eg, if I were to present an auto-completion of the tag db I would have all the tags in my app included which is'nt what I want )

The method below is what I just fleshed out to see if it would work ( which it does ) but I wondered if I was missing something with acts-as-taggable. I mean I can't see anywhere that offers this kind method?

<% ActsAsTaggableOn::Tagging.find_all_by_context("tags").each do |tagging| %>
  <%= tagging.tag %>
<% end %>

If for instance acts-as-taggable doesn't do this, is this the best way to do this? It feels a little non performant, Would I be better doing a custom SQL query instead of routing through acts-as-taggable?

If it helps at all heres a tail of my log:

Started GET "/users" for 127.0.0.1 at 2011-01-04 14:46:20 +0000
Processing by UsersController#index as HTML
SQL (0.5ms)   SELECT name
FROM sqlite_master
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
User Load (0.1ms)  SELECT "users".* FROM "users"
ActsAsTaggableOn::Tagging Load (0.5ms)  SELECT "taggings".* FROM "taggings" WHERE ("taggings"."context" = 'languages')
ActsAsTaggableOn::Tag Load (0.1ms)  SELECT "tags".* FROM "tags" WHERE ("tags"."id" = 2) LIMIT 1
Rendered users/index.html.erb within layouts/application (10.4ms)
2

2 Answers

16
votes

You could also use a statement like the following:

# Returns all the tags for the specified model/context with a count >= 1
@tags = YourModel.tag_counts_on(**context**)

Add limit and order:

# Get the top 5 tags by count
@tags = YourModel.tag_counts_on(**context**, :limit => 5, :order => "count desc")

Access the counts with the count attribute of the tags returned from tag_counts_on

tag.count
0
votes

I believe there is the way: User.tag_counts_on(:tags)

=> [#<ActsAsTaggableOn::Tag id: 1, name: "foo">,
#<ActsAsTaggableOn::Tag id: 2, name: "bar">,
#<ActsAsTaggableOn::Tag id: 3, name: "sushi">,
#<ActsAsTaggableOn::Tag id: 4, name: "pizza">]