【问题标题】:Sum of all amount if created_at dates are the same in Rails如果 created_at 日期在 Rails 中相同,则所有金额的总和
【发布时间】:2016-05-01 20:28:08
【问题描述】:

我正在尝试使用 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'

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

【问题讨论】:

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


    【解决方案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)
    

    比您当前的方法简单得多。

    console.log()在Rails中的等价物是Rails.logger.info(),你也可以使用Rails.logger.warn()Rails.logger.error()。实际上,任何输出到STDOUT 的函数,例如putsprint 都会输出到您的控制台。

    【讨论】:

    • 啊,谢谢。当我使用 pluck 时,我现在得到 undefined method []' 代表 Sun,2016 年 5 月 1 日 07:07:35 UTC +00:00:Time`。
    • 让我仔细检查一下。
    • undefined method to_date for nil:NilClass 在同一行。我现在使用f = Hash[Foo.where(client_id: 4).pluck(:created_at, :amount)] 而不是我的第一个。对吗?
    • 关闭。 pluck() 返回一个数组。使用f = Foo.all.where(client_id: 4).pluck(:created_at, :amount) 并使用yield Hash[bar] 生成块中数组的每个元素。请参阅我的更新答案。
    • 忘记删除了,抱歉
    猜你喜欢
    • 2016-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-24
    相关资源
    最近更新 更多