Sookie J Sookie J - 6 months ago 24
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

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.