SHARE
TWEET

Untitled

a guest Aug 20th, 2019 93 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import 'package:moor/moor.dart';
  2. import 'package:moor/moor_vm.dart';
  3. import 'package:rxdart/rxdart.dart';
  4.  
  5. part 'shopping_cart.g.dart';
  6.  
  7. class ShoppingCarts extends Table {
  8.   IntColumn get id => integer().autoIncrement()();
  9. }
  10.  
  11. class BuyableItems extends Table {
  12.   IntColumn get id => integer().autoIncrement()();
  13. // price, description, idk
  14. }
  15.  
  16. @DataClassName('ShoppingCartEntry')
  17. class ShoppingCartEntries extends Table {
  18.   IntColumn get shoppingCart => integer()();
  19.   IntColumn get item => integer()();
  20. }
  21.  
  22. class CartWithItems {
  23.   final ShoppingCart cart;
  24.   final List<BuyableItem> items;
  25.  
  26.   CartWithItems(this.cart, this.items);
  27. }
  28.  
  29. @UseMoor(tables: [ShoppingCarts, BuyableItems, ShoppingCartEntries])
  30. class Database extends _$Database {
  31.   @override
  32.   final int schemaVersion = 1;
  33.  
  34.   Database(QueryExecutor e) : super(e);
  35.  
  36.   @override
  37.   MigrationStrategy get migration {
  38.     return MigrationStrategy(
  39.       beforeOpen: (_, details) async {
  40.         if (details.wasCreated) {
  41.           // write some fake items
  42.           for (var i = 0; i < 10; i++) {
  43.             await into(buyableItems).insert(const BuyableItemsCompanion());
  44.           }
  45.         }
  46.       },
  47.     );
  48.   }
  49.  
  50.   /// Create a new empty shopping cart
  51.   Future<ShoppingCart> createShoppingCart() async {
  52.     final id = await into(shoppingCarts).insert(const ShoppingCartsCompanion());
  53.     return ShoppingCart(id: id);
  54.   }
  55.  
  56.   Future<List<BuyableItem>> loadAllItems() async {
  57.     return await select(buyableItems).get();
  58.   }
  59.  
  60.   Stream<CartWithItems> watchCart(int id) {
  61.     final cartQuery = select(shoppingCarts)
  62.       ..where((cart) => cart.id.equals(id));
  63.  
  64.     final contentQuery = select(shoppingCartEntries).join(
  65.       [
  66.         innerJoin(
  67.           buyableItems,
  68.           buyableItems.id.equalsExp(shoppingCartEntries.item),
  69.         ),
  70.       ],
  71.     )..where(shoppingCartEntries.shoppingCart.equals(id));
  72.  
  73.     final cartStream = cartQuery.watchSingle();
  74.  
  75.     final contentStream = contentQuery.watch().map((rows) {
  76.       return rows.map((row) => row.readTable(buyableItems)).toList();
  77.     });
  78.  
  79.     return Observable.combineLatest2(cartStream, contentStream,
  80.         (ShoppingCart cart, List<BuyableItem> items) {
  81.       return CartWithItems(cart, items);
  82.     });
  83.   }
  84.  
  85.   Stream<List<CartWithItems>> watchAllCarts() {
  86.     // start by watching all carts
  87.     final cartStream = Observable(select(shoppingCarts).watch());
  88.  
  89.     return cartStream.switchMap((carts) {
  90.       // this method is called whenever the list of carts changes. For each
  91.       // cart, we want to load all the items in it.
  92.       // (we create a map from id to cart here just for performance reasons)
  93.       final idToCart = {for (var cart in carts) cart.id: cart};
  94.       final ids = idToCart.keys;
  95.  
  96.       // select all entries that are included in a cart that we found
  97.       final entryQuery = select(shoppingCartEntries).join(
  98.         [
  99.           innerJoin(
  100.             buyableItems,
  101.             buyableItems.id.equalsExp(shoppingCartEntries.item),
  102.           )
  103.         ],
  104.       )..where(isIn(shoppingCartEntries.shoppingCart, ids));
  105.  
  106.       return entryQuery.watch().map((rows) {
  107.         // Store the list of entries for each cart, again using maps for faster
  108.         // lookups.
  109.         final idToItems = <int, List<BuyableItem>>{};
  110.  
  111.         // for each entry (row) that is included in a cart, put it in the map
  112.         // of items.
  113.         for (var row in rows) {
  114.           final item = row.readTable(buyableItems);
  115.           final id = row.readTable(shoppingCartEntries).shoppingCart;
  116.  
  117.           idToItems.putIfAbsent(id, () => []).add(item);
  118.         }
  119.  
  120.         // finally, all that's left is to merge the map of carts with the map of
  121.         // entries
  122.         return [
  123.           for (var id in ids)
  124.             CartWithItems(idToCart[id], idToItems[id] ?? []),
  125.         ];
  126.       });
  127.     });
  128.   }
  129.  
  130.   Future<void> writeShoppingCart(CartWithItems entry) {
  131.     return transaction((_) async {
  132.       final cart = entry.cart;
  133.  
  134.       // first, we write the shopping cart
  135.       await into(shoppingCarts).insert(cart, orReplace: true);
  136.  
  137.       // replace entries of the cart
  138.       await (delete(shoppingCartEntries)
  139.             ..where((entry) => entry.shoppingCart.equals(cart.id)))
  140.           .go();
  141.  
  142.       await into(shoppingCartEntries).insertAll([
  143.         for (var item in entry.items)
  144.           ShoppingCartEntry(shoppingCart: cart.id, item: item.id),
  145.       ]);
  146.     });
  147.   }
  148. }
  149.  
  150. void main() async {
  151.   final db = Database(VMDatabase.memory());
  152.  
  153.   final cart = await db.createShoppingCart();
  154.   final availableItems = await db.loadAllItems();
  155.  
  156.   final sub = db.watchCart(cart.id).listen((updated) {
  157.     print('Cart ${updated.cart} now consists of ${updated.items}');
  158.   });
  159.  
  160.   await db.writeShoppingCart(CartWithItems(cart, availableItems.sublist(0, 3)));
  161.   await db.writeShoppingCart(CartWithItems(cart, availableItems.sublist(3, 6)));
  162.   await db.writeShoppingCart(CartWithItems(cart, availableItems.sublist(6)));
  163.  
  164.   await Future.delayed(const Duration(seconds: 2));
  165.   await sub.cancel();
  166.   await db.close();
  167. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top