Closed yyong37 closed 2 years ago
Why was this closed? Did you find a solution?
Isar links doesn't work with freezed right now because it must be initialised with a non const/literal. Freezed does not allow this.
the reason as you say. it conflict.
It should work with the latest Isar version. I didn't have time to write tests yet however...
@freezed
@Collection()
class TeacherModel with _$TeacherModel {
const factory TeacherModel({
int? id,
required String subject,
}) = MyTeacherModel;
}
@freezed
@Collection()
class StudentModel with _$StudentModel {
const StudentModel._();
// try 1. can not make gen links
// get teachers => IsarLink<TeacherModel>();
const factory StudentModel({
int? id,
required String name,
// 2 try 2. can not use non-constant value for required field
// @Default(IsarLink<TeacherModel>()) IsarLink<TeacherModel> teachers,
}) = MyStudentModel;
}
@leisim as this sample code, init Isarlink and gen it I have problem can not solved. cuz freezed can not @Default() with func exec
maybe have a link annotation ?
Hi! Kinda found a solution. It comes with a cost of losing const constructors and having to have common properties (if you don't use unions, it is not a disadvantage), but works:
import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:isar/isar.dart';
import 'package:path_provider/path_provider.dart';
part 'test.freezed.dart';
part 'test.g.dart';
@freezed
@Collection()
class Teacher with _$Teacher {
const factory Teacher({
int? id,
required String name,
}) = _Teacher;
}
@freezed
@Collection()
class Student with _$Student {
Student._();
factory Student({
int? id,
required String name,
}) = _Student;
final teachers = IsarLinks<Teacher>();
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final isar = await Isar.open(
name: 'test',
schemas: [TeacherSchema, StudentSchema],
directory: (await getApplicationDocumentsDirectory()).path,
);
const teacher1 = Teacher(name: 'Ann');
const teacher2 = Teacher(name: 'John');
final student = Student(name: 'Joe');
student.teachers.addAll([teacher1, teacher2]);
await isar.writeTxn((isar) async {
await isar.teachers.putAll([teacher1, teacher2]);
await isar.students.put(student);
await student.teachers.save();
});
final dbStudent = (await isar.students.where().findAll())[0];
await dbStudent.teachers.load();
print(dbStudent.teachers);
}
The output is {Teacher(id: 4, name: Ann), Teacher(id: 3, name: John)}
@leisim Isar.autoIncrement is a final property that has a const value assigned to it. It would be better to make it const to be able to use it in freezed's @Default() annotation instead of always making id nullable.
Isar does not support freezed.
Isar does not support freezed.
will it support it in the future? many flutter devs depend on freezed
If you distinguish between the database models (Isar collections) in the data layer and business objects (freezed, ...) in the domain layer of your app and map them, Isar can also be used in an app with frezzed models in business and presentation layer.
Any update or further thoughts on this? freezed is really big.
I think I agree with what @jannikrh is saying.
This seems to be a difference between what should be in a DTO and what should happen in the domain model.
Not many clear examples out there (also writing this to validate my own thinking).
But from what understand, a DTO should be just the info you require to be persisted. A domain model could also contain information that is only relevant when running the app. A controller / use case / viewmodel then adds whatever is needed for display.
A (possibly oversimplified) example would be a timer.
Start / End recording would be DTOs.
In the domain model, you'd probably also want to insert the current time, and a function to determine the amount of time passed.
In the use case/ controller / viewmodel you'd stick something to format the time elapsed and stuff like whether or not to show a start/stop button, animate time elapsing, etc.
Did I get it right?
In that case, I do understand the confusion. For start/stop unions are very useful, and thus they become DTO as well as domain model quite often. (Certainly in getting started type stuff on internet).
You could argue that not supporting freezed helps clean architecture, at the cost of more structure for simpler applications.
@simc @neiljaywarner @FrankDomburg
for time travelers in the future! I add some code that works for me! :)
@freezed
@Collection(ignore: {'copyWith'})
class UserData with _$UserData {
///Don't Forget below line
const UserData._();
const factory UserData({
final LoginResponseData? loginResponseData,
}) = _UserData;
/// add this
Id get id => Isar.autoIncrement;
factory UserData.fromJson(Map<String, dynamic> json) => _$UserDataFromJson(json);
}
What about unions (sealed class) support?
Hi! Kinda found a solution. It comes with a cost of losing const constructors and having to have common properties (if you don't use unions, it is not a disadvantage), but works:
import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:isar/isar.dart'; import 'package:path_provider/path_provider.dart'; part 'test.freezed.dart'; part 'test.g.dart'; @freezed @Collection() class Teacher with _$Teacher { const factory Teacher({ int? id, required String name, }) = _Teacher; } @freezed @Collection() class Student with _$Student { Student._(); factory Student({ int? id, required String name, }) = _Student; final teachers = IsarLinks<Teacher>(); } void main() async { WidgetsFlutterBinding.ensureInitialized(); final isar = await Isar.open( name: 'test', schemas: [TeacherSchema, StudentSchema], directory: (await getApplicationDocumentsDirectory()).path, ); const teacher1 = Teacher(name: 'Ann'); const teacher2 = Teacher(name: 'John'); final student = Student(name: 'Joe'); student.teachers.addAll([teacher1, teacher2]); await isar.writeTxn((isar) async { await isar.teachers.putAll([teacher1, teacher2]); await isar.students.put(student); await student.teachers.save(); }); final dbStudent = (await isar.students.where().findAll())[0]; await dbStudent.teachers.load(); print(dbStudent.teachers); }
The output is
{Teacher(id: 4, name: Ann), Teacher(id: 3, name: John)}
Since the Linked property teachers
is not in the constructor, how do you handle fromJson
and toJson
methods created automatically by freezed using the JsonSerializable package?
if allowed, please add a test. thx 🌺
https://github.com/isar/isar/blob/main/packages/isar_test/lib/freezed_model.dart