load method

Future<OrmMigrationRecord> load(
  1. String relation, [
  2. PredicateCallback<OrmEntity>? constraint
])
inherited

Lazily loads a relation on this model instance.

Similar to Laravel's $model->load('relation').

Supports nested relation paths using dot notation:

await post.load('comments.author'); // Load comments, then their authors

Example:

final post = await Post.query().first();
await post.load('author'); // Lazy load author
print(post.author?.name);

With constraint (applies to the final relation in nested paths):

await post.load('comments', (q) => q.where('approved', true));

Throws LazyLoadingViolationException if ModelRelations.preventsLazyLoading is true.

Implementation

Future<TModel> load(
  String relation, [
  PredicateCallback<OrmEntity>? constraint,
]) async {
  if (ModelRelations.preventsLazyLoading) {
    throw LazyLoadingViolationException(runtimeType, relation);
  }

  final def = expectDefinition();
  final resolver = _resolveResolverFor(def);
  final context = _requireQueryContext(resolver);

  // Check if this is a nested relation path
  if (relation.contains('.')) {
    await _loadNestedRelation(relation, constraint, def, context);
    return _self();
  }

  // Find the relation definition
  final relationDef = def.relations.cast<RelationDefinition?>().firstWhere(
    (r) => r?.name == relation,
    orElse: () => null,
  );

  if (relationDef == null) {
    throw ArgumentError('Relation "$relation" not found on ${def.modelName}');
  }

  // Convert constraint callback to QueryPredicate using RelationResolver
  final relationResolver = RelationResolver(context);
  final predicate = relationResolver.predicateFor(relationDef, constraint);

  // Create a synthetic QueryRow from current model
  final row = QueryRow<TModel>(
    model: _self(),
    row: def.toMap(_self(), registry: context.codecRegistry),
  );

  // Load the relation using RelationLoader
  final loader = RelationLoader(context);
  final relationLoad = RelationLoad(
    relation: relationDef,
    predicate: predicate,
  );

  await loader.attach(def, [row], [relationLoad]);

  // The relation should now be in row.relations and synced to model cache
  return _self();
}