Sookie J Sookie J - 1 year ago 101
Ruby Question

Ruby select method in Has Many Through Association

Can you explain What the following method does and how it works? I have tried to understand it researching for several hours, but I couldn't figure it out yet.

def self.tag_counts
Tag.select("tags.name, count(taggings.tag_id) as count").joins(:taggings).group("taggings.tag_id")
end


What I understand is the ruby method 'select' usually takes a block, not like the one used in this method. The self.tag_counts method is in the event model of my application as follows.

models/event.rb

class Event < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: :slugged

belongs_to :organizers, class_name: "User"
has_many :taggings
has_many :tags, through: :taggings

def all_tags
tags.map(&:name).join(",")
end

def all_tags=(names)
self.tags = names.split(",").map do |n|
Tag.where(name: n.strip).first_or_create!
end
end

def self.tagged_with(name)
Tag.find_by_name!(name).events
end

def self.tag_counts
Tag.select("tags.name, count(taggings.tag_id) as count").joins(:taggings).group("taggings.tag_id")
end
end


models/tag.rb

class Tag < ActiveRecord::Base
has_many :taggings
has_many :events, through: :taggings
end


models/tagging.rb

class Tagging < ActiveRecord::Base
belongs_to :tag
belongs_to :event
end

Answer Source

This is an ActiveRecord query of the database. It's returning the list of tags with name and number of taggings. It looks like the input data for a tag cloud or a tag leaderboard.

This will produce something like the following SQL statement:

   SELECT tag.name, count(taggings.tag_id) as count
     FROM tags
LEFT JOIN taggings ON tags.id = taggings.tag_id
 GROUP BY taggings.tag_id

When you think of the Ruby select method, you may be thinking of the Array#select method, which is essentially a filter for arrays. The ActiveRecord select method is a database query refinement tool. You can read more about it in the Active Record Query Interface guide in the Selecting Specific Fields section.