Custom constructor excludes

This commit is contained in:
Tobe O 2018-05-13 13:23:40 -04:00
parent 7c1735c113
commit cf0a7eb652
9 changed files with 177 additions and 1 deletions

View file

@ -14,6 +14,7 @@ the time you spend writing boilerplate serialization code for your models.
* [Nesting](#nesting)
* [ID and Date Fields](#id-and-dates)
* [TypeScript Definition Generator](#typescript-definitions)
* [Constructor Parameters](#constructor-parameters)
# Usage
In your `pubspec.yaml`, you need to install the following dependencies:
@ -252,4 +253,42 @@ interface BookCollection {
Fields with an `@Exclude()` that specifies `canSerialize: false` will not be present in the
TypeScript definition. The rationale for this is that if a field (i.e. `password`) will
never be sent to the client, the client shouldn't even know the field exists.
never be sent to the client, the client shouldn't even know the field exists.
# Constructor Parameters
Sometimes, you may need to have custom constructor parameters, for example, when
using depedency injection frameworks. For these cases, `angel_serialize` can forward
custom constructor parameters.
The following:
```dart
@serializable
abstract class _Bookmark extends _BookmarkBase {
@exclude
final Book book;
int get page;
String get comment;
_Bookmark(this.book);
}
```
Generates:
```dart
class Bookmark extends _Bookmark {
Bookmark(Book book,
{this.id,
this.page,
this.comment,
this.createdAt,
this.updatedAt})
: super(book);
@override
final String id;
// ...
}
```

View file

@ -1,5 +1,6 @@
# 2.0.6
* Support for using `abstract` to create immutable model classes.
* Add support for custom constructor parameters.
# 2.0.5
* Deserialization now supports un-serialized `DateTime`.

View file

@ -102,6 +102,9 @@ Future<BuildContext> buildContext(
}
}
// Get constructor params, if any
ctx.constructorParameters.addAll(clazz.unnamedConstructor.parameters);
return ctx;
}

View file

@ -25,6 +25,8 @@ class BuildContext {
/// The fields declared on the original class.
final List<FieldElement> fields = [];
final List<ParameterElement> constructorParameters = [];
final ConstantReader annotation;
/// The name of the field that identifies data of this model type.

View file

@ -61,6 +61,18 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
void generateConstructor(
BuildContext ctx, ClassBuilder clazz, LibraryBuilder file) {
clazz.constructors.add(new Constructor((constructor) {
// Add all `super` params
if (ctx.constructorParameters.isNotEmpty) {
for (var param in ctx.constructorParameters) {
constructor.requiredParameters.add(new Parameter((b) => b
..name = param.name
..type = convertTypeReference(param.type)));
}
constructor.initializers.add(new Code(
'super(${ctx.constructorParameters.map((p) => p.name).join(',')})'));
}
for (var field in ctx.fields) {
constructor.optionalParameters.add(new Parameter((b) {
b
@ -79,10 +91,24 @@ class JsonModelGenerator extends GeneratorForAnnotation<Serializable> {
method
..name = 'copyWith'
..returns = ctx.modelClassType;
// Add all `super` params
if (ctx.constructorParameters.isNotEmpty) {
for (var param in ctx.constructorParameters) {
method.requiredParameters.add(new Parameter((b) => b
..name = param.name
..type = convertTypeReference(param.type)));
}
}
var buf = new StringBuffer('return new ${ctx.modelClassName}(');
int i = 0;
for (var param in ctx.constructorParameters) {
if (i++ > 0) buf.write(', ');
buf.write(param.name);
}
// Add named parameters
for (var field in ctx.fields) {
method.optionalParameters.add(new Parameter((b) {

View file

@ -125,9 +125,23 @@ class SerializerGenerator extends GeneratorForAnnotation<Serializable> {
..type = new Reference('Map')),
);
// Add all `super` params
if (ctx.constructorParameters.isNotEmpty) {
for (var param in ctx.constructorParameters) {
method.requiredParameters.add(new Parameter((b) => b
..name = param.name
..type = convertTypeReference(param.type)));
}
}
var buf = new StringBuffer('return new ${ctx.modelClassName}(');
int i = 0;
for (var param in ctx.constructorParameters) {
if (i++ > 0) buf.write(', ');
buf.write(param.name);
}
for (var field in ctx.fields) {
if (ctx.excluded[field.name]?.canDeserialize == false) continue;

View file

@ -26,3 +26,14 @@ abstract class _Author extends Model {
abstract class _Library extends Model {
Map<String, Book> get collection;
}
@serializable
abstract class _Bookmark extends Model {
@exclude
final Book book;
int get page;
String get comment;
_Bookmark(this.book);
}

View file

@ -103,3 +103,42 @@ class Library extends _Library {
return LibrarySerializer.toMap(this);
}
}
class Bookmark extends _Bookmark {
Bookmark(Book book,
{this.id, this.page, this.comment, this.createdAt, this.updatedAt})
: super(book);
@override
final String id;
@override
final int page;
@override
final String comment;
@override
final DateTime createdAt;
@override
final DateTime updatedAt;
Bookmark copyWith(Book book,
{String id,
int page,
String comment,
DateTime createdAt,
DateTime updatedAt}) {
return new Bookmark(book,
id: id ?? this.id,
page: page ?? this.page,
comment: comment ?? this.comment,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt);
}
Map<String, dynamic> toJson() {
return BookmarkSerializer.toMap(this);
}
}

View file

@ -107,3 +107,44 @@ abstract class LibraryFields {
static const String updatedAt = 'updated_at';
}
abstract class BookmarkSerializer {
static Bookmark fromMap(Map map, Book book) {
return new Bookmark(book,
id: map['id'],
page: map['page'],
comment: map['comment'],
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? map['created_at']
: DateTime.parse(map['created_at']))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? map['updated_at']
: DateTime.parse(map['updated_at']))
: null);
}
static Map<String, dynamic> toMap(Bookmark model) {
return {
'id': model.id,
'page': model.page,
'comment': model.comment,
'created_at': model.createdAt?.toIso8601String(),
'updated_at': model.updatedAt?.toIso8601String()
};
}
}
abstract class BookmarkFields {
static const String id = 'id';
static const String page = 'page';
static const String comment = 'comment';
static const String createdAt = 'created_at';
static const String updatedAt = 'updated_at';
}