diff --git a/angel_orm_generator/lib/src/orm_generator.dart b/angel_orm_generator/lib/src/orm_generator.dart index fb461591..25a68ca4 100644 --- a/angel_orm_generator/lib/src/orm_generator.dart +++ b/angel_orm_generator/lib/src/orm_generator.dart @@ -214,6 +214,8 @@ class OrmGenerator extends GeneratorForAnnotation { var skipToList = refer('row') .property('skip') .call([literalNum(i)]) + .property('take') + .call([literalNum(relation.foreign.effectiveFields.length)]) .property('toList') .call([]); var parsed = refer( diff --git a/angel_orm_service/analysis_options.yaml b/angel_orm_service/analysis_options.yaml new file mode 100644 index 00000000..c230cee7 --- /dev/null +++ b/angel_orm_service/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:pedantic/analysis_options.yaml +analyzer: + strong-mode: + implicit-casts: false \ No newline at end of file diff --git a/angel_orm_service/example/connect.dart b/angel_orm_service/example/connect.dart new file mode 100644 index 00000000..214e3762 --- /dev/null +++ b/angel_orm_service/example/connect.dart @@ -0,0 +1,14 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:angel_orm_postgres/angel_orm_postgres.dart'; +import 'package:postgres/postgres.dart'; + +final conn = PostgreSQLConnection('localhost', 5432, 'angel_orm_service_test', + username: Platform.environment['POSTGRES_USERNAME'] ?? 'postgres', + password: Platform.environment['POSTGRES_PASSWORD'] ?? 'password'); + +Future connect() async { + var executor = PostgreSqlExecutor(conn); + await conn.open(); + return executor; +} diff --git a/angel_orm_service/example/main.dart b/angel_orm_service/example/main.dart new file mode 100644 index 00000000..73dd2ba8 --- /dev/null +++ b/angel_orm_service/example/main.dart @@ -0,0 +1,38 @@ +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_framework/http.dart'; +import 'package:angel_orm_service/angel_orm_service.dart'; +import 'package:logging/logging.dart'; +import 'connect.dart'; +import 'todo.dart'; + +main() async { + // Logging, connection setup. + hierarchicalLoggingEnabled = true; + var app = Angel(logger: Logger.detached('orm_service')); + var http = AngelHttp(app); + var executor = await connect(); + app.logger.onRecord.listen((rec) { + print(rec); + if (rec.error != null) print(rec.error); + if (rec.stackTrace != null) print(rec.stackTrace); + }); + + // Create an ORM-backed service. + var todoService = OrmService( + executor, () => TodoQuery(), + readData: (req, res) => todoSerializer.decode(req.bodyAsMap)); + + // Because we provided `readData`, the todoService can face the Web. + // **IMPORTANT: Providing the type arguments is an ABSOLUTE MUST, if your + // model has `int` ID's (this is the case when using `angel_orm_generator` and `Model`). + // ** + app.use>( + '/api/todos', todoService); + + // Clean up when we are done. + app.shutdownHooks.add((_) => executor.close()); + + await http.startServer('127.0.0.1', 3000); + print('Listening at ${http.uri}'); + print('Todos API: ${http.uri}/api/todos'); +} diff --git a/angel_orm_service/example/migrate.dart b/angel_orm_service/example/migrate.dart new file mode 100644 index 00000000..681d295d --- /dev/null +++ b/angel_orm_service/example/migrate.dart @@ -0,0 +1,11 @@ +import 'package:angel_migration_runner/angel_migration_runner.dart'; +import 'package:angel_migration_runner/postgres.dart'; +import 'connect.dart'; +import 'todo.dart'; + +main(List args) { + var runner = PostgresMigrationRunner(conn, migrations: [ + TodoMigration(), + ]); + return runMigrations(runner, args); +} diff --git a/angel_orm_test/lib/src/models/customer.dart b/angel_orm_service/example/todo.dart similarity index 53% rename from angel_orm_test/lib/src/models/customer.dart rename to angel_orm_service/example/todo.dart index 1e87623e..e04a02b7 100644 --- a/angel_orm_test/lib/src/models/customer.dart +++ b/angel_orm_service/example/todo.dart @@ -1,11 +1,14 @@ -library angel_orm_generator.test.models.customer; - import 'package:angel_migration/angel_migration.dart'; -import 'package:angel_model/angel_model.dart'; -import 'package:angel_orm/angel_orm.dart'; import 'package:angel_serialize/angel_serialize.dart'; -part 'customer.g.dart'; +import 'package:angel_orm/angel_orm.dart'; +part 'todo.g.dart'; -@orm @serializable -class _Customer extends Model {} +@orm +abstract class _Todo extends Model { + @notNull + String get text; + + @DefaultsTo(false) + bool isComplete; +} diff --git a/angel_orm_test/lib/src/models/fruit.g.dart b/angel_orm_service/example/todo.g.dart similarity index 55% rename from angel_orm_test/lib/src/models/fruit.g.dart rename to angel_orm_service/example/todo.g.dart index 115d589f..a99cfd4d 100644 --- a/angel_orm_test/lib/src/models/fruit.g.dart +++ b/angel_orm_service/example/todo.g.dart @@ -1,18 +1,18 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of angel_orm_generator.test.models.fruit; +part of 'todo.dart'; // ************************************************************************** // MigrationGenerator // ************************************************************************** -class FruitMigration extends Migration { +class TodoMigration extends Migration { @override up(Schema schema) { - schema.create('fruits', (table) { + schema.create('todos', (table) { table.serial('id')..primaryKey(); - table.integer('tree_id'); - table.varChar('common_name'); + table.boolean('is_complete')..defaultsTo(false); + table.varChar('text'); table.timeStamp('created_at'); table.timeStamp('updated_at'); }); @@ -20,7 +20,7 @@ class FruitMigration extends Migration { @override down(Schema schema) { - schema.drop('fruits'); + schema.drop('todos'); } } @@ -28,17 +28,17 @@ class FruitMigration extends Migration { // OrmGenerator // ************************************************************************** -class FruitQuery extends Query { - FruitQuery({Set trampoline}) { +class TodoQuery extends Query { + TodoQuery({Set trampoline}) { trampoline ??= Set(); trampoline.add(tableName); - _where = FruitQueryWhere(this); + _where = TodoQueryWhere(this); } @override - final FruitQueryValues values = FruitQueryValues(); + final TodoQueryValues values = TodoQueryValues(); - FruitQueryWhere _where; + TodoQueryWhere _where; @override get casts { @@ -47,30 +47,30 @@ class FruitQuery extends Query { @override get tableName { - return 'fruits'; + return 'todos'; } @override get fields { - return const ['id', 'tree_id', 'common_name', 'created_at', 'updated_at']; + return const ['id', 'is_complete', 'text', 'created_at', 'updated_at']; } @override - FruitQueryWhere get where { + TodoQueryWhere get where { return _where; } @override - FruitQueryWhere newWhereClause() { - return FruitQueryWhere(this); + TodoQueryWhere newWhereClause() { + return TodoQueryWhere(this); } - static Fruit parseRow(List row) { + static Todo parseRow(List row) { if (row.every((x) => x == null)) return null; - var model = Fruit( + var model = Todo( id: row[0].toString(), - treeId: (row[1] as int), - commonName: (row[2] as String), + isComplete: (row[1] as bool), + text: (row[2] as String), createdAt: (row[3] as DateTime), updatedAt: (row[4] as DateTime)); return model; @@ -82,19 +82,19 @@ class FruitQuery extends Query { } } -class FruitQueryWhere extends QueryWhere { - FruitQueryWhere(FruitQuery query) +class TodoQueryWhere extends QueryWhere { + TodoQueryWhere(TodoQuery query) : id = NumericSqlExpressionBuilder(query, 'id'), - treeId = NumericSqlExpressionBuilder(query, 'tree_id'), - commonName = StringSqlExpressionBuilder(query, 'common_name'), + isComplete = BooleanSqlExpressionBuilder(query, 'is_complete'), + text = StringSqlExpressionBuilder(query, 'text'), createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'); final NumericSqlExpressionBuilder id; - final NumericSqlExpressionBuilder treeId; + final BooleanSqlExpressionBuilder isComplete; - final StringSqlExpressionBuilder commonName; + final StringSqlExpressionBuilder text; final DateTimeSqlExpressionBuilder createdAt; @@ -102,11 +102,11 @@ class FruitQueryWhere extends QueryWhere { @override get expressionBuilders { - return [id, treeId, commonName, createdAt, updatedAt]; + return [id, isComplete, text, createdAt, updatedAt]; } } -class FruitQueryValues extends MapQueryValues { +class TodoQueryValues extends MapQueryValues { @override get casts { return {}; @@ -117,16 +117,16 @@ class FruitQueryValues extends MapQueryValues { } set id(String value) => values['id'] = value; - int get treeId { - return (values['tree_id'] as int); + bool get isComplete { + return (values['is_complete'] as bool); } - set treeId(int value) => values['tree_id'] = value; - String get commonName { - return (values['common_name'] as String); + set isComplete(bool value) => values['is_complete'] = value; + String get text { + return (values['text'] as String); } - set commonName(String value) => values['common_name'] = value; + set text(String value) => values['text'] = value; DateTime get createdAt { return (values['created_at'] as DateTime); } @@ -137,9 +137,9 @@ class FruitQueryValues extends MapQueryValues { } set updatedAt(DateTime value) => values['updated_at'] = value; - void copyFrom(Fruit model) { - treeId = model.treeId; - commonName = model.commonName; + void copyFrom(Todo model) { + isComplete = model.isComplete; + text = model.text; createdAt = model.createdAt; updatedAt = model.updatedAt; } @@ -150,18 +150,22 @@ class FruitQueryValues extends MapQueryValues { // ************************************************************************** @generatedSerializable -class Fruit extends _Fruit { - Fruit( - {this.id, this.treeId, this.commonName, this.createdAt, this.updatedAt}); +class Todo extends _Todo { + Todo( + {this.id, + this.isComplete = false, + @required this.text, + this.createdAt, + this.updatedAt}); @override final String id; @override - final int treeId; + final bool isComplete; @override - final String commonName; + final String text; @override final DateTime createdAt; @@ -169,41 +173,41 @@ class Fruit extends _Fruit { @override final DateTime updatedAt; - Fruit copyWith( + Todo copyWith( {String id, - int treeId, - String commonName, + bool isComplete, + String text, DateTime createdAt, DateTime updatedAt}) { - return new Fruit( + return new Todo( id: id ?? this.id, - treeId: treeId ?? this.treeId, - commonName: commonName ?? this.commonName, + isComplete: isComplete ?? this.isComplete, + text: text ?? this.text, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt); } bool operator ==(other) { - return other is _Fruit && + return other is _Todo && other.id == id && - other.treeId == treeId && - other.commonName == commonName && + other.isComplete == isComplete && + other.text == text && other.createdAt == createdAt && other.updatedAt == updatedAt; } @override int get hashCode { - return hashObjects([id, treeId, commonName, createdAt, updatedAt]); + return hashObjects([id, isComplete, text, createdAt, updatedAt]); } @override String toString() { - return "Fruit(id=$id, treeId=$treeId, commonName=$commonName, createdAt=$createdAt, updatedAt=$updatedAt)"; + return "Todo(id=$id, isComplete=$isComplete, text=$text, createdAt=$createdAt, updatedAt=$updatedAt)"; } Map toJson() { - return FruitSerializer.toMap(this); + return TodoSerializer.toMap(this); } } @@ -211,34 +215,38 @@ class Fruit extends _Fruit { // SerializerGenerator // ************************************************************************** -const FruitSerializer fruitSerializer = const FruitSerializer(); +const TodoSerializer todoSerializer = const TodoSerializer(); -class FruitEncoder extends Converter { - const FruitEncoder(); +class TodoEncoder extends Converter { + const TodoEncoder(); @override - Map convert(Fruit model) => FruitSerializer.toMap(model); + Map convert(Todo model) => TodoSerializer.toMap(model); } -class FruitDecoder extends Converter { - const FruitDecoder(); +class TodoDecoder extends Converter { + const TodoDecoder(); @override - Fruit convert(Map map) => FruitSerializer.fromMap(map); + Todo convert(Map map) => TodoSerializer.fromMap(map); } -class FruitSerializer extends Codec { - const FruitSerializer(); +class TodoSerializer extends Codec { + const TodoSerializer(); @override - get encoder => const FruitEncoder(); + get encoder => const TodoEncoder(); @override - get decoder => const FruitDecoder(); - static Fruit fromMap(Map map) { - return new Fruit( + get decoder => const TodoDecoder(); + static Todo fromMap(Map map) { + if (map['text'] == null) { + throw new FormatException("Missing required field 'text' on Todo."); + } + + return new Todo( id: map['id'] as String, - treeId: map['tree_id'] as int, - commonName: map['common_name'] as String, + isComplete: map['is_complete'] as bool ?? false, + text: map['text'] as String, createdAt: map['created_at'] != null ? (map['created_at'] is DateTime ? (map['created_at'] as DateTime) @@ -251,34 +259,38 @@ class FruitSerializer extends Codec { : null); } - static Map toMap(_Fruit model) { + static Map toMap(_Todo model) { if (model == null) { return null; } + if (model.text == null) { + throw new FormatException("Missing required field 'text' on Todo."); + } + return { 'id': model.id, - 'tree_id': model.treeId, - 'common_name': model.commonName, + 'is_complete': model.isComplete, + 'text': model.text, 'created_at': model.createdAt?.toIso8601String(), 'updated_at': model.updatedAt?.toIso8601String() }; } } -abstract class FruitFields { +abstract class TodoFields { static const List allFields = [ id, - treeId, - commonName, + isComplete, + text, createdAt, updatedAt ]; static const String id = 'id'; - static const String treeId = 'tree_id'; + static const String isComplete = 'is_complete'; - static const String commonName = 'common_name'; + static const String text = 'text'; static const String createdAt = 'created_at'; diff --git a/angel_orm_service/lib/angel_orm_service.dart b/angel_orm_service/lib/angel_orm_service.dart new file mode 100644 index 00000000..22c8071b --- /dev/null +++ b/angel_orm_service/lib/angel_orm_service.dart @@ -0,0 +1,176 @@ +import 'dart:async'; +import 'package:angel_framework/angel_framework.dart' hide Query; +import 'package:angel_orm/angel_orm.dart'; + +/// A [Service] implementation that wraps over a [Query] class generated +/// via the Angel ORM. +class OrmService> + extends Service { + /// The [QueryExecutor] used to communicate with a database. + final QueryExecutor executor; + + /// A callback that produces an instance of [TQuery]. + final FutureOr Function() queryCreator; + + /// The name of the primary key in the database table. + /// + /// Defaults to `'id'`. + final String idField; + + /// If set to `true`, clients can remove all items by passing a `null` `id` to `remove`. + /// + /// `false` by default. + final bool allowRemoveAll; + + /// If set to `true`, parameters in `req.queryParameters` are applied to the database query. + final bool allowQuery; + + /// In most cases, you will want to provide [readData]. + /// + /// Note that you won't need to call `RequestContext.parseBody`, as by the time + /// `readData` is invoked, the body will have already been parsed. + OrmService(this.executor, this.queryCreator, + {this.idField = 'id', + this.allowRemoveAll = false, + this.allowQuery = true, + FutureOr Function(RequestContext, ResponseContext) readData}) + : super(readData: readData); + + SqlExpressionBuilder _findBuilder(TQuery query, String name) { + return query.where.expressionBuilders.firstWhere( + (b) => b.columnName == name, + orElse: () => throw ArgumentError( + '${query.where.runtimeType} has no expression builder for a column named "$name".')); + } + + void _apply(TQuery query, String name, dynamic value) { + var builder = _findBuilder(query, name); + try { + (builder as dynamic).equals(value); + } on NoSuchMethodError { + throw UnsupportedError( + '${builder.runtimeType} has no `equals` method, so it cannot be given a value from the dynamic query parameter "$name".'); + } + } + + Future _applyQuery(TQuery query, Map params) async { + if (params == null || params.isEmpty) return; + + if (allowQuery || !params.containsKey('provider')) { + var queryObj = params['query']; + + if (queryObj is Function(TQuery)) { + await queryObj(query); + } else if (queryObj is Map) { + queryObj.forEach((k, v) { + if (k is String && v is! RequestContext && v is! ResponseContext) { + _apply(query, k, v); + } + }); + } + } + } + + @override + Future> readMany(List ids, + [Map params]) async { + var query = await queryCreator(); + var builder = _findBuilder(query, idField); + + try { + (builder as dynamic).isIn(ids); + } on NoSuchMethodError { + throw UnsupportedError( + '${builder.runtimeType} `$idField` has no `isIn` method, and therefore does not support `readMany`.'); + } + + await _applyQuery(query, params); + return await query.get(executor); + } + + @override + Future> index([Map params]) async { + var query = await queryCreator(); + await _applyQuery(query, params); + return await query.get(executor); + } + + @override + Future read(Id id, [Map params]) async { + var query = await queryCreator(); + _apply(query, idField, id); + await _applyQuery(query, params); + var result = await query.getOne(executor); + if (result != null) return result; + throw new AngelHttpException.notFound( + message: 'No record found for ID $id'); + } + + @override + Future findOne( + [Map params, + String errorMessage = + 'No record was found matching the given query.']) async { + var query = await queryCreator(); + await _applyQuery(query, params); + var result = await query.getOne(executor); + if (result != null) return result; + throw new AngelHttpException.notFound(message: errorMessage); + } + + @override + Future create(Data data, [Map params]) async { + var query = await queryCreator(); + + try { + (query.values as dynamic).copyFrom(data); + } on NoSuchMethodError { + throw UnsupportedError( + '${query.values.runtimeType} has no `copyFrom` method, but OrmService requires this for insertions.'); + } + + return await query.insert(executor); + } + + @override + Future modify(Id id, Data data, [Map params]) { + // TODO: Is there any way to make this an actual modify, and not an update? + return update(id, data, params); + } + + @override + Future update(Id id, Data data, [Map params]) async { + var query = await queryCreator(); + _apply(query, idField, id); + await _applyQuery(query, params); + + try { + (query.values as dynamic).copyFrom(data); + } on NoSuchMethodError { + throw UnsupportedError( + '${query.values.runtimeType} has no `copyFrom` method, but OrmService requires this for updates.'); + } + + return await query.updateOne(executor); + } + + @override + Future remove(Id id, [Map params]) async { + var query = await queryCreator(); + + if (id == null || id == 'null') { + // Remove everything... + if (!(allowRemoveAll == true || + params?.containsKey('provider') != true)) { + throw AngelHttpException.forbidden( + message: 'Clients are not allowed to delete all items.'); + } + } else { + _apply(query, idField, id); + await _applyQuery(query, params); + } + + var deleted = await query.delete(executor); + return deleted.isEmpty ? null : deleted.first; + } +} diff --git a/angel_orm_service/mono_pkg.yaml b/angel_orm_service/mono_pkg.yaml new file mode 100644 index 00000000..e69de29b diff --git a/angel_orm_service/pubspec.yaml b/angel_orm_service/pubspec.yaml new file mode 100644 index 00000000..89c8e810 --- /dev/null +++ b/angel_orm_service/pubspec.yaml @@ -0,0 +1,18 @@ +name: angel_orm_service +dependencies: + angel_framework: ^2.0.0-alpha + angel_orm: ^2.0.0 + angel_migration: ^2.0.0-alpha +dev_dependencies: + angel_migration_runner: + path: ../angel_migration_runner + angel_orm_generator: + path: ../angel_orm_generator + angel_orm_postgres: + path: ../angel_orm_postgres + angel_orm_test: + path: ../angel_orm_test + build_runner: ^1.0.0 + logging: ^0.11.0 + pedantic: ^1.0.0 + postgres: ^1.0.0 \ No newline at end of file diff --git a/angel_orm_test/build.yaml b/angel_orm_test/build.yaml deleted file mode 100644 index 36867678..00000000 --- a/angel_orm_test/build.yaml +++ /dev/null @@ -1,42 +0,0 @@ -builders: - angel_orm: - import: "package:angel_orm_generator/angel_orm_generator.dart" - builder_factories: - - migrationBuilder - - ormBuilder - auto_apply: root_package - build_to: cache - build_extensions: - .dart: - - ".angel_migration.g.part" - - ".angel_orm.g.part" - required_inputs: - - angel_serialize.g.part - - angel_serialize_serializer.g.part - applies_builders: - - angel_serialize_generator|angel_serialize - - source_gen|combining_builder - - source_gen|part_cleanup" - -targets: - _standalone: - sources: - - lib/src/models/author.dart - - lib/src/models/car.dart - - lib/src/models/customer.dart - - lib/src/models/foot.dart - - lib/src/models/fruit.dart - - lib/src/models/has_map.dart - - lib/src/models/role.dart - - lib/src/models/unorthodox.dart - $default: - dependencies: - - angel_serialize_generator - - :_standalone - sources: - - lib/src/models/book.dart - - lib/src/models/has_car.dart - - lib/src/models/leg.dart - - lib/src/models/order.dart - - lib/src/models/tree.dart - - lib/src/models/user.dart \ No newline at end of file diff --git a/angel_orm_test/lib/src/belongs_to_test.dart b/angel_orm_test/lib/src/belongs_to_test.dart index 7b203b84..cef8344a 100644 --- a/angel_orm_test/lib/src/belongs_to_test.dart +++ b/angel_orm_test/lib/src/belongs_to_test.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:angel_orm/angel_orm.dart'; import 'package:test/test.dart'; -import 'models/author.dart'; import 'models/book.dart'; belongsToTests(FutureOr Function() createExecutor, @@ -46,7 +45,7 @@ belongsToTests(FutureOr Function() createExecutor, expect(book.name, deathlyHallows.name); var author = book.author; - print(author.toJson()); + print(AuthorSerializer.toMap(author)); expect(author.id, jkRowling.id); expect(author.name, jkRowling.name); }); @@ -62,7 +61,7 @@ belongsToTests(FutureOr Function() createExecutor, expect(book.name, deathlyHallows.name); var author = book.author; - print(author.toJson()); + print(AuthorSerializer.toMap(author)); expect(author.id, jkRowling.id); expect(author.name, jkRowling.name); }); @@ -82,7 +81,7 @@ belongsToTests(FutureOr Function() createExecutor, expect(book.name, deathlyHallows.name); var author = book.author; - print(author.toJson()); + print(AuthorSerializer.toMap(author)); expect(author.id, jkRowling.id); expect(author.name, jkRowling.name); }); @@ -106,7 +105,7 @@ belongsToTests(FutureOr Function() createExecutor, expect(book.name, deathlyHallows.name); var author = book.author; - print(author.toJson()); + print(AuthorSerializer.toMap(author)); expect(author.id, jkRowling.id); expect(author.name, jkRowling.name); }); diff --git a/angel_orm_test/lib/src/has_many_test.dart b/angel_orm_test/lib/src/has_many_test.dart index 511bf108..c96add0a 100644 --- a/angel_orm_test/lib/src/has_many_test.dart +++ b/angel_orm_test/lib/src/has_many_test.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:angel_orm/angel_orm.dart'; import 'package:test/test.dart'; -import 'models/fruit.dart'; import 'models/tree.dart'; hasManyTests(FutureOr Function() createExecutor, @@ -30,7 +29,7 @@ hasManyTests(FutureOr Function() createExecutor, Fruit apple, banana; void verify(Tree tree) { - print(tree.fruits.map((f) => f.toJson()).toList()); + print(tree.fruits.map(FruitSerializer.toMap).toList()); expect(tree.fruits, hasLength(2)); expect(tree.fruits[0].commonName, apple.commonName); expect(tree.fruits[1].commonName, banana.commonName); diff --git a/angel_orm_test/lib/src/has_one_test.dart b/angel_orm_test/lib/src/has_one_test.dart index 33897b6a..ba1abe0a 100644 --- a/angel_orm_test/lib/src/has_one_test.dart +++ b/angel_orm_test/lib/src/has_one_test.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:angel_orm/angel_orm.dart'; import 'package:test/test.dart'; -import 'models/foot.dart'; import 'models/leg.dart'; hasOneTests(FutureOr Function() createExecutor, diff --git a/angel_orm_test/lib/src/models/author.dart b/angel_orm_test/lib/src/models/author.dart deleted file mode 100644 index 311cdc89..00000000 --- a/angel_orm_test/lib/src/models/author.dart +++ /dev/null @@ -1,15 +0,0 @@ -library angel_orm.generator.models.author; - -import 'package:angel_model/angel_model.dart'; -import 'package:angel_migration/angel_migration.dart'; -import 'package:angel_orm/angel_orm.dart'; -import 'package:angel_serialize/angel_serialize.dart'; -part 'author.g.dart'; - -@serializable -@orm -abstract class _Author extends Model { - @Column(length: 255, indexType: IndexType.unique) - @SerializableField(defaultValue: 'Tobe Osakwe') - String get name; -} diff --git a/angel_orm_test/lib/src/models/author.g.dart b/angel_orm_test/lib/src/models/author.g.dart deleted file mode 100644 index a7560ad9..00000000 --- a/angel_orm_test/lib/src/models/author.g.dart +++ /dev/null @@ -1,262 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of angel_orm.generator.models.author; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class AuthorMigration extends Migration { - @override - up(Schema schema) { - schema.create('authors', (table) { - table.serial('id')..primaryKey(); - table.varChar('name', length: 255) - ..defaultsTo('Tobe Osakwe') - ..unique(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - }); - } - - @override - down(Schema schema) { - schema.drop('authors'); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class AuthorQuery extends Query { - AuthorQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = AuthorQueryWhere(this); - } - - @override - final AuthorQueryValues values = AuthorQueryValues(); - - AuthorQueryWhere _where; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'authors'; - } - - @override - get fields { - return const ['id', 'name', 'created_at', 'updated_at']; - } - - @override - AuthorQueryWhere get where { - return _where; - } - - @override - AuthorQueryWhere newWhereClause() { - return AuthorQueryWhere(this); - } - - static Author parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Author( - id: row[0].toString(), - name: (row[1] as String), - createdAt: (row[2] as DateTime), - updatedAt: (row[3] as DateTime)); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class AuthorQueryWhere extends QueryWhere { - AuthorQueryWhere(AuthorQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - name = StringSqlExpressionBuilder(query, 'name'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'); - - final NumericSqlExpressionBuilder id; - - final StringSqlExpressionBuilder name; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - @override - get expressionBuilders { - return [id, name, createdAt, updatedAt]; - } -} - -class AuthorQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - String get name { - return (values['name'] as String); - } - - set name(String value) => values['name'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - void copyFrom(Author model) { - name = model.name; - createdAt = model.createdAt; - updatedAt = model.updatedAt; - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class Author extends _Author { - Author({this.id, this.name = 'Tobe Osakwe', this.createdAt, this.updatedAt}); - - @override - final String id; - - @override - final String name; - - @override - final DateTime createdAt; - - @override - final DateTime updatedAt; - - Author copyWith( - {String id, String name, DateTime createdAt, DateTime updatedAt}) { - return new Author( - id: id ?? this.id, - name: name ?? this.name, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt); - } - - bool operator ==(other) { - return other is _Author && - other.id == id && - other.name == name && - other.createdAt == createdAt && - other.updatedAt == updatedAt; - } - - @override - int get hashCode { - return hashObjects([id, name, createdAt, updatedAt]); - } - - @override - String toString() { - return "Author(id=$id, name=$name, createdAt=$createdAt, updatedAt=$updatedAt)"; - } - - Map toJson() { - return AuthorSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const AuthorSerializer authorSerializer = const AuthorSerializer(); - -class AuthorEncoder extends Converter { - const AuthorEncoder(); - - @override - Map convert(Author model) => AuthorSerializer.toMap(model); -} - -class AuthorDecoder extends Converter { - const AuthorDecoder(); - - @override - Author convert(Map map) => AuthorSerializer.fromMap(map); -} - -class AuthorSerializer extends Codec { - const AuthorSerializer(); - - @override - get encoder => const AuthorEncoder(); - @override - get decoder => const AuthorDecoder(); - static Author fromMap(Map map) { - return new Author( - id: map['id'] as String, - name: map['name'] as String ?? 'Tobe Osakwe', - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null); - } - - static Map toMap(_Author model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'name': model.name, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String() - }; - } -} - -abstract class AuthorFields { - static const List allFields = [ - id, - name, - createdAt, - updatedAt - ]; - - static const String id = 'id'; - - static const String name = 'name'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; -} diff --git a/angel_orm_test/lib/src/models/book.dart b/angel_orm_test/lib/src/models/book.dart index c81e7021..1d515c67 100644 --- a/angel_orm_test/lib/src/models/book.dart +++ b/angel_orm_test/lib/src/models/book.dart @@ -4,17 +4,24 @@ import 'package:angel_migration/angel_migration.dart'; import 'package:angel_model/angel_model.dart'; import 'package:angel_orm/angel_orm.dart'; import 'package:angel_serialize/angel_serialize.dart'; -import 'author.dart'; part 'book.g.dart'; @serializable @orm class _Book extends Model { @belongsTo - Author author; + _Author author; @BelongsTo(localKey: "partner_author_id") - Author partnerAuthor; + _Author partnerAuthor; String name; } + +@serializable +@orm +abstract class _Author extends Model { + @Column(length: 255, indexType: IndexType.unique) + @SerializableField(defaultValue: 'Tobe Osakwe') + String get name; +} diff --git a/angel_orm_test/lib/src/models/book.g.dart b/angel_orm_test/lib/src/models/book.g.dart index 6a29dbb6..95b71133 100644 --- a/angel_orm_test/lib/src/models/book.g.dart +++ b/angel_orm_test/lib/src/models/book.g.dart @@ -25,6 +25,25 @@ class BookMigration extends Migration { } } +class AuthorMigration extends Migration { + @override + up(Schema schema) { + schema.create('authors', (table) { + table.serial('id')..primaryKey(); + table.varChar('name', length: 255) + ..defaultsTo('Tobe Osakwe') + ..unique(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + }); + } + + @override + down(Schema schema) { + schema.drop('authors'); + } +} + // ************************************************************************** // OrmGenerator // ************************************************************************** @@ -87,12 +106,12 @@ class BookQuery extends Query { createdAt: (row[4] as DateTime), updatedAt: (row[5] as DateTime)); if (row.length > 6) { - model = - model.copyWith(author: AuthorQuery.parseRow(row.skip(6).toList())); + model = model.copyWith( + author: AuthorQuery.parseRow(row.skip(6).take(4).toList())); } if (row.length > 10) { model = model.copyWith( - partnerAuthor: AuthorQuery.parseRow(row.skip(10).toList())); + partnerAuthor: AuthorQuery.parseRow(row.skip(10).take(4).toList())); } return model; } @@ -180,6 +199,113 @@ class BookQueryValues extends MapQueryValues { } } +class AuthorQuery extends Query { + AuthorQuery({Set trampoline}) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = AuthorQueryWhere(this); + } + + @override + final AuthorQueryValues values = AuthorQueryValues(); + + AuthorQueryWhere _where; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'authors'; + } + + @override + get fields { + return const ['id', 'name', 'created_at', 'updated_at']; + } + + @override + AuthorQueryWhere get where { + return _where; + } + + @override + AuthorQueryWhere newWhereClause() { + return AuthorQueryWhere(this); + } + + static Author parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Author( + id: row[0].toString(), + name: (row[1] as String), + createdAt: (row[2] as DateTime), + updatedAt: (row[3] as DateTime)); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class AuthorQueryWhere extends QueryWhere { + AuthorQueryWhere(AuthorQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + name = StringSqlExpressionBuilder(query, 'name'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'); + + final NumericSqlExpressionBuilder id; + + final StringSqlExpressionBuilder name; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + @override + get expressionBuilders { + return [id, name, createdAt, updatedAt]; + } +} + +class AuthorQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + String get name { + return (values['name'] as String); + } + + set name(String value) => values['name'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + void copyFrom(Author model) { + name = model.name; + createdAt = model.createdAt; + updatedAt = model.updatedAt; + } +} + // ************************************************************************** // JsonModelGenerator // ************************************************************************** @@ -198,10 +324,10 @@ class Book extends _Book { final String id; @override - final Author author; + final _Author author; @override - final Author partnerAuthor; + final _Author partnerAuthor; @override final String name; @@ -214,8 +340,8 @@ class Book extends _Book { Book copyWith( {String id, - Author author, - Author partnerAuthor, + _Author author, + _Author partnerAuthor, String name, DateTime createdAt, DateTime updatedAt}) { @@ -253,6 +379,54 @@ class Book extends _Book { } } +@generatedSerializable +class Author extends _Author { + Author({this.id, this.name = 'Tobe Osakwe', this.createdAt, this.updatedAt}); + + @override + final String id; + + @override + final String name; + + @override + final DateTime createdAt; + + @override + final DateTime updatedAt; + + Author copyWith( + {String id, String name, DateTime createdAt, DateTime updatedAt}) { + return new Author( + id: id ?? this.id, + name: name ?? this.name, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt); + } + + bool operator ==(other) { + return other is _Author && + other.id == id && + other.name == name && + other.createdAt == createdAt && + other.updatedAt == updatedAt; + } + + @override + int get hashCode { + return hashObjects([id, name, createdAt, updatedAt]); + } + + @override + String toString() { + return "Author(id=$id, name=$name, createdAt=$createdAt, updatedAt=$updatedAt)"; + } + + Map toJson() { + return AuthorSerializer.toMap(this); + } +} + // ************************************************************************** // SerializerGenerator // ************************************************************************** @@ -339,3 +513,72 @@ abstract class BookFields { static const String updatedAt = 'updated_at'; } + +const AuthorSerializer authorSerializer = const AuthorSerializer(); + +class AuthorEncoder extends Converter { + const AuthorEncoder(); + + @override + Map convert(Author model) => AuthorSerializer.toMap(model); +} + +class AuthorDecoder extends Converter { + const AuthorDecoder(); + + @override + Author convert(Map map) => AuthorSerializer.fromMap(map); +} + +class AuthorSerializer extends Codec { + const AuthorSerializer(); + + @override + get encoder => const AuthorEncoder(); + @override + get decoder => const AuthorDecoder(); + static Author fromMap(Map map) { + return new Author( + id: map['id'] as String, + name: map['name'] as String ?? 'Tobe Osakwe', + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null); + } + + static Map toMap(_Author model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'name': model.name, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String() + }; + } +} + +abstract class AuthorFields { + static const List allFields = [ + id, + name, + createdAt, + updatedAt + ]; + + static const String id = 'id'; + + static const String name = 'name'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; +} diff --git a/angel_orm_test/lib/src/models/customer.g.dart b/angel_orm_test/lib/src/models/customer.g.dart deleted file mode 100644 index 486133e1..00000000 --- a/angel_orm_test/lib/src/models/customer.g.dart +++ /dev/null @@ -1,234 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of angel_orm_generator.test.models.customer; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class CustomerMigration extends Migration { - @override - up(Schema schema) { - schema.create('customers', (table) { - table.serial('id')..primaryKey(); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - }); - } - - @override - down(Schema schema) { - schema.drop('customers'); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class CustomerQuery extends Query { - CustomerQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = CustomerQueryWhere(this); - } - - @override - final CustomerQueryValues values = CustomerQueryValues(); - - CustomerQueryWhere _where; - - @override - get casts { - return {}; - } - - @override - get tableName { - return 'customers'; - } - - @override - get fields { - return const ['id', 'created_at', 'updated_at']; - } - - @override - CustomerQueryWhere get where { - return _where; - } - - @override - CustomerQueryWhere newWhereClause() { - return CustomerQueryWhere(this); - } - - static Customer parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Customer( - id: row[0].toString(), - createdAt: (row[1] as DateTime), - updatedAt: (row[2] as DateTime)); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class CustomerQueryWhere extends QueryWhere { - CustomerQueryWhere(CustomerQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'); - - final NumericSqlExpressionBuilder id; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - @override - get expressionBuilders { - return [id, createdAt, updatedAt]; - } -} - -class CustomerQueryValues extends MapQueryValues { - @override - get casts { - return {}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - void copyFrom(Customer model) { - createdAt = model.createdAt; - updatedAt = model.updatedAt; - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class Customer extends _Customer { - Customer({this.id, this.createdAt, this.updatedAt}); - - @override - final String id; - - @override - final DateTime createdAt; - - @override - final DateTime updatedAt; - - Customer copyWith({String id, DateTime createdAt, DateTime updatedAt}) { - return new Customer( - id: id ?? this.id, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt); - } - - bool operator ==(other) { - return other is _Customer && - other.id == id && - other.createdAt == createdAt && - other.updatedAt == updatedAt; - } - - @override - int get hashCode { - return hashObjects([id, createdAt, updatedAt]); - } - - @override - String toString() { - return "Customer(id=$id, createdAt=$createdAt, updatedAt=$updatedAt)"; - } - - Map toJson() { - return CustomerSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const CustomerSerializer customerSerializer = const CustomerSerializer(); - -class CustomerEncoder extends Converter { - const CustomerEncoder(); - - @override - Map convert(Customer model) => CustomerSerializer.toMap(model); -} - -class CustomerDecoder extends Converter { - const CustomerDecoder(); - - @override - Customer convert(Map map) => CustomerSerializer.fromMap(map); -} - -class CustomerSerializer extends Codec { - const CustomerSerializer(); - - @override - get encoder => const CustomerEncoder(); - @override - get decoder => const CustomerDecoder(); - static Customer fromMap(Map map) { - return new Customer( - id: map['id'] as String, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null); - } - - static Map toMap(_Customer model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String() - }; - } -} - -abstract class CustomerFields { - static const List allFields = [id, createdAt, updatedAt]; - - static const String id = 'id'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; -} diff --git a/angel_orm_test/lib/src/models/foot.dart b/angel_orm_test/lib/src/models/foot.dart deleted file mode 100644 index b26f1ada..00000000 --- a/angel_orm_test/lib/src/models/foot.dart +++ /dev/null @@ -1,15 +0,0 @@ -library angel_orm_generator.test.models.foot; - -import 'package:angel_migration/angel_migration.dart'; -import 'package:angel_model/angel_model.dart'; -import 'package:angel_orm/angel_orm.dart'; -import 'package:angel_serialize/angel_serialize.dart'; -part 'foot.g.dart'; - -@serializable -@Orm(tableName: 'feet') -class _Foot extends Model { - int legId; - - double nToes; -} diff --git a/angel_orm_test/lib/src/models/foot.g.dart b/angel_orm_test/lib/src/models/foot.g.dart deleted file mode 100644 index 8e78cd27..00000000 --- a/angel_orm_test/lib/src/models/foot.g.dart +++ /dev/null @@ -1,285 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of angel_orm_generator.test.models.foot; - -// ************************************************************************** -// MigrationGenerator -// ************************************************************************** - -class FootMigration extends Migration { - @override - up(Schema schema) { - schema.create('feet', (table) { - table.serial('id')..primaryKey(); - table.integer('leg_id'); - table.declare('n_toes', ColumnType('decimal')); - table.timeStamp('created_at'); - table.timeStamp('updated_at'); - }); - } - - @override - down(Schema schema) { - schema.drop('feet'); - } -} - -// ************************************************************************** -// OrmGenerator -// ************************************************************************** - -class FootQuery extends Query { - FootQuery({Set trampoline}) { - trampoline ??= Set(); - trampoline.add(tableName); - _where = FootQueryWhere(this); - } - - @override - final FootQueryValues values = FootQueryValues(); - - FootQueryWhere _where; - - @override - get casts { - return {'n_toes': 'text'}; - } - - @override - get tableName { - return 'feet'; - } - - @override - get fields { - return const ['id', 'leg_id', 'n_toes', 'created_at', 'updated_at']; - } - - @override - FootQueryWhere get where { - return _where; - } - - @override - FootQueryWhere newWhereClause() { - return FootQueryWhere(this); - } - - static Foot parseRow(List row) { - if (row.every((x) => x == null)) return null; - var model = Foot( - id: row[0].toString(), - legId: (row[1] as int), - nToes: double.tryParse(row[2].toString()), - createdAt: (row[3] as DateTime), - updatedAt: (row[4] as DateTime)); - return model; - } - - @override - deserialize(List row) { - return parseRow(row); - } -} - -class FootQueryWhere extends QueryWhere { - FootQueryWhere(FootQuery query) - : id = NumericSqlExpressionBuilder(query, 'id'), - legId = NumericSqlExpressionBuilder(query, 'leg_id'), - nToes = NumericSqlExpressionBuilder(query, 'n_toes'), - createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), - updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'); - - final NumericSqlExpressionBuilder id; - - final NumericSqlExpressionBuilder legId; - - final NumericSqlExpressionBuilder nToes; - - final DateTimeSqlExpressionBuilder createdAt; - - final DateTimeSqlExpressionBuilder updatedAt; - - @override - get expressionBuilders { - return [id, legId, nToes, createdAt, updatedAt]; - } -} - -class FootQueryValues extends MapQueryValues { - @override - get casts { - return {'n_toes': 'decimal'}; - } - - String get id { - return (values['id'] as String); - } - - set id(String value) => values['id'] = value; - int get legId { - return (values['leg_id'] as int); - } - - set legId(int value) => values['leg_id'] = value; - double get nToes { - return double.tryParse((values['n_toes'] as String)); - } - - set nToes(double value) => values['n_toes'] = value.toString(); - DateTime get createdAt { - return (values['created_at'] as DateTime); - } - - set createdAt(DateTime value) => values['created_at'] = value; - DateTime get updatedAt { - return (values['updated_at'] as DateTime); - } - - set updatedAt(DateTime value) => values['updated_at'] = value; - void copyFrom(Foot model) { - legId = model.legId; - nToes = model.nToes; - createdAt = model.createdAt; - updatedAt = model.updatedAt; - } -} - -// ************************************************************************** -// JsonModelGenerator -// ************************************************************************** - -@generatedSerializable -class Foot extends _Foot { - Foot({this.id, this.legId, this.nToes, this.createdAt, this.updatedAt}); - - @override - final String id; - - @override - final int legId; - - @override - final double nToes; - - @override - final DateTime createdAt; - - @override - final DateTime updatedAt; - - Foot copyWith( - {String id, - int legId, - double nToes, - DateTime createdAt, - DateTime updatedAt}) { - return new Foot( - id: id ?? this.id, - legId: legId ?? this.legId, - nToes: nToes ?? this.nToes, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt); - } - - bool operator ==(other) { - return other is _Foot && - other.id == id && - other.legId == legId && - other.nToes == nToes && - other.createdAt == createdAt && - other.updatedAt == updatedAt; - } - - @override - int get hashCode { - return hashObjects([id, legId, nToes, createdAt, updatedAt]); - } - - @override - String toString() { - return "Foot(id=$id, legId=$legId, nToes=$nToes, createdAt=$createdAt, updatedAt=$updatedAt)"; - } - - Map toJson() { - return FootSerializer.toMap(this); - } -} - -// ************************************************************************** -// SerializerGenerator -// ************************************************************************** - -const FootSerializer footSerializer = const FootSerializer(); - -class FootEncoder extends Converter { - const FootEncoder(); - - @override - Map convert(Foot model) => FootSerializer.toMap(model); -} - -class FootDecoder extends Converter { - const FootDecoder(); - - @override - Foot convert(Map map) => FootSerializer.fromMap(map); -} - -class FootSerializer extends Codec { - const FootSerializer(); - - @override - get encoder => const FootEncoder(); - @override - get decoder => const FootDecoder(); - static Foot fromMap(Map map) { - return new Foot( - id: map['id'] as String, - legId: map['leg_id'] as int, - nToes: map['n_toes'] as double, - createdAt: map['created_at'] != null - ? (map['created_at'] is DateTime - ? (map['created_at'] as DateTime) - : DateTime.parse(map['created_at'].toString())) - : null, - updatedAt: map['updated_at'] != null - ? (map['updated_at'] is DateTime - ? (map['updated_at'] as DateTime) - : DateTime.parse(map['updated_at'].toString())) - : null); - } - - static Map toMap(_Foot model) { - if (model == null) { - return null; - } - return { - 'id': model.id, - 'leg_id': model.legId, - 'n_toes': model.nToes, - 'created_at': model.createdAt?.toIso8601String(), - 'updated_at': model.updatedAt?.toIso8601String() - }; - } -} - -abstract class FootFields { - static const List allFields = [ - id, - legId, - nToes, - createdAt, - updatedAt - ]; - - static const String id = 'id'; - - static const String legId = 'leg_id'; - - static const String nToes = 'n_toes'; - - static const String createdAt = 'created_at'; - - static const String updatedAt = 'updated_at'; -} diff --git a/angel_orm_test/lib/src/models/fruit.dart b/angel_orm_test/lib/src/models/fruit.dart deleted file mode 100644 index 33206053..00000000 --- a/angel_orm_test/lib/src/models/fruit.dart +++ /dev/null @@ -1,14 +0,0 @@ -library angel_orm_generator.test.models.fruit; - -import 'package:angel_migration/angel_migration.dart'; -import 'package:angel_model/angel_model.dart'; -import 'package:angel_orm/angel_orm.dart'; -import 'package:angel_serialize/angel_serialize.dart'; -part 'fruit.g.dart'; - -@serializable -@orm -class _Fruit extends Model { - int treeId; - String commonName; -} diff --git a/angel_orm_test/lib/src/models/leg.dart b/angel_orm_test/lib/src/models/leg.dart index be004363..1c7339ad 100644 --- a/angel_orm_test/lib/src/models/leg.dart +++ b/angel_orm_test/lib/src/models/leg.dart @@ -4,14 +4,21 @@ import 'package:angel_migration/angel_migration.dart'; import 'package:angel_model/angel_model.dart'; import 'package:angel_orm/angel_orm.dart'; import 'package:angel_serialize/angel_serialize.dart'; -import 'foot.dart'; part 'leg.g.dart'; @serializable @orm class _Leg extends Model { @hasOne - Foot foot; + _Foot foot; String name; } + +@serializable +@Orm(tableName: 'feet') +class _Foot extends Model { + int legId; + + double nToes; +} diff --git a/angel_orm_test/lib/src/models/leg.g.dart b/angel_orm_test/lib/src/models/leg.g.dart index db929e7f..69e926e5 100644 --- a/angel_orm_test/lib/src/models/leg.g.dart +++ b/angel_orm_test/lib/src/models/leg.g.dart @@ -23,6 +23,24 @@ class LegMigration extends Migration { } } +class FootMigration extends Migration { + @override + up(Schema schema) { + schema.create('foots', (table) { + table.serial('id')..primaryKey(); + table.integer('leg_id'); + table.declare('n_toes', ColumnType('decimal')); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + }); + } + + @override + down(Schema schema) { + schema.drop('foots'); + } +} + // ************************************************************************** // OrmGenerator // ************************************************************************** @@ -32,7 +50,7 @@ class LegQuery extends Query { trampoline ??= Set(); trampoline.add(tableName); _where = LegQueryWhere(this); - leftJoin('feet', 'id', 'leg_id', + leftJoin('foots', 'id', 'leg_id', additionalFields: const [ 'id', 'leg_id', @@ -81,7 +99,8 @@ class LegQuery extends Query { createdAt: (row[2] as DateTime), updatedAt: (row[3] as DateTime)); if (row.length > 4) { - model = model.copyWith(foot: FootQuery.parseRow(row.skip(4).toList())); + model = model.copyWith( + foot: FootQuery.parseRow(row.skip(4).take(5).toList())); } return model; } @@ -146,6 +165,123 @@ class LegQueryValues extends MapQueryValues { } } +class FootQuery extends Query { + FootQuery({Set trampoline}) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = FootQueryWhere(this); + } + + @override + final FootQueryValues values = FootQueryValues(); + + FootQueryWhere _where; + + @override + get casts { + return {'n_toes': 'text'}; + } + + @override + get tableName { + return 'foots'; + } + + @override + get fields { + return const ['id', 'leg_id', 'n_toes', 'created_at', 'updated_at']; + } + + @override + FootQueryWhere get where { + return _where; + } + + @override + FootQueryWhere newWhereClause() { + return FootQueryWhere(this); + } + + static Foot parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Foot( + id: row[0].toString(), + legId: (row[1] as int), + nToes: double.tryParse(row[2].toString()), + createdAt: (row[3] as DateTime), + updatedAt: (row[4] as DateTime)); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class FootQueryWhere extends QueryWhere { + FootQueryWhere(FootQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + legId = NumericSqlExpressionBuilder(query, 'leg_id'), + nToes = NumericSqlExpressionBuilder(query, 'n_toes'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'); + + final NumericSqlExpressionBuilder id; + + final NumericSqlExpressionBuilder legId; + + final NumericSqlExpressionBuilder nToes; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + @override + get expressionBuilders { + return [id, legId, nToes, createdAt, updatedAt]; + } +} + +class FootQueryValues extends MapQueryValues { + @override + get casts { + return {'n_toes': 'decimal'}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + int get legId { + return (values['leg_id'] as int); + } + + set legId(int value) => values['leg_id'] = value; + double get nToes { + return double.tryParse((values['n_toes'] as String)); + } + + set nToes(double value) => values['n_toes'] = value.toString(); + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + void copyFrom(Foot model) { + legId = model.legId; + nToes = model.nToes; + createdAt = model.createdAt; + updatedAt = model.updatedAt; + } +} + // ************************************************************************** // JsonModelGenerator // ************************************************************************** @@ -158,7 +294,7 @@ class Leg extends _Leg { final String id; @override - final Foot foot; + final _Foot foot; @override final String name; @@ -171,7 +307,7 @@ class Leg extends _Leg { Leg copyWith( {String id, - Foot foot, + _Foot foot, String name, DateTime createdAt, DateTime updatedAt}) { @@ -207,6 +343,63 @@ class Leg extends _Leg { } } +@generatedSerializable +class Foot extends _Foot { + Foot({this.id, this.legId, this.nToes, this.createdAt, this.updatedAt}); + + @override + final String id; + + @override + final int legId; + + @override + final double nToes; + + @override + final DateTime createdAt; + + @override + final DateTime updatedAt; + + Foot copyWith( + {String id, + int legId, + double nToes, + DateTime createdAt, + DateTime updatedAt}) { + return new Foot( + id: id ?? this.id, + legId: legId ?? this.legId, + nToes: nToes ?? this.nToes, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt); + } + + bool operator ==(other) { + return other is _Foot && + other.id == id && + other.legId == legId && + other.nToes == nToes && + other.createdAt == createdAt && + other.updatedAt == updatedAt; + } + + @override + int get hashCode { + return hashObjects([id, legId, nToes, createdAt, updatedAt]); + } + + @override + String toString() { + return "Foot(id=$id, legId=$legId, nToes=$nToes, createdAt=$createdAt, updatedAt=$updatedAt)"; + } + + Map toJson() { + return FootSerializer.toMap(this); + } +} + // ************************************************************************** // SerializerGenerator // ************************************************************************** @@ -286,3 +479,77 @@ abstract class LegFields { static const String updatedAt = 'updated_at'; } + +const FootSerializer footSerializer = const FootSerializer(); + +class FootEncoder extends Converter { + const FootEncoder(); + + @override + Map convert(Foot model) => FootSerializer.toMap(model); +} + +class FootDecoder extends Converter { + const FootDecoder(); + + @override + Foot convert(Map map) => FootSerializer.fromMap(map); +} + +class FootSerializer extends Codec { + const FootSerializer(); + + @override + get encoder => const FootEncoder(); + @override + get decoder => const FootDecoder(); + static Foot fromMap(Map map) { + return new Foot( + id: map['id'] as String, + legId: map['leg_id'] as int, + nToes: map['n_toes'] as double, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null); + } + + static Map toMap(_Foot model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'leg_id': model.legId, + 'n_toes': model.nToes, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String() + }; + } +} + +abstract class FootFields { + static const List allFields = [ + id, + legId, + nToes, + createdAt, + updatedAt + ]; + + static const String id = 'id'; + + static const String legId = 'leg_id'; + + static const String nToes = 'n_toes'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; +} diff --git a/angel_orm_test/lib/src/models/order.dart b/angel_orm_test/lib/src/models/order.dart index ebd3bc03..90f6a07a 100644 --- a/angel_orm_test/lib/src/models/order.dart +++ b/angel_orm_test/lib/src/models/order.dart @@ -4,14 +4,13 @@ import 'package:angel_migration/angel_migration.dart'; import 'package:angel_model/angel_model.dart'; import 'package:angel_orm/angel_orm.dart'; import 'package:angel_serialize/angel_serialize.dart'; -import 'customer.dart'; part 'order.g.dart'; @orm @serializable abstract class _Order extends Model { @belongsTo - Customer get customer; + _Customer get customer; int get employeeId; @@ -19,3 +18,7 @@ abstract class _Order extends Model { int get shipperId; } + +@orm +@serializable +class _Customer extends Model {} diff --git a/angel_orm_test/lib/src/models/order.g.dart b/angel_orm_test/lib/src/models/order.g.dart index 8fec0eff..6635748b 100644 --- a/angel_orm_test/lib/src/models/order.g.dart +++ b/angel_orm_test/lib/src/models/order.g.dart @@ -26,6 +26,22 @@ class OrderMigration extends Migration { } } +class CustomerMigration extends Migration { + @override + up(Schema schema) { + schema.create('customers', (table) { + table.serial('id')..primaryKey(); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + }); + } + + @override + down(Schema schema) { + schema.drop('customers'); + } +} + // ************************************************************************** // OrmGenerator // ************************************************************************** @@ -89,7 +105,7 @@ class OrderQuery extends Query { updatedAt: (row[6] as DateTime)); if (row.length > 7) { model = model.copyWith( - customer: CustomerQuery.parseRow(row.skip(7).toList())); + customer: CustomerQuery.parseRow(row.skip(7).take(3).toList())); } return model; } @@ -191,6 +207,103 @@ class OrderQueryValues extends MapQueryValues { } } +class CustomerQuery extends Query { + CustomerQuery({Set trampoline}) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = CustomerQueryWhere(this); + } + + @override + final CustomerQueryValues values = CustomerQueryValues(); + + CustomerQueryWhere _where; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'customers'; + } + + @override + get fields { + return const ['id', 'created_at', 'updated_at']; + } + + @override + CustomerQueryWhere get where { + return _where; + } + + @override + CustomerQueryWhere newWhereClause() { + return CustomerQueryWhere(this); + } + + static Customer parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Customer( + id: row[0].toString(), + createdAt: (row[1] as DateTime), + updatedAt: (row[2] as DateTime)); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class CustomerQueryWhere extends QueryWhere { + CustomerQueryWhere(CustomerQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'); + + final NumericSqlExpressionBuilder id; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + @override + get expressionBuilders { + return [id, createdAt, updatedAt]; + } +} + +class CustomerQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + void copyFrom(Customer model) { + createdAt = model.createdAt; + updatedAt = model.updatedAt; + } +} + // ************************************************************************** // JsonModelGenerator // ************************************************************************** @@ -210,7 +323,7 @@ class Order extends _Order { final String id; @override - final Customer customer; + final _Customer customer; @override final int employeeId; @@ -229,7 +342,7 @@ class Order extends _Order { Order copyWith( {String id, - Customer customer, + _Customer customer, int employeeId, DateTime orderDate, int shipperId, @@ -272,6 +385,48 @@ class Order extends _Order { } } +@generatedSerializable +class Customer extends _Customer { + Customer({this.id, this.createdAt, this.updatedAt}); + + @override + final String id; + + @override + final DateTime createdAt; + + @override + final DateTime updatedAt; + + Customer copyWith({String id, DateTime createdAt, DateTime updatedAt}) { + return new Customer( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt); + } + + bool operator ==(other) { + return other is _Customer && + other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt; + } + + @override + int get hashCode { + return hashObjects([id, createdAt, updatedAt]); + } + + @override + String toString() { + return "Customer(id=$id, createdAt=$createdAt, updatedAt=$updatedAt)"; + } + + Map toJson() { + return CustomerSerializer.toMap(this); + } +} + // ************************************************************************** // SerializerGenerator // ************************************************************************** @@ -365,3 +520,63 @@ abstract class OrderFields { static const String updatedAt = 'updated_at'; } + +const CustomerSerializer customerSerializer = const CustomerSerializer(); + +class CustomerEncoder extends Converter { + const CustomerEncoder(); + + @override + Map convert(Customer model) => CustomerSerializer.toMap(model); +} + +class CustomerDecoder extends Converter { + const CustomerDecoder(); + + @override + Customer convert(Map map) => CustomerSerializer.fromMap(map); +} + +class CustomerSerializer extends Codec { + const CustomerSerializer(); + + @override + get encoder => const CustomerEncoder(); + @override + get decoder => const CustomerDecoder(); + static Customer fromMap(Map map) { + return new Customer( + id: map['id'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null); + } + + static Map toMap(_Customer model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String() + }; + } +} + +abstract class CustomerFields { + static const List allFields = [id, createdAt, updatedAt]; + + static const String id = 'id'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; +} diff --git a/angel_orm_test/lib/src/models/tree.dart b/angel_orm_test/lib/src/models/tree.dart index 7be2b332..d549bb42 100644 --- a/angel_orm_test/lib/src/models/tree.dart +++ b/angel_orm_test/lib/src/models/tree.dart @@ -5,7 +5,6 @@ import 'package:angel_model/angel_model.dart'; import 'package:angel_orm/angel_orm.dart'; import 'package:angel_serialize/angel_serialize.dart'; import 'package:collection/collection.dart'; -import 'fruit.dart'; part 'tree.g.dart'; @serializable @@ -15,5 +14,12 @@ class _Tree extends Model { int rings; @hasMany - List fruits; + List<_Fruit> fruits; +} + +@serializable +@orm +class _Fruit extends Model { + int treeId; + String commonName; } diff --git a/angel_orm_test/lib/src/models/tree.g.dart b/angel_orm_test/lib/src/models/tree.g.dart index 853c7f7f..cdfd6b4d 100644 --- a/angel_orm_test/lib/src/models/tree.g.dart +++ b/angel_orm_test/lib/src/models/tree.g.dart @@ -23,6 +23,24 @@ class TreeMigration extends Migration { } } +class FruitMigration extends Migration { + @override + up(Schema schema) { + schema.create('fruits', (table) { + table.serial('id')..primaryKey(); + table.integer('tree_id'); + table.varChar('common_name'); + table.timeStamp('created_at'); + table.timeStamp('updated_at'); + }); + } + + @override + down(Schema schema) { + schema.drop('fruits'); + } +} + // ************************************************************************** // OrmGenerator // ************************************************************************** @@ -82,7 +100,7 @@ class TreeQuery extends Query { updatedAt: (row[3] as DateTime)); if (row.length > 4) { model = model.copyWith( - fruits: [FruitQuery.parseRow(row.skip(4).toList())] + fruits: [FruitQuery.parseRow(row.skip(4).take(5).toList())] .where((x) => x != null) .toList()); } @@ -106,7 +124,7 @@ class TreeQuery extends Query { var l = out[idx]; return out ..[idx] = l.copyWith( - fruits: List.from(l.fruits ?? []) + fruits: List<_Fruit>.from(l.fruits ?? []) ..addAll(model.fruits ?? [])); } }); @@ -125,7 +143,7 @@ class TreeQuery extends Query { var l = out[idx]; return out ..[idx] = l.copyWith( - fruits: List.from(l.fruits ?? []) + fruits: List<_Fruit>.from(l.fruits ?? []) ..addAll(model.fruits ?? [])); } }); @@ -144,7 +162,7 @@ class TreeQuery extends Query { var l = out[idx]; return out ..[idx] = l.copyWith( - fruits: List.from(l.fruits ?? []) + fruits: List<_Fruit>.from(l.fruits ?? []) ..addAll(model.fruits ?? [])); } }); @@ -206,6 +224,123 @@ class TreeQueryValues extends MapQueryValues { } } +class FruitQuery extends Query { + FruitQuery({Set trampoline}) { + trampoline ??= Set(); + trampoline.add(tableName); + _where = FruitQueryWhere(this); + } + + @override + final FruitQueryValues values = FruitQueryValues(); + + FruitQueryWhere _where; + + @override + get casts { + return {}; + } + + @override + get tableName { + return 'fruits'; + } + + @override + get fields { + return const ['id', 'tree_id', 'common_name', 'created_at', 'updated_at']; + } + + @override + FruitQueryWhere get where { + return _where; + } + + @override + FruitQueryWhere newWhereClause() { + return FruitQueryWhere(this); + } + + static Fruit parseRow(List row) { + if (row.every((x) => x == null)) return null; + var model = Fruit( + id: row[0].toString(), + treeId: (row[1] as int), + commonName: (row[2] as String), + createdAt: (row[3] as DateTime), + updatedAt: (row[4] as DateTime)); + return model; + } + + @override + deserialize(List row) { + return parseRow(row); + } +} + +class FruitQueryWhere extends QueryWhere { + FruitQueryWhere(FruitQuery query) + : id = NumericSqlExpressionBuilder(query, 'id'), + treeId = NumericSqlExpressionBuilder(query, 'tree_id'), + commonName = StringSqlExpressionBuilder(query, 'common_name'), + createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'), + updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at'); + + final NumericSqlExpressionBuilder id; + + final NumericSqlExpressionBuilder treeId; + + final StringSqlExpressionBuilder commonName; + + final DateTimeSqlExpressionBuilder createdAt; + + final DateTimeSqlExpressionBuilder updatedAt; + + @override + get expressionBuilders { + return [id, treeId, commonName, createdAt, updatedAt]; + } +} + +class FruitQueryValues extends MapQueryValues { + @override + get casts { + return {}; + } + + String get id { + return (values['id'] as String); + } + + set id(String value) => values['id'] = value; + int get treeId { + return (values['tree_id'] as int); + } + + set treeId(int value) => values['tree_id'] = value; + String get commonName { + return (values['common_name'] as String); + } + + set commonName(String value) => values['common_name'] = value; + DateTime get createdAt { + return (values['created_at'] as DateTime); + } + + set createdAt(DateTime value) => values['created_at'] = value; + DateTime get updatedAt { + return (values['updated_at'] as DateTime); + } + + set updatedAt(DateTime value) => values['updated_at'] = value; + void copyFrom(Fruit model) { + treeId = model.treeId; + commonName = model.commonName; + createdAt = model.createdAt; + updatedAt = model.updatedAt; + } +} + // ************************************************************************** // JsonModelGenerator // ************************************************************************** @@ -213,7 +348,11 @@ class TreeQueryValues extends MapQueryValues { @generatedSerializable class Tree extends _Tree { Tree( - {this.id, this.rings, List fruits, this.createdAt, this.updatedAt}) + {this.id, + this.rings, + List<_Fruit> fruits, + this.createdAt, + this.updatedAt}) : this.fruits = new List.unmodifiable(fruits ?? []); @override @@ -223,7 +362,7 @@ class Tree extends _Tree { final int rings; @override - final List fruits; + final List<_Fruit> fruits; @override final DateTime createdAt; @@ -234,7 +373,7 @@ class Tree extends _Tree { Tree copyWith( {String id, int rings, - List fruits, + List<_Fruit> fruits, DateTime createdAt, DateTime updatedAt}) { return new Tree( @@ -249,7 +388,7 @@ class Tree extends _Tree { return other is _Tree && other.id == id && other.rings == rings && - const ListEquality(const DefaultEquality()) + const ListEquality<_Fruit>(const DefaultEquality<_Fruit>()) .equals(other.fruits, fruits) && other.createdAt == createdAt && other.updatedAt == updatedAt; @@ -270,6 +409,64 @@ class Tree extends _Tree { } } +@generatedSerializable +class Fruit extends _Fruit { + Fruit( + {this.id, this.treeId, this.commonName, this.createdAt, this.updatedAt}); + + @override + final String id; + + @override + final int treeId; + + @override + final String commonName; + + @override + final DateTime createdAt; + + @override + final DateTime updatedAt; + + Fruit copyWith( + {String id, + int treeId, + String commonName, + DateTime createdAt, + DateTime updatedAt}) { + return new Fruit( + id: id ?? this.id, + treeId: treeId ?? this.treeId, + commonName: commonName ?? this.commonName, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt); + } + + bool operator ==(other) { + return other is _Fruit && + other.id == id && + other.treeId == treeId && + other.commonName == commonName && + other.createdAt == createdAt && + other.updatedAt == updatedAt; + } + + @override + int get hashCode { + return hashObjects([id, treeId, commonName, createdAt, updatedAt]); + } + + @override + String toString() { + return "Fruit(id=$id, treeId=$treeId, commonName=$commonName, createdAt=$createdAt, updatedAt=$updatedAt)"; + } + + Map toJson() { + return FruitSerializer.toMap(this); + } +} + // ************************************************************************** // SerializerGenerator // ************************************************************************** @@ -352,3 +549,77 @@ abstract class TreeFields { static const String updatedAt = 'updated_at'; } + +const FruitSerializer fruitSerializer = const FruitSerializer(); + +class FruitEncoder extends Converter { + const FruitEncoder(); + + @override + Map convert(Fruit model) => FruitSerializer.toMap(model); +} + +class FruitDecoder extends Converter { + const FruitDecoder(); + + @override + Fruit convert(Map map) => FruitSerializer.fromMap(map); +} + +class FruitSerializer extends Codec { + const FruitSerializer(); + + @override + get encoder => const FruitEncoder(); + @override + get decoder => const FruitDecoder(); + static Fruit fromMap(Map map) { + return new Fruit( + id: map['id'] as String, + treeId: map['tree_id'] as int, + commonName: map['common_name'] as String, + createdAt: map['created_at'] != null + ? (map['created_at'] is DateTime + ? (map['created_at'] as DateTime) + : DateTime.parse(map['created_at'].toString())) + : null, + updatedAt: map['updated_at'] != null + ? (map['updated_at'] is DateTime + ? (map['updated_at'] as DateTime) + : DateTime.parse(map['updated_at'].toString())) + : null); + } + + static Map toMap(_Fruit model) { + if (model == null) { + return null; + } + return { + 'id': model.id, + 'tree_id': model.treeId, + 'common_name': model.commonName, + 'created_at': model.createdAt?.toIso8601String(), + 'updated_at': model.updatedAt?.toIso8601String() + }; + } +} + +abstract class FruitFields { + static const List allFields = [ + id, + treeId, + commonName, + createdAt, + updatedAt + ]; + + static const String id = 'id'; + + static const String treeId = 'tree_id'; + + static const String commonName = 'common_name'; + + static const String createdAt = 'created_at'; + + static const String updatedAt = 'updated_at'; +} diff --git a/angel_orm_test/lib/src/models/unorthodox.g.dart b/angel_orm_test/lib/src/models/unorthodox.g.dart index efcaeb38..98a24a17 100644 --- a/angel_orm_test/lib/src/models/unorthodox.g.dart +++ b/angel_orm_test/lib/src/models/unorthodox.g.dart @@ -232,20 +232,21 @@ class WeirdJoinQuery extends Query { var model = WeirdJoin(id: (row[0] as int)); if (row.length > 2) { model = model.copyWith( - unorthodox: UnorthodoxQuery.parseRow(row.skip(2).toList())); + unorthodox: UnorthodoxQuery.parseRow(row.skip(2).take(1).toList())); } if (row.length > 3) { - model = model.copyWith(song: SongQuery.parseRow(row.skip(3).toList())); + model = model.copyWith( + song: SongQuery.parseRow(row.skip(3).take(5).toList())); } if (row.length > 8) { model = model.copyWith( - numbas: [NumbaQuery.parseRow(row.skip(8).toList())] + numbas: [NumbaQuery.parseRow(row.skip(8).take(2).toList())] .where((x) => x != null) .toList()); } if (row.length > 10) { model = model.copyWith( - foos: [FooQuery.parseRow(row.skip(10).toList())] + foos: [FooQuery.parseRow(row.skip(10).take(1).toList())] .where((x) => x != null) .toList()); } @@ -610,7 +611,7 @@ class FooQuery extends Query { var model = Foo(bar: (row[0] as String)); if (row.length > 1) { model = model.copyWith( - weirdJoins: [WeirdJoinQuery.parseRow(row.skip(1).toList())] + weirdJoins: [WeirdJoinQuery.parseRow(row.skip(1).take(2).toList())] .where((x) => x != null) .toList()); } @@ -760,10 +761,11 @@ class FooPivotQuery extends Query { var model = FooPivot(); if (row.length > 2) { model = model.copyWith( - weirdJoin: WeirdJoinQuery.parseRow(row.skip(2).toList())); + weirdJoin: WeirdJoinQuery.parseRow(row.skip(2).take(2).toList())); } if (row.length > 4) { - model = model.copyWith(foo: FooQuery.parseRow(row.skip(4).toList())); + model = + model.copyWith(foo: FooQuery.parseRow(row.skip(4).take(1).toList())); } return model; } diff --git a/angel_orm_test/lib/src/models/user.g.dart b/angel_orm_test/lib/src/models/user.g.dart index 85f6eb16..7d92b06c 100644 --- a/angel_orm_test/lib/src/models/user.g.dart +++ b/angel_orm_test/lib/src/models/user.g.dart @@ -119,7 +119,7 @@ class UserQuery extends Query { updatedAt: (row[5] as DateTime)); if (row.length > 6) { model = model.copyWith( - roles: [RoleQuery.parseRow(row.skip(6).toList())] + roles: [RoleQuery.parseRow(row.skip(6).take(4).toList())] .where((x) => x != null) .toList()); } @@ -321,10 +321,12 @@ class RoleUserQuery extends Query { if (row.every((x) => x == null)) return null; var model = RoleUser(); if (row.length > 2) { - model = model.copyWith(role: RoleQuery.parseRow(row.skip(2).toList())); + model = model.copyWith( + role: RoleQuery.parseRow(row.skip(2).take(4).toList())); } if (row.length > 6) { - model = model.copyWith(user: UserQuery.parseRow(row.skip(6).toList())); + model = model.copyWith( + user: UserQuery.parseRow(row.skip(6).take(6).toList())); } return model; } @@ -432,7 +434,7 @@ class RoleQuery extends Query { updatedAt: (row[3] as DateTime)); if (row.length > 4) { model = model.copyWith( - users: [UserQuery.parseRow(row.skip(4).toList())] + users: [UserQuery.parseRow(row.skip(4).take(6).toList())] .where((x) => x != null) .toList()); }