oobie11
oobie11

Reputation: 925

How do I create a list of the most used tags associated with a model?

I wasn't too sure how to title this question, but I'll explain here. I'm on rails 4 and I'm trying to build a wine review app. I have a wine model and a review model that is associated..

wine.rb

has_many :reviews

review.rb

belongs_to :wine
has_many :taggings
has_many :tags, through: :taggings

My reviews have tags that are made through a has_many has_many relationship with a separate model "tagging.rb"

tag.rb

has_many :taggings
has_many :reviews, through: :taggings

tagging.rb

belongs_to :review
belongs_to :tag

On my wine show.html.erb page I display a list of all the reviews and each review shows what it has been tagged with. I am trying to count the number of times that each tag has been used on the reviews and display a list of the top 5 tags the wine has received, based on all the reviews. How would I do this?

I am able to get a list of the top 5 used tags app wide with this in my review.rb

def self.tag_counts
    Tag.select("tags.*, count(taggings.tag_id) as count").
        joins(:taggings).group("taggings.tag_id").order("count DESC").limit(5)
end

But I want to be able to get the top 5 used on a specific wine. Thanks.

Update

Thanks to @kardeiz for helping me though this :). I ended up using this to get the result I was looking for

Tag.joins(:reviews => :wine).where("wines.id = ?", self.id).group("taggings.tag_id").select("wines.id, tags.*, COUNT(taggings.tag_id) as count").order('count DESC').limit(5)

then in my view I have @wine.tag_counts.each to iterate over each tag. Then each iteration I have it print out the tag name and the count.

Upvotes: 0

Views: 80

Answers (1)

Jacob Brown
Jacob Brown

Reputation: 7561

I don't have test data readily available to confirm this works, but I think this is what you want (split for legibility):

Tag
  .joins(:reviews => :wine)
  .where('wines.id = ?', whatever_id)
  .group("taggings.tag_id")
  .order("COUNT(taggings.tag_id) DESC")
  .limit(5)

EDIT

Sorry, I misread the question. I think this should do what you want (though I haven't tested):

in_sql = Tag
  .joins(:reviews => :wine)
  .group("taggings.tag_id")
  .select("wines.id as wid, tags.*, COUNT(taggings.tag_id) as count")
  .to_sql

out_sql = %Q{
  select * 
  from (#{in_sql})
  where wid = #{whatever_id}
  order by count
  limit 5
}

ActiveRecord::Base.connection.execute(out_sql)

Upvotes: 1

Related Questions