createQuietlyRelation<TRelated extends Model<TRelated> > method
Creates a related model without firing model events.
Same as createRelation but bypasses model event dispatching.
No creating/created/saving/saved events are fired during insertion.
The attributes parameter accepts:
- A tracked model instance (
TRelated). - An
InsertDtoorUpdateDtoinstance. - A
Map<String, Object?>containing field/column values.
Example:
final author = await Author.query().find(1);
final post = await author.createQuietlyRelation<Post>('posts', {
'title': 'New Post',
'published_at': DateTime.now(),
});
// Using a DTO:
final post2 = await author.createQuietlyRelation<Post>('posts',
PostInsertDto(title: 'DTO Post', publishedAt: DateTime.now()),
);
Implementation
Future<TRelated> createQuietlyRelation<TRelated extends Model<TRelated>>(
String relationName,
Object attributes,
) async {
final def = expectDefinition();
final resolver = _resolveResolverFor(def);
final relationDef = def.relations.cast<RelationDefinition?>().firstWhere(
(r) => r?.name == relationName,
orElse: () => null,
);
if (relationDef == null) {
throw ArgumentError(
'Relation "$relationName" not found on ${def.modelName}',
);
}
if (relationDef.kind != RelationKind.hasOne &&
relationDef.kind != RelationKind.hasMany) {
throw ArgumentError(
'createQuietlyRelation() can only be used with hasOne or hasMany relations. '
'Relation "$relationName" is ${relationDef.kind}',
);
}
// Get this model's local key value
final localKey = relationDef.localKey ?? 'id';
final localKeyValue = _getAttributeValue(localKey, def);
if (localKeyValue == null) {
throw StateError(
'Model ${def.modelName} local key "$localKey" value is null',
);
}
// Add foreign key to attributes
final foreignKey = relationDef.foreignKey;
final context = _requireQueryContext(resolver);
final relatedDef =
resolver.registry.expectByName(relationDef.targetModel)
as ModelDefinition<TRelated>;
final fkField = relatedDef.fields.firstWhere(
(f) => f.columnName == foreignKey || f.name == foreignKey,
);
// Normalize the input to a map using MutationInputHelper
final helper = MutationInputHelper<TRelated>(
definition: relatedDef,
codecs: context.codecRegistry,
);
final normalizedMap = helper.insertInputToMap(
attributes,
applySentinelFiltering: attributes is TRelated,
);
final attributesWithFk = {
...normalizedMap,
fkField.columnName: localKeyValue,
};
// Create the related model using query with events suppressed
final relatedQuery = Query<TRelated>(
definition: relatedDef,
context: context,
);
final results = await relatedQuery.withoutEvents().insertManyInputs([
attributesWithFk,
]);
final created = results.first;
// Update relation cache
if (relationDef.kind == RelationKind.hasOne) {
_asRelations.setRelation(relationName, created);
} else {
final existing = _asRelations.getRelation<List<TRelated>>(relationName);
if (existing != null) {
_asRelations.setRelation(relationName, [...existing, created]);
} else {
_asRelations.setRelation(relationName, [created]);
}
}
return created;
}