Query objects: materialized
This course covers query objects and PostgreSQL materialized views in a Rails application. It starts with moving query logic out of fat models into plain Ruby classes that expose self.call and return a Data.define Result. It then explains materialized views as precomputed results stored on disk, how to create them with raw SQL or the scenic gem, and how to read them through read-only models. The last lessons cover refresh strategies, locking, staleness monitoring, testing and a production checklist.
What you'll learn
- ✓How to extract query logic from fat models into query objects
- ✓The self.call and Data.define Result contract for read-only queries
- ✓When a materialized view fits and when a direct query is enough
- ✓Creating materialized views with raw SQL migrations or the scenic gem
- ✓Plain and concurrent refreshes, scheduling with Solid Queue and debouncing
- ✓Testing query objects, view SQL and refresh jobs, plus monitoring in production
What are query objects?
You open app/models/user.rb on a Monday morning. It's 847 lines long, with 34 scopes, 12 class methods that build queries and a self.dashboard_stats method of 60 lines of raw SQL stitched together with string interpolation. Three developers have added # TODO: refactor this, and nobody has.
Read the full lesson free →Curriculum
7 lessonsWhat are query objects?
Explains why fat models become bottlenecks and how read-only query objects with a fixed contract replace them.
Building your first query object
Builds a query object with self.call, a Data.define Result, keyword arguments, conditional filters and lazy relations.
Materialized views: precomputed queries
Compares regular and materialized views and explains the trade-off between read speed and data freshness.
Creating materialized views in Rails
Creates materialized views with raw SQL or scenic, backs them with read-only models and sets the schema format.
Query objects + materialized views
Combines both patterns in an admin page, using a decision matrix and keeping data sources hidden from callers.
Refresh strategies & cache invalidation
Covers plain and concurrent refresh locks, Solid Queue schedules, debouncing, staleness tracking and failure handling.
Testing & production patterns
Tests query objects, view SQL and refresh jobs, then checks query plans, refresh duration and a production checklist.