4

Rails3の問題。次の属性を持つ食品の Foods テーブルがあります。

  • 名前
  • カロリー(グラムあたり)
  • 脂肪 (グラムあたり)
  • 炭水化物(グラムあたり)
  • タンパク質(グラムあたり)

次に、特定の時間に食べられた食品を表す LoggedFoods テーブルを作成します。次の属性があります。

  • food_id
  • number_of_grams_eaten
  • ate_when (日時)

したがって、私が抱えている問題は、1 日 (すべての日) に消費されるカロリー、脂肪、タンパク質、炭水化物の合計数を 1 つのクエリで取得したいということです。新しい ActiveRecord クエリ インターフェイスを使用してこの Rails 3 を実行しようとしましたが、うまくいきませんでした。何か案は?

4

1 に答える 1

12

いくつかのバグがあるかもしれませんが、数値は一目で正しいように見えます。また、これは sqlite3 でのみテストしたため、他のデータベースでの結果は異なる場合があります (SUM またはグループ関数が異なる場合)。

app/models/logged_food.rb

class LoggedFood < ActiveRecord::Base
  belongs_to :food

  def self.totals_by_day(date)
    start_time = Time.parse(date).beginning_of_day
    end_time = Time.parse(date).end_of_day

    t = LoggedFood.arel_table

    totals = LoggedFood.
      where(t[:ate_when].gteq(start_time)).
      where(t[:ate_when].lteq(end_time)).
      joins(:food).
      select("SUM(calories * grams_eaten) as total_calories").
      select("SUM(fat * grams_eaten) as total_fat").
      select("SUM(carbs * grams_eaten) as total_carbs").
      select("SUM(protien * grams_eaten) as total_protien")

    return nil if totals.empty?

    {
      :total_calories => totals.first.total_calories, 
      :total_fat => totals.first.total_fat,
      :total_carbs => totals.first.total_carbs,
      :total_protien => totals.first.total_protien
    }

  end

end

db/seeds.rb(もちろん食品の栄養成分はわかりません)

@pizza = Food.create(:name => "pizza", :calories => 500, :fat => 10, :carbs => 20, :protien => 30)
@hot_dog = Food.create(:name => "hot dog", :calories => 400, :fat => 10, :carbs => 20, :protien => 30)
@apple = Food.create(:name => "apple", :calories => 100, :fat => 1, :carbs => 2, :protien => 3)
@banana = Food.create(:name => "banana", :calories => 100, :fat => 2, :carbs => 4, :protien => 6)

LoggedFood.create(:food_id => @pizza.id, :grams_eaten => 10, :ate_when => Time.now)
LoggedFood.create(:food_id => @apple.id, :grams_eaten => 10, :ate_when => Time.now)
LoggedFood.create(:food_id => @banana.id, :grams_eaten => 10, :ate_when => 12.hours.ago)
LoggedFood.create(:food_id => @apple.id, :grams_eaten => 10, :ate_when => 1.day.ago)
LoggedFood.create(:food_id => @pizza.id, :grams_eaten => 10, :ate_when => 2.days.ago)
LoggedFood.create(:food_id => @banana.id, :grams_eaten => 10, :ate_when => 36.hours.ago)
LoggedFood.create(:food_id => @hot_dog.id, :grams_eaten => 10, :ate_when => 2.days.ago)
LoggedFood.create(:food_id => @banana.id, :grams_eaten => 10, :ate_when => 50.hours.ago)

次に、コンソールで:

ree-1.8.7-2010.02 > LoggedFood.totals_by_day("2010-08-27")
  LoggedFood Load (0.2ms)  SELECT SUM(calories * grams_eaten) as total_calories, SUM(fat * grams_eaten) as total_fat, SUM(carbs * grams_eaten) as total_carbs, SUM(protien * grams_eaten) as total_protien FROM "logged_foods" INNER JOIN "foods" ON "foods"."id" = "logged_foods"."food_id" WHERE ("logged_foods"."ate_when" >= '2010-08-27 04:00:00.000000') AND ("logged_foods"."ate_when" <= '2010-08-28 03:59:59.999999') LIMIT 1
 => {:total_fat=>130, :total_protien=>390, :total_calories=>7000, :total_carbs=>260} 

ree-1.8.7-2010.02 > LoggedFood.totals_by_day("2010-08-26")
  LoggedFood Load (0.3ms)  SELECT SUM(calories * grams_eaten) as total_calories, SUM(fat * grams_eaten) as total_fat, SUM(carbs * grams_eaten) as total_carbs, SUM(protien * grams_eaten) as total_protien FROM "logged_foods" INNER JOIN "foods" ON "foods"."id" = "logged_foods"."food_id" WHERE ("logged_foods"."ate_when" >= '2010-08-26 04:00:00.000000') AND ("logged_foods"."ate_when" <= '2010-08-27 03:59:59.999999') LIMIT 1
 => {:total_fat=>30, :total_protien=>90, :total_calories=>2000, :total_carbs=>60} 
于 2010-08-27T23:26:57.497 に答える