Guest User

Untitled

a guest
Aug 20th, 2019
102
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