Konrad Janczyk
Konrad Janczyk

Reputation: 182

ruby on rails sum fields after group_by

before I start I just want to tell that I tried some aproaches from similar topics but they don't work well with my case.

I have orders that I am grouping by days (using group_by(&:created_at) method). Now I want to sum "total" field from orders that are on particular days. It should look something like that: 21 May 2015 Total: 215 (order1 with total = 200 and order2 with total = 15) 22 May 2015 Total: 0 23 May 2015 Total: 321

I tried something like this

orders.to_a.map { |h| h[:total] }.sum 
orders.to_a.inject { |sum, h| sum += h[:total] }

but it prints me only totals from each order (not daily sum).

I am fetching data from database (postgres) like this:

  @orders = current_user.orders.where(created_at: Time.now.beginning_of_month.. Time.now).group_by(&:created_at)

And I'm getting something like this as a result:

    {Sat, 06 Jun 2015 13:06:08 CEST +02:00=>
[#<Order id: 19, total:10], 
[#<Order id: 20, total:12], 
Fri, 05 Jun 2015 15:42:24 CEST +02:00=>
[#<Order id: 19, total:10], 
[#<Order id: 20, total:12]}

@pauloancheta Using your solution and having view like this (HAML)

#subtotal
  - @orders.each do |day,orders|
    .col-md-4
      %h2
        = day.strftime("%Y  %m %d")
        = link_to '', monthly_summary_path(date: day), class: "btn btn-info btn-small glyphicon glyphicon-zoom-in"
      %p= "sum: #{orders.map(&:total).sum}"

When I have two orders in one day i get two separate columns instead of 1 with sum.

Upvotes: 1

Views: 2151

Answers (2)

mu is too short
mu is too short

Reputation: 434745

First of all, created_at is a timestamp not a date so you're not grouping by dates at all, you're grouping by date and time of day. This is why you'll get multiple results for some dates.

Secondly, you can get the database to do all the work by using a GROUP BY on the date and then summing the total within each group:

current_user.orders
            .where(created_at: Time.now.beginning_of_month .. Time.now)
            .group('created_at::date')
            .sum(:total)

That will give you a Hash like this:

{ date_object => sum_for_that_date, ... }

Upvotes: 3

pauloancheta
pauloancheta

Reputation: 359

I tried this with my console and it worked. Hope it would work for you as well. orders.map(&:total).sum

Order.where already returns an array so I think there is no need for a .to_a method.

Upvotes: 1

Related Questions