You can do it:
MealPick.joins(:meal => :canteen) .where("canteens.id = ?", 1) .order("count_all DESC") .group(:meal_id) .count
This will return an ordered hash as follows:
{ 200 => 25 }
Where 200 will be the identifier of the food, and 25 will be the counter.
Update
For everyone who is interested, I started playing with this to find out if I can use subqueries with ActiveRecord to give me meaningful information than before. Here is what I have:
class Meal < ActiveRecord::Base belongs_to :canteen has_many :meal_picks attr_accessible :name, :price scope :with_grouped_picks, ->() { query = <<-QUERY INNER JOIN (#{Arel.sql(MealPick.counted_by_meal.to_sql)}) as top_picks ON meals.id = top_picks.meal_id QUERY joins(query) } scope :top_picks, with_grouped_picks.order("top_picks.number_of_picks DESC") scope :top_pick, top_picks.limit(1) end class MealPick < ActiveRecord::Base belongs_to :meal attr_accessible :user scope :counted_by_meal, group(:meal_id).select("meal_id, count(*) as number_of_picks") scope :top_picks, counted_by_meal.order("number_of_picks DESC") scope :top_pick, counted_by_meal.order("number_of_picks DESC").limit(1) end class Canteen < ActiveRecord::Base attr_accessible :name has_many :meals has_many :meal_picks, through: :meals def top_picks @top_picks ||= meals.top_picks end def top_pick @top_pick ||= top_picks.first end end
This allows me to do this:
c = Canteen.first c.top_picks
Let's say that I wanted to order all the dishes according to the number of peaks. I could do this:
Meal.includes(:canteen).top_picks #Returns all meals for all canteens ordered by number of picks. Meal.includes(:canteen).where("canteens.id = ?", some_id).top_picks #Top picks for a particular canteen Meal.includes(:canteen).where("canteens.location = ?", some_location) #Return top picks for a canteens in a given location
Since we use union, grouping, and server-side counts, the entire collection does not need to be loaded to determine the sampling counter. It is a little more flexible and probably more efficient.