AggtiveRecord

NOTE: This gem is not really functional yet. I just like to commit things good and early.

An attempt to formalize the description of common aggregations across timestamped records.

I wrote this gem because I found myself writing, over and over again, these kind of ActiveRecord scope:

To get the number of messages sent in the last two weeks:

Message.where('sent_at >= ?', 14.days.ago).count 

To get the rate of messages per week:

Message.count * SECONDS_PER_WEEK / (Message.order('sent_at ASC').last - Message.order('sent_at ASC').first) 

Or how about the rate per week for messages sent in the past month (because it's interesting to know if someone has sent more messages recently)?

Message.where('sent_at >= ?', 1.month.ago) * SECONDS_PER_WEEK / (Time.now - 1.month.ago)

This is easily enough to formalize in one application, but I figured maybe it'd be useful to have a convention for every app that I ever do that tries to aggregate records by time.

Let's make some meta-magic

So for the first example, for counting messages in the past two weeks, something like:

Message.count_past_14_days

OK, admittedly that's not much nicer than the standard ActiveRecord chain. But for the second example, it could be simplified to this:

Message.rate_per_week

And for the third example:

Message.rate_during_past_month_per_week

AggtiveRecord is an extension that can be applied to ActiveRecord. Maybe you'll find it useful, maybe not.

This gem takes some inspiration from the highly useful groupdate.

Message.count_during_past_year_per_day


Message.group_by_day.where('sent_at >= ?' 1.year.ago)

Interaction with :has_many

Obviously, this is just speculative

@person.rate_of_messages_per_day

@person.messages_count_during_past_year_per_day

@person.rate_word_count_from_messages_during_past_year_per_day

@person.count_messages_during_past_year_per_day
@person.messages_count_during_past_year_per_day

Message.count_during_past_year

A standard verbose call:

@person.sum_word_count_from_messages_during_past_year_per_day

Under the hood query:

@person.egg.sum(:word_count).
  from(:messages).
  during(:past_year).
  per(:day)

Which translates to this in ActiveRecord:

@person.messages.
  where('sent_at >= ?', 1.year.ago).
  group('DAY(sent_at)').
  sum(:word_count)

Result types

Scalars and arrays