orm_service tests
This commit is contained in:
parent
55e8a2e83c
commit
4bc50eca69
7 changed files with 726 additions and 7 deletions
|
@ -1,3 +1,6 @@
|
||||||
|
# 2.0.1
|
||||||
|
* Gracefully handle `null` in enum fields.
|
||||||
|
|
||||||
# 2.0.0+2
|
# 2.0.0+2
|
||||||
* Widen `analyzer` dependency range.
|
* Widen `analyzer` dependency range.
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,9 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
.property('tryParse')
|
.property('tryParse')
|
||||||
.call([expr.property('toString').call([])]);
|
.call([expr.property('toString').call([])]);
|
||||||
} else if (fType is InterfaceType && fType.element.isEnum) {
|
} else if (fType is InterfaceType && fType.element.isEnum) {
|
||||||
expr = type.property('values').index(expr.asA(refer('int')));
|
var isNull = expr.equalTo(literalNull);
|
||||||
|
expr = isNull.conditional(literalNull,
|
||||||
|
type.property('values').index(expr.asA(refer('int'))));
|
||||||
} else
|
} else
|
||||||
expr = expr.asA(type);
|
expr = expr.asA(type);
|
||||||
|
|
||||||
|
@ -691,7 +693,7 @@ class OrmGenerator extends GeneratorForAnnotation<Orm> {
|
||||||
Expression value = refer('value');
|
Expression value = refer('value');
|
||||||
|
|
||||||
if (fType is InterfaceType && fType.element.isEnum) {
|
if (fType is InterfaceType && fType.element.isEnum) {
|
||||||
value = value.property('index');
|
value = CodeExpression(Code('value?.index'));
|
||||||
} else if (const TypeChecker.fromRuntime(List)
|
} else if (const TypeChecker.fromRuntime(List)
|
||||||
.isAssignableFromType(fType)) {
|
.isAssignableFromType(fType)) {
|
||||||
value = refer('json').property('encode').call([value]);
|
value = refer('json').property('encode').call([value]);
|
||||||
|
|
21
angel_orm_service/LICENSE
Normal file
21
angel_orm_service/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017 The Angel Framework
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -63,7 +63,21 @@ class OrmService<Id, Data, TQuery extends Query<Data, QueryWhere>>
|
||||||
await queryObj(query);
|
await queryObj(query);
|
||||||
} else if (queryObj is Map) {
|
} else if (queryObj is Map) {
|
||||||
queryObj.forEach((k, v) {
|
queryObj.forEach((k, v) {
|
||||||
if (k is String && v is! RequestContext && v is! ResponseContext) {
|
if (k == r'$sort') {
|
||||||
|
if (v is Map) {
|
||||||
|
v.forEach((key, value) {
|
||||||
|
var descending = false;
|
||||||
|
if (value is String)
|
||||||
|
descending = value == '-1';
|
||||||
|
else if (value is num) descending = value.toInt() == -1;
|
||||||
|
query.orderBy(key.toString(), descending: descending);
|
||||||
|
});
|
||||||
|
} else if (v is String) {
|
||||||
|
query.orderBy(v);
|
||||||
|
}
|
||||||
|
} else if (k is String &&
|
||||||
|
v is! RequestContext &&
|
||||||
|
v is! ResponseContext) {
|
||||||
_apply(query, k, v);
|
_apply(query, k, v);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -74,6 +88,10 @@ class OrmService<Id, Data, TQuery extends Query<Data, QueryWhere>>
|
||||||
@override
|
@override
|
||||||
Future<List<Data>> readMany(List<Id> ids,
|
Future<List<Data>> readMany(List<Id> ids,
|
||||||
[Map<String, dynamic> params]) async {
|
[Map<String, dynamic> params]) async {
|
||||||
|
if (ids.isEmpty) {
|
||||||
|
throw ArgumentError.value(ids, 'ids', 'cannot be empty');
|
||||||
|
}
|
||||||
|
|
||||||
var query = await queryCreator();
|
var query = await queryCreator();
|
||||||
var builder = _findBuilder(query, idField);
|
var builder = _findBuilder(query, idField);
|
||||||
|
|
||||||
|
@ -134,7 +152,6 @@ class OrmService<Id, Data, TQuery extends Query<Data, QueryWhere>>
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Data> modify(Id id, Data data, [Map<String, dynamic> params]) {
|
Future<Data> modify(Id id, Data data, [Map<String, dynamic> params]) {
|
||||||
// TODO: Is there any way to make this an actual modify, and not an update?
|
|
||||||
return update(id, data, params);
|
return update(id, data, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +168,10 @@ class OrmService<Id, Data, TQuery extends Query<Data, QueryWhere>>
|
||||||
'${query.values.runtimeType} has no `copyFrom` method, but OrmService requires this for updates.');
|
'${query.values.runtimeType} has no `copyFrom` method, but OrmService requires this for updates.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return await query.updateOne(executor);
|
var result = await query.updateOne(executor);
|
||||||
|
if (result != null) return result;
|
||||||
|
throw new AngelHttpException.notFound(
|
||||||
|
message: 'No record found for ID $id');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -170,7 +190,9 @@ class OrmService<Id, Data, TQuery extends Query<Data, QueryWhere>>
|
||||||
await _applyQuery(query, params);
|
await _applyQuery(query, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
var deleted = await query.delete(executor);
|
var result = await query.deleteOne(executor);
|
||||||
return deleted.isEmpty ? null : deleted.first;
|
if (result != null) return result;
|
||||||
|
throw new AngelHttpException.notFound(
|
||||||
|
message: 'No record found for ID $id');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
233
angel_orm_service/test/all_test.dart
Normal file
233
angel_orm_service/test/all_test.dart
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:angel_framework/angel_framework.dart';
|
||||||
|
import 'package:angel_orm_postgres/angel_orm_postgres.dart';
|
||||||
|
import 'package:angel_orm_service/angel_orm_service.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:postgres/postgres.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'pokemon.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
Logger logger;
|
||||||
|
PostgreSqlExecutor executor;
|
||||||
|
Service<int, Pokemon> pokemonService;
|
||||||
|
|
||||||
|
setUp(() async {
|
||||||
|
var conn = PostgreSQLConnection('localhost', 5432, 'angel_orm_service_test',
|
||||||
|
username: Platform.environment['POSTGRES_USERNAME'] ?? 'postgres',
|
||||||
|
password: Platform.environment['POSTGRES_PASSWORD'] ?? 'password');
|
||||||
|
hierarchicalLoggingEnabled = true;
|
||||||
|
logger = Logger.detached('orm_service');
|
||||||
|
logger.level = Level.ALL;
|
||||||
|
if (Platform.environment['log'] == '1') logger.onRecord.listen(print);
|
||||||
|
executor = PostgreSqlExecutor(conn, logger: logger);
|
||||||
|
await conn.open();
|
||||||
|
await conn.query('''
|
||||||
|
CREATE TEMPORARY TABLE pokemons (
|
||||||
|
id serial,
|
||||||
|
species varchar,
|
||||||
|
name varchar,
|
||||||
|
level integer,
|
||||||
|
type1 integer,
|
||||||
|
type2 integer,
|
||||||
|
created_at timestamp,
|
||||||
|
updated_at timestamp
|
||||||
|
);
|
||||||
|
''');
|
||||||
|
|
||||||
|
pokemonService = OrmService(executor, () => PokemonQuery());
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() async {
|
||||||
|
await executor.close();
|
||||||
|
pokemonService.close();
|
||||||
|
logger.clearListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('create', () async {
|
||||||
|
var blaziken = await pokemonService.create(Pokemon(
|
||||||
|
species: 'Blaziken',
|
||||||
|
level: 100,
|
||||||
|
type1: PokemonType.fire,
|
||||||
|
type2: PokemonType.fighting));
|
||||||
|
print(blaziken);
|
||||||
|
expect(blaziken.id, isNotNull);
|
||||||
|
expect(blaziken.species, 'Blaziken');
|
||||||
|
expect(blaziken.level, 100);
|
||||||
|
expect(blaziken.type1, PokemonType.fire);
|
||||||
|
expect(blaziken.type2, PokemonType.fighting);
|
||||||
|
});
|
||||||
|
|
||||||
|
group('after create', () {
|
||||||
|
Pokemon giratina, pikachu;
|
||||||
|
|
||||||
|
setUp(() async {
|
||||||
|
giratina = await pokemonService.create(Pokemon(
|
||||||
|
species: 'Giratina',
|
||||||
|
name: 'My First Legendary',
|
||||||
|
level: 54,
|
||||||
|
type1: PokemonType.ghost,
|
||||||
|
type2: PokemonType.dragon));
|
||||||
|
pikachu = await pokemonService.create(Pokemon(
|
||||||
|
species: 'Pikachu',
|
||||||
|
level: 100,
|
||||||
|
type1: PokemonType.electric,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
group('index', () {
|
||||||
|
test('default', () async {
|
||||||
|
expect(await pokemonService.index(), contains(giratina));
|
||||||
|
expect(await pokemonService.index(), contains(pikachu));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('with callback', () async {
|
||||||
|
var result = await pokemonService.index({
|
||||||
|
'query': (PokemonQuery query) async {
|
||||||
|
query.where.level.equals(pikachu.level);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result, [pikachu]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('search params', () async {
|
||||||
|
Future<List<Pokemon>> searchByType1(PokemonType type1) async {
|
||||||
|
var query = {PokemonFields.type1: type1};
|
||||||
|
var params = {'query': query};
|
||||||
|
return await pokemonService.index(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(await searchByType1(PokemonType.ghost), [giratina]);
|
||||||
|
expect(await searchByType1(PokemonType.electric), [pikachu]);
|
||||||
|
expect(await searchByType1(PokemonType.grass), []);
|
||||||
|
});
|
||||||
|
|
||||||
|
group(r'$sort', () {
|
||||||
|
test('by name', () async {
|
||||||
|
expect(
|
||||||
|
await pokemonService.index({
|
||||||
|
'query': {r'$sort': 'level'}
|
||||||
|
}),
|
||||||
|
[giratina, pikachu]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('map number', () async {
|
||||||
|
expect(
|
||||||
|
await pokemonService.index({
|
||||||
|
'query': {
|
||||||
|
r'$sort': {'type1': -1}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
[giratina, pikachu]);
|
||||||
|
expect(
|
||||||
|
await pokemonService.index({
|
||||||
|
'query': {
|
||||||
|
r'$sort': {'type1': 100}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
[pikachu, giratina]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('map string', () async {
|
||||||
|
expect(
|
||||||
|
await pokemonService.index({
|
||||||
|
'query': {
|
||||||
|
r'$sort': {'type1': '-1'}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
[giratina, pikachu]);
|
||||||
|
expect(
|
||||||
|
await pokemonService.index({
|
||||||
|
'query': {
|
||||||
|
r'$sort': {'type1': 'foo'}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
[pikachu, giratina]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('findOne', () {
|
||||||
|
test('default', () async {
|
||||||
|
expect(
|
||||||
|
await pokemonService.findOne({
|
||||||
|
'query': {PokemonFields.name: giratina.name}
|
||||||
|
}),
|
||||||
|
giratina);
|
||||||
|
expect(
|
||||||
|
await pokemonService.findOne({
|
||||||
|
'query': {PokemonFields.level: pikachu.level}
|
||||||
|
}),
|
||||||
|
pikachu);
|
||||||
|
expect(
|
||||||
|
() => pokemonService.findOne({
|
||||||
|
'query': {PokemonFields.level: pikachu.level * 3}
|
||||||
|
}),
|
||||||
|
throwsA(TypeMatcher<AngelHttpException>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('nonexistent throws 404', () {
|
||||||
|
expect(
|
||||||
|
() => pokemonService.findOne({
|
||||||
|
'query': {PokemonFields.type1: PokemonType.poison}
|
||||||
|
}),
|
||||||
|
throwsA(TypeMatcher<AngelHttpException>()));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('read', () {
|
||||||
|
test('default', () async {
|
||||||
|
expect(await pokemonService.read(pikachu.idAsInt), pikachu);
|
||||||
|
expect(await pokemonService.read(giratina.idAsInt), giratina);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('nonexistent throws 404', () {
|
||||||
|
expect(() => pokemonService.read(999),
|
||||||
|
throwsA(TypeMatcher<AngelHttpException>()));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('readMany', () async {
|
||||||
|
expect(pokemonService.readMany([giratina.idAsInt, pikachu.idAsInt]),
|
||||||
|
completion([giratina, pikachu]));
|
||||||
|
expect(
|
||||||
|
pokemonService.readMany([giratina.idAsInt]), completion([giratina]));
|
||||||
|
expect(pokemonService.readMany([pikachu.idAsInt]), completion([pikachu]));
|
||||||
|
expect(() => pokemonService.readMany([]), throwsArgumentError);
|
||||||
|
});
|
||||||
|
|
||||||
|
group('update', () {
|
||||||
|
test('default', () async {
|
||||||
|
expect(
|
||||||
|
await pokemonService.update(
|
||||||
|
giratina.idAsInt, giratina.copyWith(name: 'Hello')),
|
||||||
|
giratina.copyWith(name: 'Hello'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('nonexistent throws 404', () {
|
||||||
|
expect(
|
||||||
|
() => pokemonService.update(999, giratina.copyWith(name: 'Hello')),
|
||||||
|
throwsA(TypeMatcher<AngelHttpException>()));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('remove', () {
|
||||||
|
test('default', () async {
|
||||||
|
expect(pokemonService.read(giratina.idAsInt), completion(giratina));
|
||||||
|
expect(pokemonService.read(pikachu.idAsInt), completion(pikachu));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('nonexistent throws 404', () {
|
||||||
|
expect(() => pokemonService.remove(999),
|
||||||
|
throwsA(TypeMatcher<AngelHttpException>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('cannot remove all unless explicitly set', () async {
|
||||||
|
expect(() => pokemonService.remove(null, {'provider': Providers.rest}),
|
||||||
|
throwsA(TypeMatcher<AngelHttpException>()));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
33
angel_orm_service/test/pokemon.dart
Normal file
33
angel_orm_service/test/pokemon.dart
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import 'package:angel_migration/angel_migration.dart';
|
||||||
|
import 'package:angel_serialize/angel_serialize.dart';
|
||||||
|
import 'package:angel_orm/angel_orm.dart';
|
||||||
|
part 'pokemon.g.dart';
|
||||||
|
|
||||||
|
enum PokemonType {
|
||||||
|
fire,
|
||||||
|
grass,
|
||||||
|
water,
|
||||||
|
dragon,
|
||||||
|
poison,
|
||||||
|
dark,
|
||||||
|
fighting,
|
||||||
|
electric,
|
||||||
|
ghost
|
||||||
|
}
|
||||||
|
|
||||||
|
@serializable
|
||||||
|
@orm
|
||||||
|
abstract class _Pokemon extends Model {
|
||||||
|
@notNull
|
||||||
|
String get species;
|
||||||
|
|
||||||
|
String get name;
|
||||||
|
|
||||||
|
@notNull
|
||||||
|
int get level;
|
||||||
|
|
||||||
|
@notNull
|
||||||
|
PokemonType get type1;
|
||||||
|
|
||||||
|
PokemonType get type2;
|
||||||
|
}
|
405
angel_orm_service/test/pokemon.g.dart
Normal file
405
angel_orm_service/test/pokemon.g.dart
Normal file
|
@ -0,0 +1,405 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'pokemon.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// MigrationGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class PokemonMigration extends Migration {
|
||||||
|
@override
|
||||||
|
up(Schema schema) {
|
||||||
|
schema.create('pokemons', (table) {
|
||||||
|
table.serial('id')..primaryKey();
|
||||||
|
table.varChar('species');
|
||||||
|
table.varChar('name');
|
||||||
|
table.integer('level');
|
||||||
|
table.integer('type1');
|
||||||
|
table.integer('type2');
|
||||||
|
table.timeStamp('created_at');
|
||||||
|
table.timeStamp('updated_at');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
down(Schema schema) {
|
||||||
|
schema.drop('pokemons');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// OrmGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class PokemonQuery extends Query<Pokemon, PokemonQueryWhere> {
|
||||||
|
PokemonQuery({Set<String> trampoline}) {
|
||||||
|
trampoline ??= Set();
|
||||||
|
trampoline.add(tableName);
|
||||||
|
_where = PokemonQueryWhere(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
final PokemonQueryValues values = PokemonQueryValues();
|
||||||
|
|
||||||
|
PokemonQueryWhere _where;
|
||||||
|
|
||||||
|
@override
|
||||||
|
get casts {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
get tableName {
|
||||||
|
return 'pokemons';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
get fields {
|
||||||
|
return const [
|
||||||
|
'id',
|
||||||
|
'species',
|
||||||
|
'name',
|
||||||
|
'level',
|
||||||
|
'type1',
|
||||||
|
'type2',
|
||||||
|
'created_at',
|
||||||
|
'updated_at'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
PokemonQueryWhere get where {
|
||||||
|
return _where;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
PokemonQueryWhere newWhereClause() {
|
||||||
|
return PokemonQueryWhere(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Pokemon parseRow(List row) {
|
||||||
|
if (row.every((x) => x == null)) return null;
|
||||||
|
var model = Pokemon(
|
||||||
|
id: row[0].toString(),
|
||||||
|
species: (row[1] as String),
|
||||||
|
name: (row[2] as String),
|
||||||
|
level: (row[3] as int),
|
||||||
|
type1: row[4] == null ? null : PokemonType.values[(row[4] as int)],
|
||||||
|
type2: row[5] == null ? null : PokemonType.values[(row[5] as int)],
|
||||||
|
createdAt: (row[6] as DateTime),
|
||||||
|
updatedAt: (row[7] as DateTime));
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
deserialize(List row) {
|
||||||
|
return parseRow(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PokemonQueryWhere extends QueryWhere {
|
||||||
|
PokemonQueryWhere(PokemonQuery query)
|
||||||
|
: id = NumericSqlExpressionBuilder<int>(query, 'id'),
|
||||||
|
species = StringSqlExpressionBuilder(query, 'species'),
|
||||||
|
name = StringSqlExpressionBuilder(query, 'name'),
|
||||||
|
level = NumericSqlExpressionBuilder<int>(query, 'level'),
|
||||||
|
type1 = EnumSqlExpressionBuilder<PokemonType>(
|
||||||
|
query, 'type1', (v) => v.index),
|
||||||
|
type2 = EnumSqlExpressionBuilder<PokemonType>(
|
||||||
|
query, 'type2', (v) => v.index),
|
||||||
|
createdAt = DateTimeSqlExpressionBuilder(query, 'created_at'),
|
||||||
|
updatedAt = DateTimeSqlExpressionBuilder(query, 'updated_at');
|
||||||
|
|
||||||
|
final NumericSqlExpressionBuilder<int> id;
|
||||||
|
|
||||||
|
final StringSqlExpressionBuilder species;
|
||||||
|
|
||||||
|
final StringSqlExpressionBuilder name;
|
||||||
|
|
||||||
|
final NumericSqlExpressionBuilder<int> level;
|
||||||
|
|
||||||
|
final EnumSqlExpressionBuilder<PokemonType> type1;
|
||||||
|
|
||||||
|
final EnumSqlExpressionBuilder<PokemonType> type2;
|
||||||
|
|
||||||
|
final DateTimeSqlExpressionBuilder createdAt;
|
||||||
|
|
||||||
|
final DateTimeSqlExpressionBuilder updatedAt;
|
||||||
|
|
||||||
|
@override
|
||||||
|
get expressionBuilders {
|
||||||
|
return [id, species, name, level, type1, type2, createdAt, updatedAt];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PokemonQueryValues extends MapQueryValues {
|
||||||
|
@override
|
||||||
|
get casts {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
String get id {
|
||||||
|
return (values['id'] as String);
|
||||||
|
}
|
||||||
|
|
||||||
|
set id(String value) => values['id'] = value;
|
||||||
|
String get species {
|
||||||
|
return (values['species'] as String);
|
||||||
|
}
|
||||||
|
|
||||||
|
set species(String value) => values['species'] = value;
|
||||||
|
String get name {
|
||||||
|
return (values['name'] as String);
|
||||||
|
}
|
||||||
|
|
||||||
|
set name(String value) => values['name'] = value;
|
||||||
|
int get level {
|
||||||
|
return (values['level'] as int);
|
||||||
|
}
|
||||||
|
|
||||||
|
set level(int value) => values['level'] = value;
|
||||||
|
PokemonType get type1 {
|
||||||
|
return PokemonType.values[(values['type1'] as int)];
|
||||||
|
}
|
||||||
|
|
||||||
|
set type1(PokemonType value) => values['type1'] = value?.index;
|
||||||
|
PokemonType get type2 {
|
||||||
|
return PokemonType.values[(values['type2'] as int)];
|
||||||
|
}
|
||||||
|
|
||||||
|
set type2(PokemonType value) => values['type2'] = value?.index;
|
||||||
|
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(Pokemon model) {
|
||||||
|
species = model.species;
|
||||||
|
name = model.name;
|
||||||
|
level = model.level;
|
||||||
|
type1 = model.type1;
|
||||||
|
type2 = model.type2;
|
||||||
|
createdAt = model.createdAt;
|
||||||
|
updatedAt = model.updatedAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonModelGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
@generatedSerializable
|
||||||
|
class Pokemon extends _Pokemon {
|
||||||
|
Pokemon(
|
||||||
|
{this.id,
|
||||||
|
@required this.species,
|
||||||
|
this.name,
|
||||||
|
@required this.level,
|
||||||
|
@required this.type1,
|
||||||
|
this.type2,
|
||||||
|
this.createdAt,
|
||||||
|
this.updatedAt});
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String species;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final int level;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final PokemonType type1;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final PokemonType type2;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final DateTime createdAt;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final DateTime updatedAt;
|
||||||
|
|
||||||
|
Pokemon copyWith(
|
||||||
|
{String id,
|
||||||
|
String species,
|
||||||
|
String name,
|
||||||
|
int level,
|
||||||
|
PokemonType type1,
|
||||||
|
PokemonType type2,
|
||||||
|
DateTime createdAt,
|
||||||
|
DateTime updatedAt}) {
|
||||||
|
return new Pokemon(
|
||||||
|
id: id ?? this.id,
|
||||||
|
species: species ?? this.species,
|
||||||
|
name: name ?? this.name,
|
||||||
|
level: level ?? this.level,
|
||||||
|
type1: type1 ?? this.type1,
|
||||||
|
type2: type2 ?? this.type2,
|
||||||
|
createdAt: createdAt ?? this.createdAt,
|
||||||
|
updatedAt: updatedAt ?? this.updatedAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator ==(other) {
|
||||||
|
return other is _Pokemon &&
|
||||||
|
other.id == id &&
|
||||||
|
other.species == species &&
|
||||||
|
other.name == name &&
|
||||||
|
other.level == level &&
|
||||||
|
other.type1 == type1 &&
|
||||||
|
other.type2 == type2 &&
|
||||||
|
other.createdAt == createdAt &&
|
||||||
|
other.updatedAt == updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return hashObjects(
|
||||||
|
[id, species, name, level, type1, type2, createdAt, updatedAt]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return "Pokemon(id=$id, species=$species, name=$name, level=$level, type1=$type1, type2=$type2, createdAt=$createdAt, updatedAt=$updatedAt)";
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return PokemonSerializer.toMap(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// SerializerGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
const PokemonSerializer pokemonSerializer = const PokemonSerializer();
|
||||||
|
|
||||||
|
class PokemonEncoder extends Converter<Pokemon, Map> {
|
||||||
|
const PokemonEncoder();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map convert(Pokemon model) => PokemonSerializer.toMap(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PokemonDecoder extends Converter<Map, Pokemon> {
|
||||||
|
const PokemonDecoder();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Pokemon convert(Map map) => PokemonSerializer.fromMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PokemonSerializer extends Codec<Pokemon, Map> {
|
||||||
|
const PokemonSerializer();
|
||||||
|
|
||||||
|
@override
|
||||||
|
get encoder => const PokemonEncoder();
|
||||||
|
@override
|
||||||
|
get decoder => const PokemonDecoder();
|
||||||
|
static Pokemon fromMap(Map map) {
|
||||||
|
if (map['species'] == null) {
|
||||||
|
throw new FormatException("Missing required field 'species' on Pokemon.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map['level'] == null) {
|
||||||
|
throw new FormatException("Missing required field 'level' on Pokemon.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map['type1'] == null) {
|
||||||
|
throw new FormatException("Missing required field 'type1' on Pokemon.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Pokemon(
|
||||||
|
id: map['id'] as String,
|
||||||
|
species: map['species'] as String,
|
||||||
|
name: map['name'] as String,
|
||||||
|
level: map['level'] as int,
|
||||||
|
type1: map['type1'] is PokemonType
|
||||||
|
? (map['type1'] as PokemonType)
|
||||||
|
: (map['type1'] is int
|
||||||
|
? PokemonType.values[map['type1'] as int]
|
||||||
|
: null),
|
||||||
|
type2: map['type2'] is PokemonType
|
||||||
|
? (map['type2'] as PokemonType)
|
||||||
|
: (map['type2'] is int
|
||||||
|
? PokemonType.values[map['type2'] as int]
|
||||||
|
: null),
|
||||||
|
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<String, dynamic> toMap(_Pokemon model) {
|
||||||
|
if (model == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (model.species == null) {
|
||||||
|
throw new FormatException("Missing required field 'species' on Pokemon.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.level == null) {
|
||||||
|
throw new FormatException("Missing required field 'level' on Pokemon.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.type1 == null) {
|
||||||
|
throw new FormatException("Missing required field 'type1' on Pokemon.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': model.id,
|
||||||
|
'species': model.species,
|
||||||
|
'name': model.name,
|
||||||
|
'level': model.level,
|
||||||
|
'type1':
|
||||||
|
model.type1 == null ? null : PokemonType.values.indexOf(model.type1),
|
||||||
|
'type2':
|
||||||
|
model.type2 == null ? null : PokemonType.values.indexOf(model.type2),
|
||||||
|
'created_at': model.createdAt?.toIso8601String(),
|
||||||
|
'updated_at': model.updatedAt?.toIso8601String()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class PokemonFields {
|
||||||
|
static const List<String> allFields = <String>[
|
||||||
|
id,
|
||||||
|
species,
|
||||||
|
name,
|
||||||
|
level,
|
||||||
|
type1,
|
||||||
|
type2,
|
||||||
|
createdAt,
|
||||||
|
updatedAt
|
||||||
|
];
|
||||||
|
|
||||||
|
static const String id = 'id';
|
||||||
|
|
||||||
|
static const String species = 'species';
|
||||||
|
|
||||||
|
static const String name = 'name';
|
||||||
|
|
||||||
|
static const String level = 'level';
|
||||||
|
|
||||||
|
static const String type1 = 'type1';
|
||||||
|
|
||||||
|
static const String type2 = 'type2';
|
||||||
|
|
||||||
|
static const String createdAt = 'created_at';
|
||||||
|
|
||||||
|
static const String updatedAt = 'updated_at';
|
||||||
|
}
|
Loading…
Reference in a new issue