如果created_at日期在Rails中相同,则所有金额的总和

时间:2016-05-01 10:14:04

标签: ruby-on-rails ruby ruby-on-rails-4

我尝试使用Rails数据库(pg)查询replicate this,但没有太多运气。

我的Foo表有很多列,但我对created_atamount感兴趣。

Foo.all.where(client_id: 4)看起来像这样:

[
  [0] {:created_at => <date>, :amount => 20},
  [1] {:created_at => <different date>, :amount => 5},
  ...
]

Stripe Charge Object在json,所以我想我可以:

f = Foo.all.where(client_id: 4).as_json # could I?

无论如何,我的控制器:

# As per first link above
def each_user_foo
  starting_after = nil
  loop do
    f = Foo.all.where(client_id: 4).as_json
    #f_hash = Hash[f.each_slice(2).to_a] # I was trying something here
    break if f.none?
    f.each do |bar|
      yield bar
    end
    starting_after = bar.last.id
  end
end

foo_by_date = Hash.new(0)

each_user_foo do |f|
  # Parses date object. `to_date` converts a DateTime object to a date (daily resolution).
  amount_date = DateTime.strptime(f.created_at.to_s, "%s").to_date # line 50
  amount = f.amount

  # Initialize the amount for this date to 0.
  foo_by_date[amount_date] ||= 0

  foo_by_date[amount_date] += amount
end

第50行的错误是:

  

未定义的方法`created_at&#39;对于哈希

我猜一个对象仍然在某个数组中。另外,Rails中的JS console.log()是否相同?会很方便。

1 个答案:

答案 0 :(得分:1)

看起来f通过调用as_json存储为Hash对象,但是您通过使用each_user_foo块中的普通Ruby对象来对待它.运算符。

解决方案是使用散列访问器运算符(例如f[:created_at])。您也不需要对日期进行字符串化和解析,因为它已经是DateTime对象:

amount_date = f[:created_at].to_date # line 50
amount = f[:amount]

另外,Foo是模型类吗?如果是这样,我建议您使用pluck来获取所需的属性,这比调用as_json更有效,更清晰:

# As per first link above
def each_user_foo
    f = Foo.where(client_id: 4).pluck(:created_at, :amount)
    f.each do |bar|
      yield(bar.first, bar.last)
    end
end

foo_by_date = Hash.new(0)

each_user_foo do |created_at, amount|
  # Parses date object. `to_date` converts a DateTime object to a date (daily resolution).
  amount_date = created_at.to_date # line 50
  foo_by_date[amount_date] += amount
end

您也可以删除此行:

foo_by_date[amount_date] ||= 0 

由于您在foo_by_date = Hash.new(0)变量分配中使用了初始值设定项。

修改

如果您正在使用Postgres,请执行以下操作:

Foo.where(client_id: 4).group("date_trunc('day', created_at)").sum(:amount)

或者对于MySQL:

Foo.where(client_id: 4).group("DAY(created_at)").sum(:amount)

比你目前的方法简单得多。

Rails中的console.log()相当于Rails.logger.info(),您还可以使用Rails.logger.warn()Rails.logger.error()。实际上,输出到STDOUT的任何函数(例如putsprint)都会输出到您的控制台。