使用inject方法对数组rails的实例求和

时间:2014-07-23 20:03:52

标签: ruby-on-rails ruby arrays sorting

我有一个名为@jdc_array的实例变量,在检查时其内容如下所示:

"[#<ActiveRecord::Associations::CollectionProxy [#<JobDeliveryCost id: 13, job_id: 53, delivery_cost_id: 1, cost_per_unit: 50.0, quantity: 3, timing: \"install\", created_at: \"2014-07-23 15:20:34\", updated_at: \"2014-07-23 15:20:34\">, #<JobDeliveryCost id: 15, job_id: 53, delivery_cost_id: 1, cost_per_unit: 50.0, quantity: 5, timing: \"install\", created_at: \"2014-07-23 15:57:45\", updated_at: \"2014-07-23 15:57:45\">, #<JobDeliveryCost id: 18, job_id: 53, delivery_cost_id: 1, cost_per_unit: 44.0, quantity: 1, timing: \"breakdown\", created_at: \"2014-07-23 18:27:20\", updated_at: \"2014-07-23 18:27:20\">, #<JobDeliveryCost id: 19, job_id: 53, delivery_cost_id: 1, cost_per_unit: 22.0, quantity: 1, timing: \"install\", created_at: \"2014-07-23 18:27:28\", updated_at: \"2014-07-23 18:27:28\">, #<JobDeliveryCost id: 20, job_id: 53, delivery_cost_id: 1, cost_per_unit: 3.0, quantity: 1, timing: \"install\", created_at: \"2014-07-23 18:28:45\", updated_at: \"2014-07-23 18:28:45\">]>, nil]" 

我想总结cost_per_unit:的所有实例,所以我创建了这个方法

  def calculate_delivery_total(array)
    array.map(&:cost_per_unit).inject(0, &:+) 
  end

并像这样调用方法:

  def index 
    if get_deliverable
      @jdc_array=(@job.job_delivery_costs.any? ? [@job.job_delivery_costs,@new_delivery] : [@new_delivery])
      @new_delivery = @deliverable.job_delivery_costs.build
    end
    set_job_delivery_cost
    @total = calculate_delivery_total(@jdc_array)
  end

但是我发现这个错误!?!

formal argument cannot be an instance variable def calculate_delivery_total(@array) 

三个问题。为什么我会收到此错误,如何解决?第三,在控制器中做这样的事情是好的形式,还是我应该在其他地方做这些以及如何做?

更新

所以按照SO海报的建议我将方法改为

  def calculate_delivery_total(array)
    array.map(&:cost_per_unit).inject(0, &:+)
  end

但我仍然收到此错误

undefined method `cost_per_unit' for #<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_JobDeliveryCost:0x00000106172788>

我可以在控制台中执行此操作,为什么不在这里工作?!

2 个答案:

答案 0 :(得分:0)

要回答第二个问题,我使用外观模式为视图准备数据。这样可以避免在视图或控制器中进行计算,并促进关注点和重用的分离。

这是一个资源,但我可以在编辑中进行扩展。

https://medium.com/@ryakh/facade-pattern-on-rails-d65b86cdb5b1


对于错误,它是一个猜测,但可能是数组的最后一个元素是零吗?你试过.to_a和紧凑型吗?

def calculate_delivery_total(array) array.to_a.compact.map(&:cost_per_unit).inject(0, &:+) end

答案 1 :(得分:0)

您的@jdc_array可以是以下两个值之一:

[@job.job_delivery_costs,@new_delivery]

或者

[@new_delivery]

我不知道@new_delivery是什么,但job_delivery_costs会返回JobDeliveryCost集合(更具体地说是CollectionProxy)对象,这意味着你在集合中有一个集合。

另一方面,@new_delivery可能是nil(根据帖子开头的示例数据),可能是因为在您之后为其分配了一个值。把它放在数组(数组中的值不会改变) - 你需要交换这些行。

我的建议是更改方法以接收两个参数 - 交付成本列表和新交付,如下所示:

def calculate_delivery_total(deliveries, new_delivery)
  total = 0
  unless deliveries.nil?
    total = deliveries.map(&:cost_per_unit)
  end
  unless new_delivery.nil?
    total += new_delivery.cost_per_unit
  end
  total
end

并且您的index代码应该如下所示:

  def index 
    if get_deliverable
      @new_delivery = @deliverable.job_delivery_costs.build
    end
    set_job_delivery_cost
    @total = calculate_delivery_total(@job.job_delivery_costs,@new_delivery)
  end