How to get a list of all tags while using the gem 'acts-as-taggable-on' in Rails (not the counts)
The tags are stored in the Tags table, which you access from your program with e.g.
ActsAsTaggableOn::Tag.all
If you need more info on tag usage, there is also the table
ActsAsTaggableOn::Tagging
which contains links to where each tag is being used, including its context
To further apply this to your example, you can use
ActsAsTaggableOn::Tagging.includes(:tag).where(context: 'deshanatags').map { |tagging| { 'id' => tagging.tag_id.to_s, 'name' => tagging.tag.name } }.uniq
Let's explain the various parts in this statement:
- the 'includes' makes sure the different tags are "eager loaded", in other words, that instead of loading n+1 records, only 2 queries will be done on the database
- the 'where' limits the records to the ones with the given context
- the 'map' converts the resulting array of records into a new array, containing the hashes you asked for in your problem, with id mapped to the tag's id, and name mapped to the tag's name
- finally the 'uniq' makes sure that you don't have doubles in your list
To also cope with your additional problem, being taggins without tag, you could extend the where clause to
where("(context = 'deshanatags') AND (tag_id IS NOT NULL)")
How to get *ALL* tags on an acts_as_taggable object regardless of its contexts
c.base_tags.map(&:name)
There is no built-in shortcut to get the names directly, but that's short enough :)
Edit: base_tags
is an association defined on classes declared as taggable: has_many :base_tags, through: :taggings, source: :tag, class_name: '::ActsAsTaggableOn::Tag'
Source: https://github.com/mbleigh/acts-as-taggable-on/blob/master/lib/acts_as_taggable_on/taggable.rb
How to count the amount of times a tag has been used with ActsAsTaggableOn rails
According to this and this, you should be able to:
Post.tag_counts
Given :tags
is the "context" you used on the Post
model.
Listing all tags for an acts_as_taggable
You dont need to go through all the trouble of creating a tag model and controller. `acts-as-taggable-on provides a method to find a list of all tags for the model.
2.0.0-p451 :008 > Factoid.tag_counts
ActsAsTaggableOn::Tag Load (2.0ms) SELECT tags.*, taggings.tags_count AS count FROM "tags" JOIN (SELECT taggings.tag_id, COUNT(taggings.tag_id) AS tags_count FROM "taggings" INNER JOIN factoids ON factoids.id = taggings.taggable_id WHERE (taggings.taggable_type = 'Factoid' AND taggings.context = 'tags') AND (taggings.taggable_id IN(SELECT factoids.id FROM "factoids")) GROUP BY taggings.tag_id HAVING COUNT(taggings.tag_id) > 0) AS taggings ON taggings.tag_id = tags.id
=> #<ActiveRecord::Relation [#<ActsAsTaggableOn::Tag id: 1, name: "tag">]>
This will return a ActiveRecord::Relation of all the tag objects. You can run map on it to get a array of tags
Factoid.tag_counts.map(&:name)
=> ["tag"]
Return all tags based on context - ActsAsTaggableOn
I have never used acts-as-taggable-on but a quick browse through of the code suggests, you can do:
# to get all the tags with context topic with counts
ActsAsTaggableOn::Tagging.
includes(:tag).
where(:context => "topics").
group("tags.name").
select("tags.name, COUNT(*) as count")
You should probably take a look at ActsAsTaggableOn::Tagging, ActsAsTaggableOn::Tag and the migration file in your db/migrations folder to figure out how you can go about it.
If you don't want the count, only the tag names:
tags = ActsAsTaggableOn::Tag.includes(:taggings).
where("taggings.context = 'topics'").
select("DISTINCT tags.*")
# usage
tags.each {|tag| puts tag.name}
I hope that answers your question.
Acts-as-taggable-on find all tags by context
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
how to find number of tag matches in acts as taggable on
You can call tag_list
on the objects and use that to figure out how many tags there are:
tags = %w{hello world planet earth}
objs = ModelName.taggedWith(tags, :any => true)
objs.sort_by! { |o| -(tags & o.tag_list).length }
The tags & o.tag_list
yields the intersection of the tags you're looking for and the tags found, then we negate the size of the intersection to tell sort_by
(which sorts in ascending order) to put larger intersections at the front, negating the result is an easy way to reverse the usual sort order.
Related Topics
Rails Generate Has_Many Association
Rails Flash Message Remains for Two Page Loads
What Is the Easiest Way I Can Create a 'Beep' Sound from a Ruby Program
Ruby Koan 151 Raising Exceptions
Collect Values from an Array of Hashes
Iterate Every Month with Date Objects
Creating an Md5 Hash of a Number, String, Array, or Hash in Ruby
How Does Rails Implement Before_Filter
Rails - Testing JSON API with Functional Tests
Rails: Serializing Objects in a Database
Ruby: Select a Hash from Inside an Array
"Rmagick" Gem Installation Issue
How to Check What Is Queued in Activejob Using Rspec
How to Group This Array of Hashes
How to Run a Ruby Script Within Bundler Context