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, --yes]
mat_views:create_by_id[definition_id, force, --yes]
mat_views:create_all[force, --yes]
Refresh
mat_views:refresh_by_name[view_name, row_count_strategy, --yes]
mat_views:refresh_by_id[definition_id, row_count_strategy, --yes]
mat_views:refresh_all[row_count_strategy, --yes]
row_count_strategy
can be:
estimated
(default; fast, usesreltuples
)exact
(usesCOUNT(*)
)- blank to skip counting (if you pass nothing)
Delete
mat_views:delete_by_name[view_name, cascade, --yes]
mat_views:delete_by_id[definition_id, cascade, --yes]
mat_views:delete_all[cascade, --yes]
cascade
is boolean-ish:
false
(default) βRESTRICT
(fails if dependents exist)true
βCASCADE
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
--yes
arg orYES=1
.
All log output uses
Rails.logger
. In development, ensure your logger is visible (e.g., to STDOUT).
Name resolution & safety
view_name
may 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_path
at 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::CreateViewJob
with args[definition_id, force]
- Refresh β
MatViews::RefreshViewJob
with args[definition_id, row_count_strategy]
- Delete β
MatViews::DeleteViewJob
with args[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.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 = :inline
for immediate execution (jobs still record run rows). - Concurrent refresh fails: ensure your MV has a unique index that covers all rows.