Backwards compatibility: Use DataClasses as companion

This commit is contained in:
Simon Binder 2019-06-21 09:42:10 +02:00
parent ec2592203c
commit b79611e6e0
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
5 changed files with 221 additions and 56 deletions

View File

@ -7,7 +7,7 @@ part of 'example.dart';
// **************************************************************************
// ignore_for_file: unnecessary_brace_in_string_interps
class Category extends DataClass {
class Category extends DataClass with DelegatingCompanionMixin<Category> {
final int id;
final String description;
Category({this.id, this.description});
@ -38,6 +38,16 @@ class Category extends DataClass {
};
}
@override
UpdateCompanion<Category> createCompanion(bool nullToAbsent) {
return CategoriesCompanion(
id: id == null && nullToAbsent ? const Value.absent() : Value.use(id),
description: description == null && nullToAbsent
? const Value.absent()
: Value.use(description),
);
}
Category copyWith({int id, String description}) => Category(
id: id ?? this.id,
description: description ?? this.description,
@ -63,11 +73,11 @@ class CategoriesCompanion implements UpdateCompanion<Category> {
final Value<int> id;
final Value<String> description;
const CategoriesCompanion({
this.id = Value.absent(),
this.description = Value.absent(),
this.id = const Value.absent(),
this.description = const Value.absent(),
});
@override
bool isValuePresent(int index) {
bool isValuePresent(int index, bool _) {
switch (index) {
case 0:
return id.present;
@ -151,7 +161,7 @@ class $CategoriesTable extends Categories
}
}
class Recipe extends DataClass {
class Recipe extends DataClass with DelegatingCompanionMixin<Recipe> {
final int id;
final String title;
final String instructions;
@ -192,6 +202,22 @@ class Recipe extends DataClass {
};
}
@override
UpdateCompanion<Recipe> createCompanion(bool nullToAbsent) {
return RecipesCompanion(
id: id == null && nullToAbsent ? const Value.absent() : Value.use(id),
title: title == null && nullToAbsent
? const Value.absent()
: Value.use(title),
instructions: instructions == null && nullToAbsent
? const Value.absent()
: Value.use(instructions),
category: category == null && nullToAbsent
? const Value.absent()
: Value.use(category),
);
}
Recipe copyWith({int id, String title, String instructions, int category}) =>
Recipe(
id: id ?? this.id,
@ -231,13 +257,13 @@ class RecipesCompanion implements UpdateCompanion<Recipe> {
final Value<String> instructions;
final Value<int> category;
const RecipesCompanion({
this.id = Value.absent(),
this.title = Value.absent(),
this.instructions = Value.absent(),
this.category = Value.absent(),
this.id = const Value.absent(),
this.title = const Value.absent(),
this.instructions = const Value.absent(),
this.category = const Value.absent(),
});
@override
bool isValuePresent(int index) {
bool isValuePresent(int index, bool _) {
switch (index) {
case 0:
return id.present;
@ -356,7 +382,7 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
}
}
class Ingredient extends DataClass {
class Ingredient extends DataClass with DelegatingCompanionMixin<Ingredient> {
final int id;
final String name;
final int caloriesPer100g;
@ -391,6 +417,18 @@ class Ingredient extends DataClass {
};
}
@override
UpdateCompanion<Ingredient> createCompanion(bool nullToAbsent) {
return IngredientsCompanion(
id: id == null && nullToAbsent ? const Value.absent() : Value.use(id),
name:
name == null && nullToAbsent ? const Value.absent() : Value.use(name),
caloriesPer100g: caloriesPer100g == null && nullToAbsent
? const Value.absent()
: Value.use(caloriesPer100g),
);
}
Ingredient copyWith({int id, String name, int caloriesPer100g}) => Ingredient(
id: id ?? this.id,
name: name ?? this.name,
@ -423,12 +461,12 @@ class IngredientsCompanion implements UpdateCompanion<Ingredient> {
final Value<String> name;
final Value<int> caloriesPer100g;
const IngredientsCompanion({
this.id = Value.absent(),
this.name = Value.absent(),
this.caloriesPer100g = Value.absent(),
this.id = const Value.absent(),
this.name = const Value.absent(),
this.caloriesPer100g = const Value.absent(),
});
@override
bool isValuePresent(int index) {
bool isValuePresent(int index, bool _) {
switch (index) {
case 0:
return id.present;
@ -532,7 +570,8 @@ class $IngredientsTable extends Ingredients
}
}
class IngredientInRecipe extends DataClass {
class IngredientInRecipe extends DataClass
with DelegatingCompanionMixin<IngredientInRecipe> {
final int recipe;
final int ingredient;
final int amountInGrams;
@ -568,6 +607,21 @@ class IngredientInRecipe extends DataClass {
};
}
@override
UpdateCompanion<IngredientInRecipe> createCompanion(bool nullToAbsent) {
return IngredientInRecipesCompanion(
recipe: recipe == null && nullToAbsent
? const Value.absent()
: Value.use(recipe),
ingredient: ingredient == null && nullToAbsent
? const Value.absent()
: Value.use(ingredient),
amountInGrams: amountInGrams == null && nullToAbsent
? const Value.absent()
: Value.use(amountInGrams),
);
}
IngredientInRecipe copyWith(
{int recipe, int ingredient, int amountInGrams}) =>
IngredientInRecipe(
@ -604,12 +658,12 @@ class IngredientInRecipesCompanion
final Value<int> ingredient;
final Value<int> amountInGrams;
const IngredientInRecipesCompanion({
this.recipe = Value.absent(),
this.ingredient = Value.absent(),
this.amountInGrams = Value.absent(),
this.recipe = const Value.absent(),
this.ingredient = const Value.absent(),
this.amountInGrams = const Value.absent(),
});
@override
bool isValuePresent(int index) {
bool isValuePresent(int index, bool _) {
switch (index) {
case 0:
return recipe.present;

View File

@ -5,7 +5,7 @@ import 'package:moor/moor.dart';
/// A common supertype for all data classes generated by moor. Data classes are
/// immutable structures that represent a single row in a database table.
abstract class DataClass implements UpdateCompanion {
abstract class DataClass {
const DataClass();
/// Converts this object into a representation that can be encoded with
@ -21,9 +21,6 @@ abstract class DataClass implements UpdateCompanion {
return json.encode(toJson(serializer: serializer));
}
@override
bool isValuePresent(int index) => true;
/// Used internally be generated code
@protected
static dynamic parseJson(String jsonString) {
@ -40,8 +37,37 @@ abstract class UpdateCompanion<D extends DataClass> {
/// Used internally by moor.
///
/// Returns true if the column at the position [index] has been explicitly
/// set to a value.
bool isValuePresent(int index);
/// set to a value. The [assumeNullAsAbsent] parameter exists for backwards
/// compatibility reasons, as [DataClass] implements [UpdateCompanion] but
/// doesn't have value fields.
bool isValuePresent(int index, bool assumeNullAsAbsent);
}
/// Used internally by moor for generated code.
///
/// Exists for backwards compatibility so that a [DataClass] can implement
/// [UpdateCompanion].
mixin DelegatingCompanionMixin<D extends DataClass>
implements UpdateCompanion<D> {
UpdateCompanion<D> _absent;
UpdateCompanion<D> _present;
@visibleForOverriding
UpdateCompanion<D> createCompanion(bool nullToAbsent);
UpdateCompanion<D> _resolveDelegate(bool nullToAbsent) {
if (nullToAbsent) {
return _absent ??= createCompanion(true);
} else {
return _present ??= createCompanion(false);
}
}
@override
bool isValuePresent(int index, bool assumeNullAsAbsent) {
final delegate = _resolveDelegate(assumeNullAsAbsent);
return delegate.isValuePresent(index, assumeNullAsAbsent);
}
}
/// A wrapper around arbitrary data [T] to indicate presence or absence

View File

@ -7,7 +7,7 @@ part of 'todos.dart';
// **************************************************************************
// ignore_for_file: unnecessary_brace_in_string_interps
class TodoEntry extends DataClass {
class TodoEntry extends DataClass with DelegatingCompanionMixin<TodoEntry> {
final int id;
final String title;
final String content;
@ -55,6 +55,25 @@ class TodoEntry extends DataClass {
};
}
@override
UpdateCompanion<TodoEntry> createCompanion(bool nullToAbsent) {
return TodosTableCompanion(
id: id == null && nullToAbsent ? const Value.absent() : Value.use(id),
title: title == null && nullToAbsent
? const Value.absent()
: Value.use(title),
content: content == null && nullToAbsent
? const Value.absent()
: Value.use(content),
targetDate: targetDate == null && nullToAbsent
? const Value.absent()
: Value.use(targetDate),
category: category == null && nullToAbsent
? const Value.absent()
: Value.use(category),
);
}
TodoEntry copyWith(
{int id,
String title,
@ -104,14 +123,14 @@ class TodosTableCompanion implements UpdateCompanion<TodoEntry> {
final Value<DateTime> targetDate;
final Value<int> category;
const TodosTableCompanion({
this.id = Value.absent(),
this.title = Value.absent(),
this.content = Value.absent(),
this.targetDate = Value.absent(),
this.category = Value.absent(),
this.id = const Value.absent(),
this.title = const Value.absent(),
this.content = const Value.absent(),
this.targetDate = const Value.absent(),
this.category = const Value.absent(),
});
@override
bool isValuePresent(int index) {
bool isValuePresent(int index, bool _) {
switch (index) {
case 0:
return id.present;
@ -253,7 +272,7 @@ class $TodosTableTable extends TodosTable
}
}
class Category extends DataClass {
class Category extends DataClass with DelegatingCompanionMixin<Category> {
final int id;
final String description;
Category({this.id, this.description});
@ -284,6 +303,16 @@ class Category extends DataClass {
};
}
@override
UpdateCompanion<Category> createCompanion(bool nullToAbsent) {
return CategoriesCompanion(
id: id == null && nullToAbsent ? const Value.absent() : Value.use(id),
description: description == null && nullToAbsent
? const Value.absent()
: Value.use(description),
);
}
Category copyWith({int id, String description}) => Category(
id: id ?? this.id,
description: description ?? this.description,
@ -309,11 +338,11 @@ class CategoriesCompanion implements UpdateCompanion<Category> {
final Value<int> id;
final Value<String> description;
const CategoriesCompanion({
this.id = Value.absent(),
this.description = Value.absent(),
this.id = const Value.absent(),
this.description = const Value.absent(),
});
@override
bool isValuePresent(int index) {
bool isValuePresent(int index, bool _) {
switch (index) {
case 0:
return id.present;
@ -394,7 +423,7 @@ class $CategoriesTable extends Categories
}
}
class User extends DataClass {
class User extends DataClass with DelegatingCompanionMixin<User> {
final int id;
final String name;
final bool isAwesome;
@ -447,6 +476,24 @@ class User extends DataClass {
};
}
@override
UpdateCompanion<User> createCompanion(bool nullToAbsent) {
return UsersCompanion(
id: id == null && nullToAbsent ? const Value.absent() : Value.use(id),
name:
name == null && nullToAbsent ? const Value.absent() : Value.use(name),
isAwesome: isAwesome == null && nullToAbsent
? const Value.absent()
: Value.use(isAwesome),
profilePicture: profilePicture == null && nullToAbsent
? const Value.absent()
: Value.use(profilePicture),
creationTime: creationTime == null && nullToAbsent
? const Value.absent()
: Value.use(creationTime),
);
}
User copyWith(
{int id,
String name,
@ -497,14 +544,14 @@ class UsersCompanion implements UpdateCompanion<User> {
final Value<Uint8List> profilePicture;
final Value<DateTime> creationTime;
const UsersCompanion({
this.id = Value.absent(),
this.name = Value.absent(),
this.isAwesome = Value.absent(),
this.profilePicture = Value.absent(),
this.creationTime = Value.absent(),
this.id = const Value.absent(),
this.name = const Value.absent(),
this.isAwesome = const Value.absent(),
this.profilePicture = const Value.absent(),
this.creationTime = const Value.absent(),
});
@override
bool isValuePresent(int index) {
bool isValuePresent(int index, bool _) {
switch (index) {
case 0:
return id.present;
@ -642,7 +689,7 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
}
}
class SharedTodo extends DataClass {
class SharedTodo extends DataClass with DelegatingCompanionMixin<SharedTodo> {
final int todo;
final int user;
SharedTodo({this.todo, this.user});
@ -671,6 +718,16 @@ class SharedTodo extends DataClass {
};
}
@override
UpdateCompanion<SharedTodo> createCompanion(bool nullToAbsent) {
return SharedTodosCompanion(
todo:
todo == null && nullToAbsent ? const Value.absent() : Value.use(todo),
user:
user == null && nullToAbsent ? const Value.absent() : Value.use(user),
);
}
SharedTodo copyWith({int todo, int user}) => SharedTodo(
todo: todo ?? this.todo,
user: user ?? this.user,
@ -696,11 +753,11 @@ class SharedTodosCompanion implements UpdateCompanion<SharedTodo> {
final Value<int> todo;
final Value<int> user;
const SharedTodosCompanion({
this.todo = Value.absent(),
this.user = Value.absent(),
this.todo = const Value.absent(),
this.user = const Value.absent(),
});
@override
bool isValuePresent(int index) {
bool isValuePresent(int index, bool _) {
switch (index) {
case 0:
return todo.present;
@ -785,7 +842,8 @@ class $SharedTodosTable extends SharedTodos
}
}
class TableWithoutPKData extends DataClass {
class TableWithoutPKData extends DataClass
with DelegatingCompanionMixin<TableWithoutPKData> {
final int notReallyAnId;
final double someFloat;
TableWithoutPKData({this.notReallyAnId, this.someFloat});
@ -818,6 +876,18 @@ class TableWithoutPKData extends DataClass {
};
}
@override
UpdateCompanion<TableWithoutPKData> createCompanion(bool nullToAbsent) {
return TableWithoutPKCompanion(
notReallyAnId: notReallyAnId == null && nullToAbsent
? const Value.absent()
: Value.use(notReallyAnId),
someFloat: someFloat == null && nullToAbsent
? const Value.absent()
: Value.use(someFloat),
);
}
TableWithoutPKData copyWith({int notReallyAnId, double someFloat}) =>
TableWithoutPKData(
notReallyAnId: notReallyAnId ?? this.notReallyAnId,
@ -847,11 +917,11 @@ class TableWithoutPKCompanion implements UpdateCompanion<TableWithoutPKData> {
final Value<int> notReallyAnId;
final Value<double> someFloat;
const TableWithoutPKCompanion({
this.notReallyAnId = Value.absent(),
this.someFloat = Value.absent(),
this.notReallyAnId = const Value.absent(),
this.someFloat = const Value.absent(),
});
@override
bool isValuePresent(int index) {
bool isValuePresent(int index, bool _) {
switch (index) {
case 0:
return notReallyAnId.present;

View File

@ -12,7 +12,8 @@ class DataClassWriter {
DataClassWriter(this.table, this.options);
void writeInto(StringBuffer buffer) {
buffer.write('class ${table.dartTypeName} extends DataClass {\n');
buffer.write('class ${table.dartTypeName} extends DataClass '
'with DelegatingCompanionMixin<${table.dartTypeName}> {\n');
// write individual fields
for (var column in table.columns) {
@ -34,12 +35,12 @@ class DataClassWriter {
// And a serializer and deserializer method
_writeFromJson(buffer);
_writeToJson(buffer);
_writeCompanionOverride(buffer);
// And a convenience method to copy data from this class.
_writeCopyWith(buffer);
_writeToString(buffer);
_writeHashCode(buffer);
// override ==
@ -217,6 +218,20 @@ class DataClassWriter {
}
}
void _writeCompanionOverride(StringBuffer buffer) {
// UpdateCompanion<D> createCompanion(bool nullToAbsent);
buffer.write('@override\nUpdateCompanion<${table.dartTypeName}> '
'createCompanion(bool nullToAbsent) {\n'
'return ${table.updateCompanionName}(');
for (var column in table.columns) {
final getter = column.dartGetterName;
buffer.write('$getter: $getter == null && nullToAbsent ? '
'const Value.absent() : Value.use($getter),');
}
buffer.write(');}\n');
}
/// Recursively creates the implementation for hashCode of the data class,
/// assuming it has at least one field. When it has one field, we just return
/// the hash code of that field. Otherwise, we multiply it with 31 and add

View File

@ -28,7 +28,7 @@ class UpdateCompanionWriter {
buffer.write('const ${table.updateCompanionName}({');
for (var column in table.columns) {
buffer.write('this.${column.dartGetterName} = Value.absent(),');
buffer.write('this.${column.dartGetterName} = const Value.absent(),');
}
buffer.write('});\n');
@ -36,7 +36,7 @@ class UpdateCompanionWriter {
void _writeIsPresentOverride(StringBuffer buffer) {
buffer
..write('@override\nbool isValuePresent(int index) {\n')
..write('@override\nbool isValuePresent(int index, bool _) {\n')
..write('switch (index) {');
for (var i = 0; i < table.columns.length; i++) {