Angular + Parse: Serverless Rapid Prototype
In order to minimize the time to market for the SuperMighty platform, we began looking into Cloud Services such as Parse and Firebase to manage our users and Mighty Items (MI). Such platforms make life for developers less painful on an order of magnitude. We chose to go with Parse since it integrates better with IOS and the first game we are interacting with is written in IOS. Below I have documented the very simple process of creating a direct and secure connection directly between Parse and our developer dashboard.
Our initial thought on utilizing this cloud storage was that we would still need to build an API who's purpose would be to hide our Parse API credentials from being directly viewable through the client side code of our AngularJS dashboard as well as our various plugins for Unity, Gamemaker, iOS, etc. Upon further inspection it was revealed that Parse has already taken care of this problem.
Parse's object level control allows a user to create an Access Control List (ACL), which is a JSON object defining permissions for both a specific user and the general public.
// Only user with ID nH0EQaCfCu has read/write access. The public has no read/write access. {"nH0EQaCfCu":{"write":true,"read":true}} // Only user with ID nH0EQaCfCu has read/write access. The public has read access only. {"nH0EQaCfCu":{"write":true,"read":true}, "*":{"read":true}} Setting up an ACL for parse is as easy as a few lines of code implemented in the save method: // Create instance of Parse with getters and setters var Item = Parse.Object.extend({ className: "Items", attrs:['productId', 'tempUser', 'user'] }); // Create an Access Control List var acl = new Parse.ACL(); // Set permissions for the current user acl.setWriteAccess( currentUser, true); acl.setReadAccess( currentUser, true); // Set permissions for the public acl.setPublicReadAccess(false); acl.setPublicWriteAccess(false); var item = new Item({ACL: acl});
Now that there is no more need for an obfuscation layer, our dashboard and plugins can communicate directly with Parse rather than having to first write to an API thats only purpose would be to house the Parse API credentials. This eliminates a significant amount of development.
Once looking into the Parse JavaScript API, I found that it does not directly interface with Angular in the same way that Firebase does using their provided Angular Fire plugin. The main issue with Parse and Angular is that Angular does not automatically bind to Parse objects. The standard Parse JavaScript API can still be used but it requires a $scope.$apply() call to the digest cycle upon retrieving or saving data.
A simple patch will also take care of this for you as well as creating getters and setters for all of the properties of the Parse object you wish to access.
https://github.com/brandid/parse-angular-patch
Now I am able to use the Parse API as it is detailed in the documentation.
In my service I can create a method to find results like so:
find: function() { var query = new Parse.Query(Item); var delay = $q.defer(); query.equalTo('user', currentUser); query.find({ success: function(response) { delay.resolve(response); }, error: function(object, error) { delay.reject(error); } }); return delay.promise; },
In my controller I can implement the method just as easily and assign the result to $scope.items:
Item.find().then(function(response) { $scope.data.items = response; });
The parse angular patch also allows you to define getters and setters for whatever properties you wish. This allows for ease of use particularly while creating templates.
// Create instance of parse with getters and setters var Item = Parse.Object.extend({ className: "Items", attrs:['productId', 'tempUser', 'user'] });
The getters and setters can then be implemented in the template like so:
In closing, the out of box functionality of Parse can save countless hours when trying to push a product to market quickly.