
When creating analytical tables or graphs for your client, we normally use active record and SQL queries in order to get the results that we want. There’s no harm done when you want absolute control over the what data is being shown. However, it could sometimes cause some complications whenever you want to create more complicated data.
Groupdate gem
If that’s the case, it’s great to know of the GroupDate gem. With this gem, you’re able to abstract the complicated queries, and focus on the results of the data. If you dive in deeper with this gem, you’ll appreciate the things you could do on top of it.
Installation
You can install it using bundle add groupdate
and it will give you the latest version of the gem.
Application Example
We’re creating a sample e-commerce application, where the graphs are a must in order for the user to visualize performance of the app.
Let’s show the models for this sample app.
1. User
Purpose: Customer/user management
Attributes: name, email, registered_at
Key Relationships:
has_many :orders, dependent: :destroy
has_many :product_views, dependent: :destroy
has_many :order_items, through: :orders
2. Category
Purpose: Product categorisation for organisation and analytics
Attributes: name
Key Relationships:
has_many :products, dependent: :destroy
3. Product
Purpose: Product catalog management
Attributes: name, price, category_id
Key Relationships:
belongs_to :category
has_many :order_items, dependent: :destroy
has_many :product_views, dependent: :destroy
has_many :orders, through: :order_items
4. Order
Purpose: Transaction and sales tracking
Attributes: user_id, total_amount, status, ordered_at
Key Relationships:
belongs_to :user
has_many :order_items, dependent: :destroy
has_many :products, through: :order_items
Scopes: completed, pending, cancelled for status-based analytics
5. OrderItem
Purpose: Shopping cart line items and detailed purchase tracking
Attributes: order_id, product_id, quantity, unit_price
Key Relationships:
belongs_to :order
belongs_to :product
Methods: total_price calculation
Validations: Positive quantity and unit_price
Analytics Role: Enables detailed product sales analysis, average order value calculations, and quantity-based insights
Sample outputs
These are the sample outputs I could think of in this application.
(1). Daily Sales (last 30 days)
Order.completed.where(ordered_at: 30.days.ago..Date.current).group_by_day(:ordered_at).sum(:total_amount)
{Wed, 09 Jul 2025 => 0.876169e4,
Thu, 10 Jul 2025 => 0.943317e4,
Fri, 11 Jul 2025 => 0.1049019e5,
...
}
Let's make this more understandable by adding `.map {|k, v| [k, v.round(0)] }.to_h`
{Wed, 09 Jul 2025 => 8762,
Thu, 10 Jul 2025 => 9433,
Fri, 11 Jul 2025 => 10490,
...
}
(2). Orders by Day of Week (30 Days)
Order.completed.where(ordered_at: 30.days.ago..Date.current).group_by_day_of_week(:ordered_at).count
# 0 is Sunday
{0 => 40, 1 => 45, 2 => 48, 3 => 53, 4 => 43, 5 => 30, 6 => 38}
(3). Monthly User Registrations (Year 2025)
User.where(registered_at: Date.current.beginning_of_year..Date.current.end_of_year).group_by_month(:registered_at).count
{Wed, 01 Jan 2025 => 23,
Sat, 01 Feb 2025 => 23,
Sat, 01 Mar 2025 => 23,
Tue, 01 Apr 2025 => 18,
Thu, 01 May 2025 => 35,
Sun, 01 Jun 2025 => 40,
Tue, 01 Jul 2025 => 28,
Fri, 01 Aug 2025 => 8}
(4). Orders by Hour of Day (All time)
Order.completed.group_by_hour_of_day(:ordered_at).count
{0 => 72,
1 => 53,
2 => 55,
3 => 54,
4 => 54,
5 => 47,
6 => 66,
7 => 45,
8 => 55,
9 => 46,
10 => 59,
11 => 36,
12 => 58,
13 => 53,
14 => 40,
15 => 57,
16 => 51,
17 => 54,
18 => 42,
19 => 53,
20 => 46,
21 => 53,
22 => 52,
23 => 46}
(5). Weekly Conversion Rate
views_by_week = ProductView.where(viewed_at: 8.weeks.ago..Time.current)
.group_by_week(:viewed_at)
.count
orders_by_week = Order.completed
.where(ordered_at: 8.weeks.ago..Time.current)
.group_by_week(:ordered_at)
.count
@conversion_rate_by_week = {}
views_by_week.each do |week, views|
orders = orders_by_week[week] || 0
@conversion_rate_by_week[week] = views > 0 ? (orders.to_f / views * 100).round(2) : 0
end
{Sun, 08 Jun 2025 => 8.57,
Sun, 15 Jun 2025 => 9.07,
Sun, 22 Jun 2025 => 8.57,
Sun, 29 Jun 2025 => 7.14,
Sun, 06 Jul 2025 => 9.11,
Sun, 13 Jul 2025 => 10.17,
Sun, 20 Jul 2025 => 8.57,
Sun, 27 Jul 2025 => 8.92,
Sun, 03 Aug 2025 => 8.24}
Summary
The Groupdate gem simplifies complex analytics by abstracting complicated SQL queries into intuitive ActiveRecord methods like group_by_day, group_by_week, and group_by_month, allowing developers to focus on data results rather than query complexity. It’s particularly powerful for e-commerce analytics dashboards where you need to track temporal patterns like daily sales trends, user registration growth, hourly ordering behavior, and conversion rates across different time periods without writing raw SQL.
With the examples shown above showing its ease of use. We can definitely make use of this gem to simplify our analytics.
What other examples could you think of?
Ps. if you have any questions
Ask here