Write correct mapping code for custom objects

This commit is contained in:
Simon Binder 2019-07-18 12:53:26 +02:00
parent bf4d16add6
commit ff93af231c
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
3 changed files with 58 additions and 7 deletions

View File

@ -109,6 +109,40 @@ class ColumnBuilder<
/// Uses a custom [converter] to store custom Dart objects in a single column
/// and automatically mapping them from and to sql.
///
/// An example might look like this:
/// ```dart
/// // this is the custom object with we want to store in a column. It
/// // can be as complex as you want it to be
/// class MyCustomObject {
/// final String data;
/// MyCustomObject(this.data);
/// }
///
/// class CustomConverter extends TypeConverter<MyCustomObject, String> {
/// // this class is responsible for turning a custom object into a string.
/// // this is easy here, but more complex objects could be serialized using
/// // json or any other method of your choice.
/// const CustomConverter();
/// @override
/// MyCustomObject mapToDart(String fromDb) {
/// return fromDb == null ? null : MyCustomObject(fromDb);
/// }
///
/// @override
/// String mapToSql(MyCustomObject value) {
/// return value?.data;
/// }
/// }
///
/// ```
///
/// In that case, you could have a table with this column
/// ```dart
/// TextColumn get custom => text().map(const CustomConverter())();
/// ```
/// The generated row class will then use a `MyFancyClass` instead of a
/// `String`, which would usually be used for [Table.text] columns.
Builder map<T>(TypeConverter<T, ResultDartType> converter) => null;
/// Turns this column builder into a column. This method won't actually be

View File

@ -853,16 +853,18 @@ class TableWithoutPKData extends DataClass
final effectivePrefix = prefix ?? '';
final intType = db.typeSystem.forDartType<int>();
final doubleType = db.typeSystem.forDartType<double>();
final myCustomObjectType = db.typeSystem.forDartType<MyCustomObject>();
final stringType = db.typeSystem.forDartType<String>();
final customConverter = const CustomConverter();
return TableWithoutPKData(
notReallyAnId: intType
.mapFromDatabaseResponse(data['${effectivePrefix}not_really_an_id']),
someFloat: doubleType
.mapFromDatabaseResponse(data['${effectivePrefix}some_float']),
custom: myCustomObjectType
.mapFromDatabaseResponse(data['${effectivePrefix}custom']),
custom: customConverter.mapToDart(
stringType.mapFromDatabaseResponse(data['${effectivePrefix}custom'])),
);
}
factory TableWithoutPKData.fromJson(Map<String, dynamic> json,
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
return TableWithoutPKData(

View File

@ -1,3 +1,4 @@
import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/options.dart';
import 'package:recase/recase.dart';
@ -77,8 +78,9 @@ class DataClassWriter {
..write("final effectivePrefix = prefix ?? '';");
final dartTypeToResolver = <String, String>{};
final columnToTypeMapper = <SpecifiedColumn, String>{};
final types = table.columns.map((c) => c.dartTypeName).toSet();
final types = table.columns.map((c) => c.variableTypeName).toSet();
for (var usedType in types) {
// final intType = db.typeSystem.forDartType<int>();
final resolver = '${ReCase(usedType).camelCase}Type';
@ -88,17 +90,30 @@ class DataClassWriter {
.write('final $resolver = db.typeSystem.forDartType<$usedType>();\n');
}
for (var column in table.columns.where((c) => c.typeConverter != null)) {
final name = '${column.dartGetterName}Converter';
columnToTypeMapper[column] = name;
buffer.write('final $name = ${column.typeConverter.toSource()};');
}
// finally, the mighty constructor invocation:
buffer.write('return $dataClassName(');
for (var column in table.columns) {
// id: intType.mapFromDatabaseResponse(data["id])
final getter = column.dartGetterName;
final resolver = dartTypeToResolver[column.dartTypeName];
final resolver = dartTypeToResolver[column.variableTypeName];
final columnName = "'\${effectivePrefix}${column.name.name}'";
final typeParser = '$resolver.mapFromDatabaseResponse(data[$columnName])';
buffer.write('$getter: $typeParser,');
var loadType = '$resolver.mapFromDatabaseResponse(data[$columnName])';
if (columnToTypeMapper.containsKey(column)) {
final converter = columnToTypeMapper[column];
loadType = '$converter.mapToDart($loadType)';
}
buffer.write('$getter: $loadType,');
}
buffer.write(');}\n');