Model Scopes
Scopes package reusable query constraints on a model. Ormed supports:
- Generated scopes (declared on the model with
@OrmScope) - Inline scopes (registered at runtime on a
ScopeRegistry)
Snippet context
- The examples focus on the scope-related lines and omit full bootstrapping.
- Where setup is required, the snippet calls
bootstrapOrm()to wire generated registrations.
- Generated
- Inline
Define scopes as static methods that accept a Query<$Model> as the first parameter.
Global scopes apply to every query for the model:
(global: true)
static Query<$ScopedUser> activeOnly(Query<$ScopedUser> query) =>
query.whereEquals('active', true);
Local scopes are opt-in and can accept positional or named arguments:
()
static Query<$ScopedUser> withDomain(
Query<$ScopedUser> query,
String domain,
) => query.whereLike('email', '%@$domain');
()
static Query<$ScopedUser> roleIs(
Query<$ScopedUser> query, {
required String role,
}) => query.whereEquals('role', role);
Register generated scopes once during bootstrap:
// bootstrapOrm() wires up generated scopes (and other generated helpers).
final registry = bootstrapOrm();
Use generated query helpers:
// Local scopes compose via generated extensions
final admins = await dataSource.context
.query<$ScopedUser>()
.withDomain('example.com')
.roleIs(role: 'admin')
.get();
Global scopes apply automatically:
// Global scope filters inactive rows automatically
final active = await dataSource.context.query<$ScopedUser>().get();
Disable a specific global scope when needed:
// Opt out of globals when needed
final allRows = await dataSource.context
.query<$ScopedUser>()
.withoutGlobalScope('activeOnly')
.get();
Inline scopes are useful for environment-specific behavior and tests. Register them on a ScopeRegistry (usually via context.scopeRegistry).
Register scopes:
// Register scopes at runtime without touching the model
context.scopeRegistry.addLocalScope<$ScopedUser>(
'byRole',
(query, args) => query.whereEquals('role', args.first),
);
context.scopeRegistry.addGlobalScope<$ScopedUser>(
'activeOnly',
(query) => query.whereEquals('active', true),
);
Apply them via scope('name', args) (and disable globals the same way as generated scopes):
final admins = await context.query<$ScopedUser>().scope('byRole', [
'admin',
]).get();
final allWithInactive = await context
.query<$ScopedUser>()
.withoutGlobalScope('activeOnly')
.get();
Rules & notes
- Static only: scopes must be
staticso both the user model type and generated$Modelquery APIs can reference them consistently. - Global scopes must be argument-free (beyond the initial
Query<T>). - Identifiers default to the method name; override with
@OrmScope(identifier: 'custom')when needed.