Reputation: 8162
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?
Upvotes: 22
Views: 10738
Reputation: 1315
In more recent versions, you can use:
ActsAsTaggableOn::Tag.for_context(:deshanatags)
I ended up here from Google, but then found the answer in the wiki.
From the wiki
From the code
Upvotes: 4
Reputation: 412
I personally think that both solutions will be slow if you have many tags to retrieve as there are many single select statements. I'd do it like this:
ActsAsTaggableOn::Tagging.includes(:tag).where(context: 'deshanatags').uniq.pluck(:id, :name)
If you're on ruby 1.9+
This way you'll just end up with:
SELECT DISTINCT "taggings"."id", name FROM "taggings" LEFT OUTER JOIN "tags" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."context" = 'deshanatags'
Quick and easy imo
Upvotes: 5
Reputation: 6025
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:
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)")
Upvotes: 46
Reputation: 774
Using the ActsAsTaggableOn::Tagging
model, you can get a list of all tags and filter them down according to context, then format them as follows:
ActsAsTaggableOn::Tagging.all
.where(context: "deshanatags")
.map {|tagging| { "id" => "#{tagging.tag.id}", "name" => tagging.tag.name } }
The where
will give us a result of all taggings for a given context, which we then iterate over using map
, retrieving the related tag for each tagging in our result and getting the id and name attributes.
Make sure to chain the methods directly (not across several lines) if you're not using ruby 1.9+
You can then call .to_json on the result to get a properly formatted json object that you can use
I updated the post to clarify what each statement does and also updated the format of our final result to use strings as keys instead of symbols
Upvotes: 3