ruby 42 lines · 7 steps

Building a weekly signups report in Rails

A plain service object that groups records by week and fills in zeros for weeks with no signups.

Explained by highlit
1class WeeklySignupsReport
2 DEFAULT_WEEKS = 12
3 
4 def initialize(weeks: DEFAULT_WEEKS, source: User.all)
5 @weeks = weeks
6 @source = source
7 end
8 
9 def call
10 labels = week_starts
11 counts = counts_by_week
12 
13 labels.map do |week_start|
14 {
15 week: week_start.strftime("%b %-d"),
16 starts_on: week_start.iso8601,
17 signups: counts.fetch(week_start, 0)
18 }
19 end
20 end
21 
22 private
23 
24 attr_reader :source
25 
26 def counts_by_week
27 source
28 .where(created_at: range)
29 .group("DATE_TRUNC('week', created_at)")
30 .count
31 .transform_keys { |timestamp| timestamp.to_date }
32 end
33 
34 def week_starts
35 (0...@weeks)
36 .map { |offset| range.begin.to_date + offset.weeks }
37 end
38 
39 def range
40 @range ||= @weeks.weeks.ago.beginning_of_week..Time.current.end_of_week
41 end
42end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Injecting the source relation makes the report reusable and easy to test with any scope.
  2. 2Grouping in SQL with DATE_TRUNC pushes aggregation to the database instead of loading every row.
  3. 3Building a complete list of buckets and defaulting missing keys to zero guarantees a gap-free series.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Building a weekly signups report in Rails — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code