rails activerecord sum适用于.each但不适用于其他人

时间:2014-08-08 16:12:00

标签: ruby-on-rails ruby postgresql activerecord

我正在尝试计算activerecords中的平衡,一个是有效的,另一个是无效的。

1 =>为什么这不能达到平衡:

@accounts_balances = Account.select('(sum("in")) - (sum("out")) as balance_amount')
puts "exist #{@accounts_balances.exists?}"
puts "balance: #{@accounts_balances.balance_amount}"

错误:

undefined method `balance_amount' for #<ActiveRecord::Relation [#<Account id: nil>]>

2 =&GT;虽然这有效:

Account.select('(sum("in")) - (sum("out")) as balance_amount').each do |value|
  puts value.balance_amount
end

我不喜欢在2号中使用.each,并且更愿意执行sql语句并获取余额。这个问题是什么?

1 个答案:

答案 0 :(得分:2)

以下内容可行:

@accounts_balances[0].balance_amount

实际上@accounts_balances不是ActiveRecord对象。 @accounts_balancesActiveRecord个对象的集合。您需要从集合中提取ActiveRecord对象。

看下面的例子: -

我有一个Comment型号。

arup@linux-wzza:~/Rails/model_prac> rails c
Loading development environment (Rails 4.1.4)
Comment.first
# => #<Comment id: 1, value_old: "I am a good Boy.", value_new: "I am a bad Boy.", created_at: "2014-08-02 17:36:14", updated_at: "2014-08-02 18:21:42">

现在看,#select方法为我们提供了一个ActiveRecord::Relation对象。这意味着它是ActiveRecord个对象的集合。

Comment.select("value_old")
# => #<ActiveRecord::Relation [#<Comment id: nil, value_old: "I am a good Boy.">, #<Comment id: nil, value_old: nil>]>
Comment.select("value_old").class
# => Comment::ActiveRecord_Relation

现在,您可以从Array#[]方法的集合中获取这些ActiveRecord对象。

Comment.select("value_old")[0]
# => #<Comment id: nil, value_old: "I am a good Boy.">
Comment.select("value_old")[0].class
# => Comment(id: integer, value_old: text, value_new: text, created_at: datetime, updated_at: datetime)

因此,Comment.select("value_old")[0]正在为您提供ActiveRecord个对象。现在,您可以调用Rails为您提供的自动 getter 方法。看下面: -

Comment.select("value_old")[0].value_old
# => "I am a good Boy."

以下是不行的,我上面说的原因。因为它是集合

Comment.select("value_old").value_old
# undefined method `value_old' for #<Comment::ActiveRecord_Relation:0xa780e88>

为什么#each方法有效?

原因是 - 当您在块中调用#each时,它会在每次迭代中传递一个AR 对象,并且一旦您拥有 AR 对象你的手,也可以调用 getter 方法,我已在上面展示过。

Comment.select("value_old").each { |r| p r.class }
# => Comment(id: integer, value_old: text, value_new: text, created_at: datetime, updated_at: datetime)
# => Comment(id: integer, value_old: text, value_new: text, created_at: datetime, updated_at: datetime)