Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import 'package:moor/moor.dart';
- import 'package:moor/moor_vm.dart';
- import 'package:rxdart/rxdart.dart';
- part 'shopping_cart.g.dart';
- class ShoppingCarts extends Table {
- IntColumn get id => integer().autoIncrement()();
- }
- class BuyableItems extends Table {
- IntColumn get id => integer().autoIncrement()();
- // price, description, idk
- }
- @DataClassName('ShoppingCartEntry')
- class ShoppingCartEntries extends Table {
- IntColumn get shoppingCart => integer()();
- IntColumn get item => integer()();
- }
- class CartWithItems {
- final ShoppingCart cart;
- final List<BuyableItem> items;
- CartWithItems(this.cart, this.items);
- }
- @UseMoor(tables: [ShoppingCarts, BuyableItems, ShoppingCartEntries])
- class Database extends _$Database {
- @override
- final int schemaVersion = 1;
- Database(QueryExecutor e) : super(e);
- @override
- MigrationStrategy get migration {
- return MigrationStrategy(
- beforeOpen: (_, details) async {
- if (details.wasCreated) {
- // write some fake items
- for (var i = 0; i < 10; i++) {
- await into(buyableItems).insert(const BuyableItemsCompanion());
- }
- }
- },
- );
- }
- /// Create a new empty shopping cart
- Future<ShoppingCart> createShoppingCart() async {
- final id = await into(shoppingCarts).insert(const ShoppingCartsCompanion());
- return ShoppingCart(id: id);
- }
- Future<List<BuyableItem>> loadAllItems() async {
- return await select(buyableItems).get();
- }
- Stream<CartWithItems> watchCart(int id) {
- final cartQuery = select(shoppingCarts)
- ..where((cart) => cart.id.equals(id));
- final contentQuery = select(shoppingCartEntries).join(
- [
- innerJoin(
- buyableItems,
- buyableItems.id.equalsExp(shoppingCartEntries.item),
- ),
- ],
- )..where(shoppingCartEntries.shoppingCart.equals(id));
- final cartStream = cartQuery.watchSingle();
- final contentStream = contentQuery.watch().map((rows) {
- return rows.map((row) => row.readTable(buyableItems)).toList();
- });
- return Observable.combineLatest2(cartStream, contentStream,
- (ShoppingCart cart, List<BuyableItem> items) {
- return CartWithItems(cart, items);
- });
- }
- Stream<List<CartWithItems>> watchAllCarts() {
- // start by watching all carts
- final cartStream = Observable(select(shoppingCarts).watch());
- return cartStream.switchMap((carts) {
- // this method is called whenever the list of carts changes. For each
- // cart, we want to load all the items in it.
- // (we create a map from id to cart here just for performance reasons)
- final idToCart = {for (var cart in carts) cart.id: cart};
- final ids = idToCart.keys;
- // select all entries that are included in a cart that we found
- final entryQuery = select(shoppingCartEntries).join(
- [
- innerJoin(
- buyableItems,
- buyableItems.id.equalsExp(shoppingCartEntries.item),
- )
- ],
- )..where(isIn(shoppingCartEntries.shoppingCart, ids));
- return entryQuery.watch().map((rows) {
- // Store the list of entries for each cart, again using maps for faster
- // lookups.
- final idToItems = <int, List<BuyableItem>>{};
- // for each entry (row) that is included in a cart, put it in the map
- // of items.
- for (var row in rows) {
- final item = row.readTable(buyableItems);
- final id = row.readTable(shoppingCartEntries).shoppingCart;
- idToItems.putIfAbsent(id, () => []).add(item);
- }
- // finally, all that's left is to merge the map of carts with the map of
- // entries
- return [
- for (var id in ids)
- CartWithItems(idToCart[id], idToItems[id] ?? []),
- ];
- });
- });
- }
- Future<void> writeShoppingCart(CartWithItems entry) {
- return transaction((_) async {
- final cart = entry.cart;
- // first, we write the shopping cart
- await into(shoppingCarts).insert(cart, orReplace: true);
- // replace entries of the cart
- await (delete(shoppingCartEntries)
- ..where((entry) => entry.shoppingCart.equals(cart.id)))
- .go();
- await into(shoppingCartEntries).insertAll([
- for (var item in entry.items)
- ShoppingCartEntry(shoppingCart: cart.id, item: item.id),
- ]);
- });
- }
- }
- void main() async {
- final db = Database(VMDatabase.memory());
- final cart = await db.createShoppingCart();
- final availableItems = await db.loadAllItems();
- final sub = db.watchCart(cart.id).listen((updated) {
- print('Cart ${updated.cart} now consists of ${updated.items}');
- });
- await db.writeShoppingCart(CartWithItems(cart, availableItems.sublist(0, 3)));
- await db.writeShoppingCart(CartWithItems(cart, availableItems.sublist(3, 6)));
- await db.writeShoppingCart(CartWithItems(cart, availableItems.sublist(6)));
- await Future.delayed(const Duration(seconds: 2));
- await sub.cancel();
- await db.close();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement