Tim K.
Tim K.

Reputation: 170

Donations over past 24 months with keys and sums

Having pulled donations from the past two years, I'm trying to derive the sum of those donations per month, storing the keys (each month) and the values (the sum of donations for each month) in an array of hashes. I would like the keys to be numbers 1 to 24 (1 being two years ago and 24 being this month) and if there are no donations for a given month, the value would be zero for that month. How would I do this as an array of hashes in Ruby/Rails?

This is my variable with the donations already in it.

donations = Gift.where(:date => (Date.today - 2.years)..Date.today)

Upvotes: 1

Views: 77

Answers (3)

Tim K.
Tim K.

Reputation: 170

I found a good solution that covered all the bases--@user1185563's solution didn't bring in months without donations and @Tilo's called the database 24 times, but I very much appreciated the ideas! I'm sure this could be done more efficiently, but I created the hash with 24 elements (key: beginning of each month, value: 0) and then iterated through the donations and added their amounts to the hash in the appropriate position.

def monthly_hash
  monthly_hash = {}
  date = 2.years.ago
  i = 0
  while date < Time.now do
    monthly_hash["#{date.beginning_of_month}"] = 0
    date += 1.month
    i += 1
  end
  return monthly_hash
end

@monthly_hash = monthly_hash
@donations.each do |donation|
  @monthly_hash["#{donation.date.beginning_of_month}"] += donation.amount
end

Upvotes: 0

user1185563
user1185563

Reputation: 33

First, we need a function to find the difference in months from the current time.

def month_diff(date)
  (Date.current.year * 12 + Date.current.month) - (date.year * 12 + date.month)
end

Then we iterate through @donation, assuming that :amount is used to store the value of each donation:

q = {}
@donations.each do |donation|
  date = month_diff(donation.date)
  if q[date].nil?
    q[date] = donation.amount
  else
    q[date] += donation.amount
  end
end

Upvotes: 0

Tilo
Tilo

Reputation: 33732

the following gives you a hash, with keys '2013/09" , etc...

 monthly_donations = {}
 date = Time.now
 while date > 2.years.ago do 

   range = date.beginning_of_month..date.end_of_month
   monthly_donations[ "{#date.year}/#{date.month}" ] = Giftl.sum(:column, :conditions => {created_at >= range})

   date -= 30.days
 end

To select the records in that time-span, this should be enough:

 donations = Gift.where("date >= #{2.years.ago}") 

you can also do this:

 donations = Gift.where("date >= :start_date AND date <= :end_date",
                         {start_date: 2.years.ago, end_date: Time.now} )

See also: 2.2.1 "Placeholder Conditions" http://guides.rubyonrails.org/active_record_querying.html

To sum-up a column in the database record, you can then do this:

 sum = Gift.sum(:column , :conditions => {created_at >= 2.years.ago})

Upvotes: 1

Related Questions