Skip to main content

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.

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();

Rules & notes

  • Static only: scopes must be static so both the user model type and generated $Model query 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.