I'm building an app where a Document
has a DocumentTemplate
which belongs to a DocumentFamily
.
I'm working on the basic CRUD operations for the app and I need a watchDocumentTemplateById
method where I get a stream of a DocumentTemplate
but I also need to watch its DocumentFamily
.
The problem is that I have no idea how to nest the two streams so that when a DocumentFamily
gets updated, the DocumentTemplate
will have the updated DocumentFamily
.
I would really appreciate if someone could show me the right way to do it. I'm using Flutter with ObjectBox as my local database.
Here is the method watchDocumentTemplateById
I started implementing (unfinished) :
@override
Stream<Either<DocumentTemplateFailure, DocumentTemplate>>
watchDocumentTemplateById(UniqueId templateId) {
return _box
.query(DocumentTemplateEntity_.id.equals(templateId.getOrCrash()))
.watch(triggerImmediately: true)
.map((query) {
final templateEntity = query.findFirst();
if (null != templateEntity) {
final familyOrFailureStream =
_documentFamilyRepository.watchDocumentFamilyById(
UniqueId.fromUniqueString(templateEntity.familyId));
familyOrFailureStream.listen((familyOrFailure) {
return familyOrFailure.fold(
(failure) =>
DocumentTemplateFailure.familyFailure(familyFailure: failure),
(family) => templateEntity.toDomain(family: family),
);
});
}
return left(const DocumentTemplateFailure.notFound());
});
}
And the classes mentioned above (DocumentTemplate, DocumentTemplateEntity, DocumentFamily and DocumentFamilyEntity) :
DocumentTemplate :
@freezed
class DocumentTemplate with _$DocumentTemplate {
factory DocumentTemplate({
required UniqueId id,
required DocumentTemplateTitle title,
required double leftMargin,
required double topMargin,
required double rightMargin,
required double bottomMargin,
required DocumentFamily family,
}) = _DocumentTemplate;
}
DocumentTemplateEntity :
@Entity()
class DocumentTemplateEntity {
@Id()
int obid = 0;
@Unique()
String id;
String title;
double leftMargin;
double topMargin;
double rightMargin;
double bottomMargin;
String familyId;
DocumentTemplateEntity({
required this.id,
required this.title,
required this.leftMargin,
required this.topMargin,
required this.rightMargin,
required this.bottomMargin,
required this.familyId,
});
DocumentTemplate toDomain({
required DocumentFamily family,
}) =>
DocumentTemplate(
id: UniqueId.fromUniqueString(id),
title: DocumentTemplateTitle(title),
leftMargin: leftMargin,
topMargin: topMargin,
rightMargin: rightMargin,
bottomMargin: bottomMargin,
family: family,
);
factory DocumentTemplateEntity.fromDomain(DocumentTemplate template) =>
DocumentTemplateEntity(
id: template.id.getOrCrash(),
title: template.title.getOrCrash(),
leftMargin: template.leftMargin,
topMargin: template.topMargin,
rightMargin: template.rightMargin,
bottomMargin: template.bottomMargin,
familyId: template.family.id.getOrCrash(),
);
}
DocumentFamily :
@freezed
class DocumentFamily with _$DocumentFamily {
factory DocumentFamily({
required UniqueId id,
required int position,
required String name,
}) = _DocumentFamily;
}
DocumentFamilyEntity :
@Entity()
class DocumentFamilyEntity {
@Id()
int obid = 0;
@Unique()
String id;
String name;
int position;
DocumentFamilyEntity({
required this.id,
required this.name,
required this.position,
});
DocumentFamily toDomain() => DocumentFamily(
id: UniqueId.fromUniqueString(id),
name: name,
position: position,
);
factory DocumentFamilyEntity.fromDomain(DocumentFamily family) =>
DocumentFamilyEntity(
id: family.id.getOrCrash(),
name: family.name,
position: family.position,
);
}
Thanks in advance !
EDIT :
I tried to solve it by myself and found the switchMap
method, which seems to combine two streams into one but I'm not entirely sure if it will work here's the updated watchDocumentTemplateById
method :
ref.: How do I nest Streams in Dart (map Streams to Stream events)?
@override
Stream<Either<DocumentTemplateFailure, DocumentTemplate>>
watchDocumentTemplateById(UniqueId templateId) {
return _box
.query(DocumentTemplateEntity_.id.equals(templateId.getOrCrash()))
.watch(triggerImmediately: true)
.switchMap((query) {
final templateEntity = query.findFirst();
// if(null == templateEntity) return ??? DocumentTemplateFailure.notFound();
final familyId = UniqueId.fromUniqueString(templateEntity!.familyId);
return _documentFamilyRepository.watchDocumentFamilyById(familyId).map(
(failureOrFamily) => failureOrFamily.fold(
(failure) => left(
DocumentTemplateFailure.familyFailure(familyFailure: failure),
),
(family) => right(
templateEntity.toDomain(family: family),
),
),
);
});
}