Reputation: 12495
I'm using the rails gem acts-as-taggable on, and am tagging posts on two contexts: tags and topics.
To return a hash of all the topics tags used so far for posts I can use the code:
Post.tag_counts_on(:topics)
However, I have created a certain number of set topics tags, and if some of these topics tags aren't currently being used as tags on posts, then the code above doesn't return the said topics.
I am wondering if there is a way to return all the relevant tags based on context -- I was hoping for a solution along the lines of :
topics = Tag.topics
To implement the solution, I created a Tag.rb model:
class Tag < ActiveRecord::Base
has_many :relationship_topics, :foreign_key => "topic_followed_id", :dependent => :destroy
has_many :topic_followers, :through => :relationship_topics, :source => :topic_follower
end
Here I have some code to allow for following topics, but nothing more.
Does anyone know how I could return all the tags based on context?
Upvotes: 10
Views: 4399
Reputation: 1527
The method is very simple:
ActsAsTaggableOn::Tag.for_context('topics')
Upvotes: -1
Reputation: 41954
This worked best for me:
ActsAsTaggableOn::Tag.includes(:taggings).where(taggings:{context:'topics'}).uniq(:name).order(:name)
One limitation when doing joins
or includes
with a tagging context is that you will only see topics that are active. You cannot load up a topic list and have them show up using this query. See examples:
Without tagging context
2.2.1 :009 > ActsAsTaggableOn::Tag.includes(:taggings)
ActsAsTaggableOn::Tag Load (0.4ms) SELECT `tags`.* FROM `tags`
ActsAsTaggableOn::Tagging Load (0.4ms) SELECT `taggings`.* FROM `taggings` WHERE `taggings`.`tag_id` IN (1, 2, 3)
[
[0] severe hearing loss {
:id => 1,
:name => "severe hearing loss",
:taggings_count => 0
},
[1] hearing loss {
:id => 2,
:name => "hearing loss",
:taggings_count => 1
},
[2] hearing aids {
:id => 3,
:name => "hearing aids",
:taggings_count => 0
}
]
With taggings context of topics
2.2.1 :016 > ActsAsTaggableOn::Tag.includes(:taggings).where(taggings:{context:'topics'})
SQL (0.4ms) SELECT `tags`.`id` AS t0_r0, `tags`.`name` AS t0_r1, `tags`.`taggings_count` AS t0_r2, `taggings`.`id` AS t1_r0, `taggings`.`tag_id` AS t1_r1, `taggings`.`taggable_id` AS t1_r2, `taggings`.`taggable_type` AS t1_r3, `taggings`.`tagger_id` AS t1_r4, `taggings`.`tagger_type` AS t1_r5, `taggings`.`context` AS t1_r6, `taggings`.`created_at` AS t1_r7 FROM `tags` LEFT OUTER JOIN `taggings` ON `taggings`.`tag_id` = `tags`.`id` WHERE `taggings`.`context` = 'topics'
[
[0] hearing loss {
:id => 2,
:name => "hearing loss",
:taggings_count => 1
}
]
Upvotes: 0
Reputation: 3567
Use Model.tag_counts
(from Using acts-as-taggable-on how do I find the top, say 10, tags in my app?):
User.skill_counts # => [<Tag name="joking" count=2>,<Tag name="clowning" count=1>...]
Upvotes: 0
Reputation: 10907
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.
Upvotes: 17