How to get a list of all tags while using the gem 'acts-as-taggable-on' in Rails (not the counts)

THpubs picture THpubs · Mar 28, 2014 · Viewed 9.1k times · Source

I have set the acts-as-taggable-on gem in my model like this :

 acts_as_taggable_on :deshanatags

It use the context deshanatags. Now I need to get a list of all the tags (not only the ones assigned for one item. I need everything) in this context in the following format :

[
    {"id":"856","name":"House"},
    {"id":"1035","name":"Desperate Housewives"}
]

How can I do this?

I tried to follow many tutorials but hit dead ends because most of them are written for Rails 3. Rails for have some changes to the model like removal of attr_accessor which make it difficult for me to understand those tutorials. So please help.

Simply im trying to add Jquery Token input (http://loopj.com/jquery-tokeninput/) to my app

PS : Through Tagging table, is there a way to get a list of tags like the output of Tag.all by filtering the context?

Answer

Danny picture Danny · Mar 28, 2014

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)")