Is there a way to modify an Insertable<> before insert/update in a DAO?
I need to do that for 3 things:
updatedAt when a row is modified.I currently have these methods inside my DAO, but I would like to change them to use Insertable<Task>:
Future insertTask(TasksCompanion task) {
var gid = Uuid().v4();
var taskCopy = task.copyWith(gid: Value(gid));
return into(tasks).insert(taskCopy);
}
Future updateTask(Task task) {
var taskCopy = task.copyWith(updatedAt: DateTime.now());
update(tasks).replace(taskCopy);
}
Future deleteTask(Task task) {
var taskCopy = task.copyWith(deletedAt: DateTime.now());
return update(tasks).replace(taskCopy);
}
I tried using Iterable<Task> but it doesn't seem to be any methods I can use to modify the data about to be inserted.
Would you happen to know how to use Insertable<Task> instead?
Also, would you consider this to be a correct way to set up the code to auto-generate the primary key?
I do have to use uuid, but is updateTask the right place to set that up?
Thanks.
You can call Insertable.createCompanion to turn an Insertable into an appropriate companion, on which you can then call the copy methods.
The method has a boolean parameter, which controls whether null values from the Task class should be mapped to Value.absent or Value(null). We typically set it it to true on inserts (map null to absent) and false on updates (map null to null).
I haven't tried it, but the code could look similar to
Future insertTask(Insertable<Task> task) {
var gid = Uuid().v4();
var companion = task.createCompanion(true) as TasksCompanion;
var taskCopy = companion.copyWith(gid: Value(gid));
return into(tasks).insert(taskCopy);
}
Future updateTask(Insertable<Task> task) {
var companion = task.createCompanion(false) as TasksCompanion;
var taskCopy = companion.copyWith(updatedAt: DateTime.now());
update(tasks).replace(taskCopy);
}
Future deleteTask(Insertable<Task> task) {
var companion = task.createCompanion(false) as TasksCompanion;
var taskCopy = companion.copyWith(deletedAt: DateTime.now());
return update(tasks).replace(taskCopy);
}
Also, would you consider this to be a correct way to set up the code to auto-generate the primary key?
If you need to generate keys in Dart, doing that in an insert method seems appropriate, yet.
Hello @simolus3,
Given that createCompanion() isn't available anymore, are there any alternatives you recommend to solve the issue?
Would you consider this a good approach?:
myInsertable.toColumns()btw. Thanks for the hard work on this library, it's really good.
I think that approach should work, yes. You can use a RawValuesInsertable for step 3.
Future insertTask(Insertable<Task> task) {
var gid = Uuid().v4();
var columns = task.toColumns(true);
columns['gid'] = Variable(gid.toString());
return into(tasks).insert(RawValuesInsertable(columns));
}
The map returned by toColumns already has the type converters applied. This means that you'd now have to apply type converters manually when changing values (like with gid.toString()).
If you need it, I can look into ways moor_generator could make this easier. For instance, we could generate a method on generated data classes to turn them into a generated companion. With the introduction of RawValuesInsertable that was needed for upserts, we can't transform a arbitrary Insertable<D> to a generated companion anymore. You could then change your methods to take a TasksCompanion instead of an Insertable<Task>. The places that called your methods with a data class would then have to call the generated method.
we could generate a method on generated data classes to turn them into a generated companion
I think that would be really helpful. Our sync code has a bunch of mappers that convert remote models to and from local data classes. All our local insert/update methods take companions, so currently we use something like:
Foo localFoo = remoteFoo.toLocalFoo();
FooCompanion companion = localFoo.createCompanion(false);
await insertFoo(companion, mode: InsertMode.insertOrReplace);
Thanks for the feedback! The createCompanion method will be back in moor 3.1, but only for generated data classes.
Most helpful comment
I think that approach should work, yes. You can use a
RawValuesInsertablefor step 3.The map returned by
toColumnsalready has the type converters applied. This means that you'd now have to apply type converters manually when changing values (like withgid.toString()).If you need it, I can look into ways
moor_generatorcould make this easier. For instance, we could generate a method on generated data classes to turn them into a generated companion. With the introduction ofRawValuesInsertablethat was needed for upserts, we can't transform a arbitraryInsertable<D>to a generated companion anymore. You could then change your methods to take aTasksCompanioninstead of anInsertable<Task>. The places that called your methods with a data class would then have to call the generated method.