简体   繁体   English

Rails,将模型所有实例的属性的总和求和

[英]Rails, sum the aggregate of an attribute of all instances of a model

I have a model Channel. 我有一个模特频道。 The relating table has several column, for example clicks. 相关表有几列,例如单击。

So Channel.all.sum(:clicks) gives me the sum of clicks of all channels. 所以Channel.all.sum(:clicks)给我所有频道的点击总和。

In my model I have added a new method 在我的模型中,我添加了一种新方法

def test
 123 #this is just an example
end

So now, Channel.first.test returns 123 所以现在Channel.first.test返回123

What I want to do is something like Channel.all.sum(:test) which sums the test value of all channels. 我要执行的操作类似于Channel.all.sum(:test) ,该操作将所有通道的测试值相加。

The error I get is that test is not a column, which of course it is not, but I hoped to till be able to build this sum. 我得到的错误是测试不是一列,当然不是,但我希望直到能够建立这个总和。

How could I achieve this? 我怎样才能做到这一点?

You could try: 您可以尝试:

Channel.all.map(&:test).sum

Where clicks is a column of the model's table, use: 如果点击是模型表的一列,请使用:

Channel.sum(:clicks)

To solve your issue, you can do 为了解决您的问题,您可以

Channel.all.sum(&:test)

But it would be better to try achieving it on the database layer, because processing with Ruby might be heavy for memory and efficiency. 但是最好尝试在数据库层上实现它,因为使用Ruby进行处理可能会增加内存和效率。

EDIT 编辑

If you want to sum by a method which takes arguments: 如果要通过带有参数的方法求和:

Channel.all.sum { |channel| channel.test(start_date, end_date) }

What you are talking about here is two very different things: 您在这里谈论的是两件截然不同的事情:

ActiveRecord::Calculations.sum sums the values of a column in the database: ActiveRecord::Calculations.sum对数据库中列的值求和:

SELECT SUM("table_name"."column_name") FROM "column_name"

This is what happens if you call Channel.sum(:column_name) . 如果调用Channel.sum(:column_name) ,就会发生这种情况。

ActiveSupport also extends the Enumerable module with a .sum method: ActiveSupport还使用.sum方法扩展了Enumerable模块

module Enumerable
  def sum(identity = nil, &block)
    if block_given?
      map(&block).sum(identity)
    else
      sum = identity ? inject(identity, :+) : inject(:+)
      sum || identity || 0
    end
  end 
end

This loops though all the values in memory and adds them together. 这会循环遍历内存中的所有值,并将它们加在一起。

Channel.all.sum(&:test)

Is equivalent to: 等效于:

Channel.all.inject(0) { |sum, c| sum + c.test }

Using the later can lead to serious performance issues as it pulls all the data out of the database. 使用后者可能会导致严重的性能问题,因为它将所有数据从数据库中拉出。

Alternatively you do this. 或者,您也可以这样做。

Channel.all.inject(0) {|sum,x| sum + x.test }

You can changed the 0 to whatever value you want the sum to start off at. 您可以将0更改为希望总和开始的任何值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM