Skip to content

Instantly share code, notes, and snippets.

@jaumard
Created July 1, 2019 14:08
Show Gist options
  • Save jaumard/5e777dbd1f2090a7d859061aa2165f5d to your computer and use it in GitHub Desktop.
Save jaumard/5e777dbd1f2090a7d859061aa2165f5d to your computer and use it in GitHub Desktop.
immutable jaguar models
import 'dart:io';
import 'package:jaguar_query_postgres/jaguar_query_postgres.dart';
import 'models.dart';
/// The adapter
final adapter = PgAdapter('postgres', username: 'postgres', password: 'postgres');
main() async {
// Create beans
await adapter.connect();
final cartBean = CartBean(adapter);
final cartItemBean = CartItemBean(adapter);
await cartItemBean.drop();
await cartBean.drop();
await cartBean.createTable(ifNotExists: true);
await cartItemBean.createTable(ifNotExists: true);
final cart = Cart(
extId: 1,
id: 3,
amount: 12,
items: [
CartItem(amount: 12, description: 'test'),
],
modified: 1);
final carts = await cartBean.getAll();
print(carts);
await cartBean.insert(cart, cascade: true);
final carts2 = await cartBean.getAll();
final preloadedCarts = await cartBean.preloadAll(carts2);
print(preloadedCarts);
await cartBean.update(Cart(
extId: preloadedCarts[0].extId,
id: preloadedCarts[0].id,
amount: preloadedCarts[0].amount,
items: [
CartItem(
id: preloadedCarts[0].items[0].id,
amount: 66,
quantity: preloadedCarts[0].items[0].quantity,
product: preloadedCarts[0].items[0].product,
description: preloadedCarts[0].items[0].description + ' updated',
cartId: preloadedCarts[0].items[0].cartId,
)
],
modified: 2,
), cascade: true);
final updatedCart = await cartBean.find(cart.extId, preload: true, cascade: true);
print(updatedCart);
exit(0);
}
import 'package:jaguar_query/jaguar_query.dart';
import 'package:jaguar_orm/jaguar_orm.dart';
part 'models.jorm.dart';
class Cart {
static const int currentCartId = 1;
@Column(isNullable: true)
final int id;
@PrimaryKey(isNullable: false)
final int extId;
@HasMany(CartItemBean)
final List<CartItem> items;
@Column()
final int amount;
@Column()
final int modified;
Cart({this.extId, this.amount = 0, this.id, this.modified, this.items = const <CartItem>[]});
Cart copy({id, extId, int amount, List<CartItem> items, modified, transactionId}) {
return Cart(
id: id ?? this.id,
extId: extId ?? this.extId,
modified: modified ?? this.modified,
amount: amount ?? this.amount,
items: items ?? this.items,
);
}
@override
String toString() {
return 'Cart{id: $id, extId: $extId, items: $items, amount: $amount, modified: $modified}';
}
}
class CartItem {
@PrimaryKey(auto: true)
final int id;
@Column()
final int amount;
@Column(isNullable: true)
final int product;
@Column()
final int quantity;
@Column(isNullable: true)
final String description;
@BelongsTo(CartBean, refCol: 'extId', byHasMany: true)
final int cartId;
CartItem({this.amount, this.quantity = 1, this.description, this.product, this.id, this.cartId});
CartItem copy({id, int cartId, String description, int quantity, int product, int amount}) {
return CartItem(
amount: amount ?? this.amount,
product: product ?? this.product,
quantity: quantity ?? this.quantity,
id: id ?? this.id,
description: description ?? this.description,
cartId: cartId ?? this.cartId,
);
}
@override
String toString() {
return 'CartItem{id: $id, amount: $amount, product: $product, quantity: $quantity, description: $description, cartId: $cartId}';
}
}
@GenBean()
class CartItemBean extends Bean<CartItem> with _CartItemBean {
CartItemBean(Adapter adapter) : super(adapter);
CartBean _cartBean;
@override
String get tableName => 'cartItem';
@override
CartBean get cartBean => _cartBean ??= CartBean(adapter);
}
@GenBean()
class CartBean extends Bean<Cart> with _CartBean {
CartBean(Adapter adapter) : super(adapter);
CartItemBean _cartItemBean;
@override
String get tableName => 'cart';
@override
CartItemBean get cartItemBean => _cartItemBean ??= CartItemBean(adapter);
}
part of 'models.dart';
abstract class _CartBean implements Bean<Cart> {
final id = IntField('id');
final extId = IntField('ext_id');
final amount = IntField('amount');
final modified = IntField('modified');
Map<String, Field> _fields;
Map<String, Field> get fields => _fields ??= {
id.name: id,
extId.name: extId,
amount.name: amount,
modified.name: modified,
};
Cart fromMap(Map map) {
Cart model = Cart(
id: adapter.parseValue(map['id']),
extId: adapter.parseValue(map['ext_id']),
amount: adapter.parseValue(map['amount']),
modified: adapter.parseValue(map['modified']),
);
return model;
}
List<SetColumn> toSetColumns(Cart model, {bool update = false, Set<String> only, bool onlyNonNull = false}) {
List<SetColumn> ret = [];
if (only == null && !onlyNonNull) {
ret.add(id.set(model.id));
ret.add(extId.set(model.extId));
ret.add(amount.set(model.amount));
ret.add(modified.set(model.modified));
} else if (only != null) {
if (only.contains(id.name)) ret.add(id.set(model.id));
if (only.contains(extId.name)) ret.add(extId.set(model.extId));
if (only.contains(amount.name)) ret.add(amount.set(model.amount));
if (only.contains(modified.name)) ret.add(modified.set(model.modified));
} else
/* if (onlyNonNull) */ {
if (model.id != null) {
ret.add(id.set(model.id));
}
if (model.extId != null) {
ret.add(extId.set(model.extId));
}
if (model.amount != null) {
ret.add(amount.set(model.amount));
}
if (model.modified != null) {
ret.add(modified.set(model.modified));
}
}
return ret;
}
Future<void> createTable({bool ifNotExists = false}) async {
final st = Sql.create(tableName, ifNotExists: ifNotExists);
st.addInt(id.name, isNullable: true);
st.addInt(extId.name, primary: true, isNullable: false);
st.addInt(amount.name, isNullable: false);
st.addInt(modified.name, isNullable: false);
return adapter.createTable(st);
}
Future<dynamic> insert(Cart model, {bool cascade = false, bool onlyNonNull = false, Set<String> only}) async {
final Insert insert = inserter.setMany(toSetColumns(model, only: only, onlyNonNull: onlyNonNull));
var retId = await adapter.insert(insert);
if (cascade) {
Cart newModel;
if (model.items != null) {
newModel ??= await find(model.extId);
final items = model.items.map((x) => cartItemBean.associateCart(x, newModel));
for (final child in items) {
await cartItemBean.insert(child, cascade: cascade);
}
}
}
return retId;
}
Future<void> insertMany(List<Cart> models, {bool cascade = false, bool onlyNonNull = false, Set<String> only}) async {
if (cascade) {
final List<Future> futures = [];
for (var model in models) {
futures.add(insert(model, cascade: cascade));
}
await Future.wait(futures);
return;
} else {
final List<List<SetColumn>> data = models.map((model) => toSetColumns(model, only: only, onlyNonNull: onlyNonNull)).toList();
final InsertMany insert = inserters.addAll(data);
await adapter.insertMany(insert);
return;
}
}
Future<dynamic> upsert(Cart model, {bool cascade = false, Set<String> only, bool onlyNonNull = false}) async {
final Upsert upsert = upserter.setMany(toSetColumns(model, only: only, onlyNonNull: onlyNonNull));
var retId = await adapter.upsert(upsert);
if (cascade) {
Cart newModel;
if (model.items != null) {
newModel ??= await find(model.extId);
final items = model.items.map((x) => cartItemBean.associateCart(x, newModel));
for (final child in items) {
await cartItemBean.upsert(child, cascade: cascade);
}
}
}
return retId;
}
Future<void> upsertMany(List<Cart> models, {bool cascade = false, bool onlyNonNull = false, Set<String> only}) async {
if (cascade) {
final List<Future> futures = [];
for (var model in models) {
futures.add(upsert(model, cascade: cascade));
}
await Future.wait(futures);
return;
} else {
final List<List<SetColumn>> data = [];
for (var i = 0; i < models.length; ++i) {
var model = models[i];
data.add(toSetColumns(model, only: only, onlyNonNull: onlyNonNull).toList());
}
final UpsertMany upsert = upserters.addAll(data);
await adapter.upsertMany(upsert);
return;
}
}
Future<int> update(Cart model, {bool cascade = false, bool associate = false, Set<String> only, bool onlyNonNull = false}) async {
final Update update = updater.where(this.extId.eq(model.extId)).setMany(toSetColumns(model, only: only, onlyNonNull: onlyNonNull));
final ret = adapter.update(update);
if (cascade) {
Cart newModel;
if (model.items != null) {
if (associate) {
newModel ??= await find(model.extId);
model.items.forEach((x) => cartItemBean.associateCart(x, newModel));
}
for (final child in model.items) {
await cartItemBean.update(child, cascade: cascade, associate: associate);
}
}
}
return ret;
}
Future<void> updateMany(List<Cart> models, {bool cascade = false, bool onlyNonNull = false, Set<String> only}) async {
if (cascade) {
final List<Future> futures = [];
for (var model in models) {
futures.add(update(model, cascade: cascade));
}
await Future.wait(futures);
return;
} else {
final List<List<SetColumn>> data = [];
final List<Expression> where = [];
for (var i = 0; i < models.length; ++i) {
var model = models[i];
data.add(toSetColumns(model, only: only, onlyNonNull: onlyNonNull).toList());
where.add(this.extId.eq(model.extId));
}
final UpdateMany update = updaters.addAll(data, where);
await adapter.updateMany(update);
return;
}
}
Future<Cart> find(int extId, {bool preload = false, bool cascade = false}) async {
final Find find = finder.where(this.extId.eq(extId));
Cart model = await findOne(find);
if (preload && model != null) {
model = await this.preload(model, cascade: cascade);
}
return model;
}
Future<int> remove(int extId, {bool cascade = false}) async {
if (cascade) {
final Cart newModel = await find(extId);
if (newModel != null) {
await cartItemBean.removeByCart(newModel.extId);
}
}
final Remove remove = remover.where(this.extId.eq(extId));
return adapter.remove(remove);
}
Future<int> removeMany(List<Cart> models) async {
// Return if models is empty. If this is not done, all records will be removed!
if (models == null || models.isEmpty) return 0;
final Remove remove = remover;
for (final model in models) {
remove.or(this.extId.eq(model.extId));
}
return adapter.remove(remove);
}
Future<Cart> preload(Cart model, {bool cascade = false}) async {
final items = await cartItemBean.findByCart(model.extId, preload: cascade, cascade: cascade);
return Cart(
items: items,
extId: model.extId,
id: model.id,
amount: model.amount,
modified: model.modified,
);
}
Future<List<Cart>> preloadAll(List<Cart> models, {bool cascade = false}) async {
List<Cart> preloadedModels = [];
await OneToXHelper.preloadAll<Cart, CartItem>(
models,
(Cart model) => [model.extId],
cartItemBean.findByCartList,
(CartItem model) => [model.cartId],
(Cart model, CartItem child) {
preloadedModels.add(Cart(
items: List.from(model.items)..add(child),
extId: model.extId,
id: model.id,
amount: model.amount,
modified: model.modified,
));
},
cascade: cascade);
return preloadedModels;
}
CartItemBean get cartItemBean;
}
abstract class _CartItemBean implements Bean<CartItem> {
final id = IntField('id');
final amount = IntField('amount');
final product = IntField('product');
final quantity = IntField('quantity');
final description = StrField('description');
final cartId = IntField('cart_id');
Map<String, Field> _fields;
Map<String, Field> get fields => _fields ??= {
id.name: id,
amount.name: amount,
product.name: product,
quantity.name: quantity,
description.name: description,
cartId.name: cartId,
};
CartItem fromMap(Map map) {
CartItem model = CartItem(
id: adapter.parseValue(map['id']),
amount: adapter.parseValue(map['amount']),
product: adapter.parseValue(map['product']),
quantity: adapter.parseValue(map['quantity']),
description: adapter.parseValue(map['description']),
cartId: adapter.parseValue(map['cart_id']));
return model;
}
List<SetColumn> toSetColumns(CartItem model, {bool update = false, Set<String> only, bool onlyNonNull = false}) {
List<SetColumn> ret = [];
if (only == null && !onlyNonNull) {
if (model.id != null) {
ret.add(id.set(model.id));
}
ret.add(amount.set(model.amount));
ret.add(product.set(model.product));
ret.add(quantity.set(model.quantity));
ret.add(description.set(model.description));
ret.add(cartId.set(model.cartId));
} else if (only != null) {
if (model.id != null) {
if (only.contains(id.name)) ret.add(id.set(model.id));
}
if (only.contains(amount.name)) ret.add(amount.set(model.amount));
if (only.contains(product.name)) ret.add(product.set(model.product));
if (only.contains(quantity.name)) ret.add(quantity.set(model.quantity));
if (only.contains(description.name)) ret.add(description.set(model.description));
if (only.contains(cartId.name)) ret.add(cartId.set(model.cartId));
} else
/* if (onlyNonNull) */ {
if (model.id != null) {
ret.add(id.set(model.id));
}
if (model.amount != null) {
ret.add(amount.set(model.amount));
}
if (model.product != null) {
ret.add(product.set(model.product));
}
if (model.quantity != null) {
ret.add(quantity.set(model.quantity));
}
if (model.description != null) {
ret.add(description.set(model.description));
}
if (model.cartId != null) {
ret.add(cartId.set(model.cartId));
}
}
return ret;
}
Future<void> createTable({bool ifNotExists = false}) async {
final st = Sql.create(tableName, ifNotExists: ifNotExists);
st.addInt(id.name, primary: true, autoIncrement: true, isNullable: false);
st.addInt(amount.name, isNullable: false);
st.addInt(product.name, isNullable: true);
st.addInt(quantity.name, isNullable: false);
st.addStr(description.name, isNullable: true);
st.addInt(cartId.name, foreignTable: cartBean.tableName, foreignCol: 'ext_id', isNullable: false);
return adapter.createTable(st);
}
Future<dynamic> insert(CartItem model, {bool cascade = false, bool onlyNonNull = false, Set<String> only}) async {
final Insert insert = inserter.setMany(toSetColumns(model, only: only, onlyNonNull: onlyNonNull)).id(id.name);
var retId = await adapter.insert(insert);
return retId;
}
Future<void> insertMany(List<CartItem> models, {bool onlyNonNull = false, Set<String> only}) async {
final List<List<SetColumn>> data = models.map((model) => toSetColumns(model, only: only, onlyNonNull: onlyNonNull)).toList();
final InsertMany insert = inserters.addAll(data);
await adapter.insertMany(insert);
return;
}
Future<dynamic> upsert(CartItem model, {bool cascade = false, Set<String> only, bool onlyNonNull = false}) async {
final Upsert upsert = upserter.setMany(toSetColumns(model, only: only, onlyNonNull: onlyNonNull)).id(id.name);
var retId = await adapter.upsert(upsert);
return retId;
}
Future<void> upsertMany(List<CartItem> models, {bool onlyNonNull = false, Set<String> only}) async {
final List<List<SetColumn>> data = [];
for (var i = 0; i < models.length; ++i) {
var model = models[i];
data.add(toSetColumns(model, only: only, onlyNonNull: onlyNonNull).toList());
}
final UpsertMany upsert = upserters.addAll(data);
await adapter.upsertMany(upsert);
return;
}
Future<int> update(CartItem model, {bool cascade = false, bool associate = false, Set<String> only, bool onlyNonNull = false}) async {
final Update update = updater.where(this.id.eq(model.id)).setMany(toSetColumns(model, only: only, onlyNonNull: onlyNonNull));
return adapter.update(update);
}
Future<void> updateMany(List<CartItem> models, {bool onlyNonNull = false, Set<String> only}) async {
final List<List<SetColumn>> data = [];
final List<Expression> where = [];
for (var i = 0; i < models.length; ++i) {
var model = models[i];
data.add(toSetColumns(model, only: only, onlyNonNull: onlyNonNull).toList());
where.add(this.id.eq(model.id));
}
final UpdateMany update = updaters.addAll(data, where);
await adapter.updateMany(update);
return;
}
Future<CartItem> find(int id, {bool preload = false, bool cascade = false}) async {
final Find find = finder.where(this.id.eq(id));
return await findOne(find);
}
Future<int> remove(int id) async {
final Remove remove = remover.where(this.id.eq(id));
return adapter.remove(remove);
}
Future<int> removeMany(List<CartItem> models) async {
// Return if models is empty. If this is not done, all records will be removed!
if (models == null || models.isEmpty) return 0;
final Remove remove = remover;
for (final model in models) {
remove.or(this.id.eq(model.id));
}
return adapter.remove(remove);
}
Future<List<CartItem>> findByCart(int cartId, {bool preload = false, bool cascade = false}) async {
final Find find = finder.where(this.cartId.eq(cartId));
return findMany(find);
}
Future<List<CartItem>> findByCartList(List<Cart> models, {bool preload = false, bool cascade = false}) async {
// Return if models is empty. If this is not done, all the records will be returned!
if (models == null || models.isEmpty) return [];
final Find find = finder;
for (Cart model in models) {
find.or(this.cartId.eq(model.extId));
}
return findMany(find);
}
Future<int> removeByCart(int cartId) async {
final Remove rm = remover.where(this.cartId.eq(cartId));
return await adapter.remove(rm);
}
CartItem associateCart(CartItem child, Cart parent) {
return CartItem(
cartId: parent.extId,
description: child.description,
product: child.product,
amount: child.amount,
id: child.id,
quantity: child.quantity,
);
}
CartBean get cartBean;
}
name: jaguar_test
description: Test
version: 1.0.0
environment:
sdk: '>=2.2.0 <3.0.0'
dependencies:
jaguar_query_postgres: ^2.2.6
dev_dependencies:
build_runner: 1.1.2
jaguar_orm_gen: ^2.2.27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment