Rake Tasks
The engine ships a set of Rake tasks for creating, refreshing, and deleting PostgreSQL materialized views. Tasks log via Rails.logger, ask for confirmation (unless skipped), and enqueue background jobs through the Adapter.
Adapter call (used under the hood):
MatViews::Jobs::Adapter.enqueue(job_class, queue: MatViews.configuration.job_queue, args: [...])The adapter does not guess a backend; it uses whatever you configured (ActiveJob, Sidekiq, Resque).
Available tasks
Create
mat_views:create_by_name[view_name, force, row_count_strategy, --yes]mat_views:create_by_id[mat_view_definition_id, force, row_count_strategy, --yes]mat_views:create_all[force, row_count_strategy, --yes]
force is boolean-ish:
false(default) βCREATE MATERIALIZED VIEW ...(fails if exists)trueβCREATE OR REPLACE MATERIALIZED VIEW ...(drops first if exists)
row_count_strategy can be:
none(default; skips counting)estimated(fast, usesreltuples)exact(usesCOUNT(*))- blank to skip counting (if you pass nothing)
Refresh
mat_views:refresh_by_name[view_name, row_count_strategy, --yes]mat_views:refresh_by_id[mat_view_definition_id, row_count_strategy, --yes]mat_views:refresh_all[row_count_strategy, --yes]
row_count_strategy can be:
none(default; skips counting)estimated(fast, usesreltuples)exact(usesCOUNT(*))- blank to skip counting (if you pass nothing)
Delete
mat_views:delete_by_name[view_name, cascade, row_count_strategy, --yes]mat_views:delete_by_id[mat_view_definition_id, cascade, row_count_strategy, --yes]mat_views:delete_all[cascade, row_count_strategy, --yes]
cascade is boolean-ish:
false(default) βRESTRICT(fails if dependents exist)trueβCASCADE
row_count_strategy can be:
none(default; skips counting)estimated(fast, usesreltuples)exact(usesCOUNT(*))- blank to skip counting (if you pass nothing)
Arguments & env overrides
Tasks accept positional args and optional env overrides:
| Purpose | Positional arg | Env var (override) | Accepted values |
|---|---|---|---|
| Skip confirmation | --yes (3rd arg) | YES=1 | --yes, yes, y, 1 |
| Force create | force | FORCE=true | true/false/1/0/yes/no |
| Row count strategy | row_count_strategy | ROW_COUNT_STRATEGY=... | estimated, exact, (blank) |
| Cascade delete | cascade | CASCADE=true (if implemented in helpers) | true/false/1/0/yes/no |
Boolean-ish parsing accepts:
1,true,yes,y,--yes(case-insensitive). If you pass both arg and env, arg wins.
Confirmation behavior
- Tasks log a context line and prompt:
Proceed? [y/N]: - Input
y/Y/yesβ proceed - Empty line or EOF (
Ctrl+D) β abort withAborted. - To skip the prompt entirely, pass
--yesarg orYES=1.
All log output uses
Rails.logger. In development, ensure your logger is visible (e.g., to STDOUT).
Name resolution & safety
view_namemay be either:- the definition name (unqualified, e.g.,
mv_user_activity), or - a schema-qualified materialized view (e.g.,
public.mv_user_activity).
- the definition name (unqualified, e.g.,
- If you pass a schema-qualified name that physically exists but thereβs no definition with that name, the task raises a helpful error (prevents operating on orphaned MVs silently).
- Definition names must be simple identifiers (no dots). Schema is resolved from the DB
search_pathat runtime by services.
Examples
Shell tip: for Zsh/Bash, quote the task invocation when passing commas.
Create
# Create by name (no force), skip confirm
bin/rake 'mat_views:create_by_name[mv_user_activity,--yes]'
# Create by id with force=true, skip confirm
bin/rake 'mat_views:create_by_id[42,true,--yes]'
# Create all with force=false (default), skip confirm
bin/rake 'mat_views:create_all[,--yes]'
# Using env overrides: YES=1, FORCE=true
YES=1 FORCE=true bin/rake 'mat_views:create_by_name[mv_user_activity]'
Refresh
# Refresh by name with default row_count_strategy (:estimated), skip confirm
bin/rake 'mat_views:refresh_by_name[mv_user_activity,--yes]'
# Refresh by id with exact row count, skip confirm
bin/rake 'mat_views:refresh_by_id[42,exact,--yes]'
# Refresh all with no row count at all (blank arg), skip confirm
bin/rake 'mat_views:refresh_all[,--yes]'
# Using env override for strategy
YES=1 ROW_COUNT_STRATEGY=exact bin/rake 'mat_views:refresh_by_name[mv_user_activity]'
Delete
# Delete by name with cascade=false (default), skip confirm
bin/rake 'mat_views:delete_by_name[mv_user_activity,--yes]'
# Delete by id with cascade=true, skip confirm
bin/rake 'mat_views:delete_by_id[42,true,--yes]'
# Delete all with cascade=false (default), skip confirm
bin/rake 'mat_views:delete_all[,--yes]'
# Using env override for cascade
YES=1 CASCADE=true bin/rake 'mat_views:delete_by_name[mv_user_activity]'
Schema-qualified name
# Will check for a corresponding definition; if none exists but the MV exists β raises
YES=1 bin/rake 'mat_views:refresh_by_name[public.mv_user_activity]'
What gets enqueued
Each task enqueues one job per definition:
- Create β
MatViews::CreateViewJobwith args[mat_view_definition_id, force] - Refresh β
MatViews::RefreshViewJobwith args[mat_view_definition_id, row_count_strategy] - Delete β
MatViews::DeleteViewJobwith args[mat_view_definition_id, cascade]
Queue is taken from MatViews.configuration.job_queue (default :default unless you changed it).
Output & logging
-
Tasks use
Rails.logger.info(noputs), e.g.:[mat_views] Enqueued RefreshViewJob for definition #42 (mv_user_activity), row_count_strategy=estimated -
If no definitions are found (e.g.,
*_all), they log:[mat_views] No mat view definitions found.
Error cases you may see
view_name is required- missing/blank name.No MatViews::MatViewDefinition found for "foo"- unknown definition.Materialized view public.foo exists, but no MatViews::MatViewDefinition record was found for name="foo"- schema-qualified MV exists but no definition; intentional guardrail.mat_view_definition_id is required- missing/blank id.- Abort on confirm - pressing Enter or EOF at the prompt without
--yes/YES=1.
Under the hood
The tasks are implemented in lib/tasks/mat_views_tasks.rake and rely on MatViews::Tasks::Helpers:
confirm!(message, skip:)- logs and prompts (or skips with--yes/YES=1)find_definition_by_name!- resolves names (definition vs schema-qualified MV)parse_force?,parse_row_count_strategy,parse_cascade?- boolean/enum parsingenqueue_create,enqueue_refresh,enqueue_delete- adapter calls
Troubleshooting
- No logs appear: ensure your Rails logger outputs to STDOUT/stderr in your environment.
- Command parsing in shell: quote the whole task invocation when passing commas or blank args.
- Background jobs donβt run: verify your queue backend is configured and running; in development, consider
config.active_job.queue_adapter = :inlinefor immediate execution (jobs still record run rows). - Concurrent refresh fails: ensure your MV has a unique index that covers all rows.