4

クエリについてサポートが必要です。私は複数の食堂を持っており、それぞれに複数の食事があり、各食事には複数のMealPicksがあります。

このモデルが良いアイデアかどうかはわかりませんがMealPick、今日食事が選ばれた回数を表示する必要があるため、このクエリを実行するためにタイムスタンプが必要でした。

class Meal < ActiveRecord::Base
  def todays_picks
    meal_picks.where(["created_at >= ? AND created_at < ?", Date.today.beginning_of_day, Date.today.end_of_day])
  end
end

Mealにmeal_picked_countカウンターがあり、increment_counterメソッドでインクリメントする前。

さて、今度は各食堂にMealPicksが最も多い食事を表示する必要があります。コンソールで遊んでみましたCanteen.find(1).meals.maximum("meal_picks.count")が、列ではないため、明らかに機能しません。

何か案は?

4

2 に答える 2

6

あなたはこれを行うことができます:

MealPick.joins(:meal => :canteen)
        .where("canteens.id = ?", 1)
        .order("count_all DESC")
        .group(:meal_id)
        .count

これにより、次のような順序付きハッシュが返されます。

{ 200 => 25 }

200食事IDはどこに25あり、カウントはどこになりますか。

アップデート

興味のある人のために、私はこれをいじって、ActiveRecordでサブクエリを使用して、以前に思いついたものよりも意味のある情報を提供できるかどうかを確認し始めました。これが私が持っているものです:

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

これにより、これを行うことができます。

c = Canteen.first
c.top_picks #Returns their meals ordered by the number of picks
c.top_pick  #Returns the one with the top number of picks

ピック数ですべての食事を注文したいとしましょう。私はこれを行うことができます:

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

結合、グループ化、およびサーバー側のカウントを使用しているため、ピックカウントを決定するためにコレクション全体をロードする必要はありません。これはもう少し柔軟性があり、おそらくより効率的です。

于 2012-12-12T21:33:16.427 に答える
-1
canteen.meals.max {|m| m.meal_picked_count}
于 2012-12-12T20:56:05.743 に答える