Search code examples
dartangular-dart

AngularDart: in memory data service with multiple collections


I have been following the Hero Tutorial, and have an in_memory_data_service.dart file with one "collection/table" called _initialHeroes. But everything at the moment, is laid out to support only this collection/table. How would I best refactor the in_memory_data_service.dart to support multiple collections/tables?


Solution

  • This is how I solved it. Just deciding based on the path segment of the url (which is "places" or "posts", to which in-memory-list I should connect. In my case to places or posts. Not very nicely coded, but it's only temporary anyway and works.

    
    import 'dart:async';
    import 'dart:convert';
    import 'dart:math';
    import 'package:angular/angular.dart';
    import 'package:http/http.dart';
    import 'package:http/testing.dart';
    import 'src/place.dart';
    import 'src/post.dart';
    
    @Injectable()
    class InMemoryDataService extends MockClient {
      static final _initialPlaces = [
        {'id': 11, 'name': 'Place 1'},
        {'id': 12, 'name': 'Place 2'},
        {'id': 13, 'name': 'Place 3'},
        {'id': 14, 'name': 'Place 4'},
        {'id': 15, 'name': 'Place 5'},
        {'id': 16, 'name': 'Place 6'},
        {'id': 17, 'name': 'Place 7'},
        {'id': 18, 'name': 'Place 8'},
        {'id': 19, 'name': 'Place 9'},
        {'id': 20, 'name': 'Place 10'}
      ];
    
      static final _initialPosts = [
        {'id': 23, 'place_id': 11, 'text': 'My first post'},
        {'id': 24, 'place_id': 11, 'text': 'My second post'},
        {'id': 25, 'place_id': 11, 'text': 'My third post'},
        {'id': 26, 'place_id': 11, 'text': 'My fourth post'},
        {'id': 27, 'place_id': 11, 'text': 'My fifth post'},
        {'id': 28, 'place_id': 11, 'text': 'My sixth post'},
        {'id': 29, 'place_id': 11, 'text': 'My seventh post'},
        {'id': 30, 'place_id': 11, 'text': 'My eights post'},
        {'id': 31, 'place_id': 11, 'text': 'My ninth post'},
        {'id': 32, 'place_id': 11, 'text': 'My tenth post'},
        {'id': 33, 'place_id': 11, 'text': 'My elevents post'},
      ];
    
      static List _placesTbl;
      static List _postsTbl;
      static int _nextPlacesId;
      static int _nextPostsId;
    
      static Future _handler(Request request) async {
        if (_placesTbl == null) resetDb();
    
        var data;
        switch (request.method) {
          case 'GET':
            final id = int.tryParse(request.url.pathSegments.last);
    
            switch(request.url.pathSegments[1]) {
              case 'places':
                if (id != null) {
                  data = _placesTbl
                    .firstWhere((place) => place.id == id); // throws if no match
                } else {
                  String prefix = request.url.queryParameters['name'] ?? '';
                  final regExp = new RegExp(prefix, caseSensitive: false);
                  data = _placesTbl.where((place) => place.name.contains(regExp)).toList();
                }
                break;
              case 'posts':
                if (id != null) {
                  data = _postsTbl
                    .firstWhere((post) => post.id == id); // throws if no match
                } else {
                  String prefix = request.url.queryParameters['text'] ?? '';
                  final regExp = new RegExp(prefix, caseSensitive: false);
                  data = _postsTbl.where((post) => post.text.contains(regExp)).toList();
                }          
                break;
              default:
                throw 'Unimplemented HTTP method ${request.method}';            
            }
            break;
          case 'POST':
            switch(request.url.pathSegments[1]) {
              case 'places':
                var name = json.decode(request.body)['name'];
                var newPlace = new Place(_nextPlacesId++, name);
                _placesTbl.add(newPlace);
                data = newPlace;
                break;
              case 'posts':
                var text = json.decode(request.body)['text'];
                var place_id = json.decode(request.body)['place_id'];
                var newPost = new Post(_nextPostsId++, place_id, text);
                _postsTbl.add(newPost);
                data = newPost;          
                break;
            }
            break;
          case 'PUT':
            switch(request.url.pathSegments[1]) {
              case 'places':
                var placeChanges = new Place.fromJson(json.decode(request.body));
                var targetPlace = _placesTbl.firstWhere((h) => h.id == placeChanges.id);
                targetPlace.name = placeChanges.name;
                data = targetPlace;          
                break;
              case 'posts':
                var postChanges = new Post.fromJson(json.decode(request.body));
                var targetPost = _postsTbl.firstWhere((h) => h.id == postChanges.id);
                targetPost.place_id = postChanges.place_id;
                targetPost.text = postChanges.text;
                data = targetPost;            
                break;
            }
            break;
          case 'DELETE':
            switch(request.url.pathSegments[1]) {
              case 'places':
                var id = int.parse(request.url.pathSegments.last);
                _placesTbl.removeWhere((place) => place.id == id);
                break;
              case 'posts':
                var id = int.parse(request.url.pathSegments.last);
                _postsTbl.removeWhere((post) => post.id == id);
                break;
            }
            // No data, so leave it as null.
            break;
          default:
            throw 'Unimplemented HTTP method ${request.method}';
        }
        return new Response(json.encode({'data': data}), 200,
            headers: {'content-type': 'application/json'});
      }
    
      static resetDb() {
        _placesTbl = _initialPlaces.map((json) => new Place.fromJson(json)).toList();
        _postsTbl = _initialPosts.map((json) => new Post.fromJson(json)).toList();
        _nextPlacesId = _placesTbl.map((place) => place.id).fold(0, max) + 1;
        _nextPostsId = _postsTbl.map((post) => post.id).fold(0, max) + 1;
      }
    
      static String lookUpPlacesName(int id) =>
          _placesTbl.firstWhere((place) => place.id == id, orElse: null)?.name;
    
      static String lookUpPostsText(int id) =>
          _postsTbl.firstWhere((post) => post.id == id, orElse: null)?.text;
    
      InMemoryDataService() : super(_handler);
    }