Getting started with the Sane stack – Installation and CRUD

Sane stack logo

Getting started with the Sane stack is as easy as installing a few global Node packages. The official web site  has concise,  yet sufficient instructions, Node is the only requirement:

  • npm install -g sails ember-cli sane-cli
  • sane new project creates a local project with sails-disk. To install withDocker and production databases see Options.
  • sane generate api user name:string age:number to generate a new API on the backend and models on the frontend
  • sane up to start the sails server on localhost:1337 as well as the ember dev server on localhost:4200.
  • To work on your frontend-app you work as you would normally do with ember-cli on localhost:4200.
  • You are now good to go.

The caveat here is that you’ll be using your hard drive as a database instead of a better suited solution like SQL or Mongo. Because of this I recommend you make your choice, pre-install it  and init your project with ‘-d mongo|postgres|mysql’ flag. If you are set up with Docker, the container it creates will create the database installation for you so you don’t have to worry about pre-installing.

Amazingly, this alone should give you a full web development stack and your first API – for a user resource, it will also ensure the Ember client and the Sails server communicate well. To understand how this magic works you should read up on Sails blueprints here: http://sailsjs.org/#/documentation/reference/blueprint-api The framework is cleverly designed so that the basic CRUD methods do not have to be defined for every resource, instead when such a request comes, the blueprints are read and the response is automatic according to them. Likewise when Ember makes requests like ‘this.store.find’ or ‘this.store.save’ it is automatically making a request by reading a certain blueprint in Ember Data.

Such communication between client and server is normally defined as REST, but of course there is no REST standard yet. Ember is highly opinionated about how it wants its data served, and because of that the author of SANE decided to adapt the stack to Ember. This is achieved with the following very helpful module – https://github.com/mphasize/sails-generate-ember-blueprints, which adds custom blueprints to Sails and adapts the server responses to the requirements of Ember data. If you want to be comfortable using this stack, you need to understand these requirements and the best source are the Ember guides on models: http://emberjs.com/guides/models/

For this tutorial, I will briefly mention that, Ember data expects models which come to it as a server response to be named appropriately and have a unique id so that they go in the store properly. This means if you generate a post resource like this: ‘sane generate resource post title:string body:string’ a response from the post api at ‘/api/v1/posts/:id’ will have to look like this:

“post”: {
“title”: “yuyuyuyu”,
“body”: “moooo”,
“createdAt”: “2014-12-18T04:16:11.987Z”,
“updatedAt”: “2014-12-18T04:16:11.987Z”,
“id”: “5492550bd6f292c2c465df87”
}

And a listing of posts coming as a response to a GET request to ‘/api/v1/posts/’ has to look like this:

{
“posts”: [
{
“title”: “sfa”,
“body”: “fsafsfsafa”,
“createdAt”: “2014-12-17T22:08:36.055Z”,
“updatedAt”: “2014-12-17T22:08:36.056Z”,
“id”: “5491fee4be3190138a31891d”
},
{
“title”: “WHAT “,
“body”: “UP”,
“createdAt”: “2014-12-17T22:09:47.341Z”,
“updatedAt”: “2014-12-17T22:09:47.341Z”,
“id”: “5491ff2be41e1abc8be1f835”
},
{
“title”: “yuyuyuyu”,
“body”: “moooo”,
“createdAt”: “2014-12-18T04:16:11.987Z”,
“updatedAt”: “2014-12-18T04:16:11.987Z”,
“id”: “5492550bd6f292c2c465df87”
}]
}

Again, this is all automatic for you per installing the Sane stack and saves you a lot of work. It is quite common for developers to use a tool like Postman to test their API right away after creating it. In this case, make sure that you are requesting your resource with this standard in mind and therefore if you are creating a new post with a POST to ‘/api/v1/posts/’, your request should contain an object named user with the proper attributes. This is also achievable through the url bar like this /api/v1/posts?post[name]=bla&post[title]=meh.

The attributes bring me to my next point. The resource generator of Sane is able to mirror your models on client and server, so running this command ‘sane generate resource user name:string age:number’ generated the models in such a way that the attributes will match. If you are creating more attributes later as I’m sure you will have to, you need to make sure that you set the matching attribute names on both sides according to the syntax of each and also make sure you set the data types correctly as they also differ. You can find more about that in the docs for Sails and Ember.

With your communication set up. You are ready to build your UI. There is a demonstration of this in this tutorial’s accompanying project ‘How-to-Sane’ on Github – https://github.com/mgenev/how-to-sane/tree/master/client/app/pods/posts. We can achieve most of this by using Ember CLI’s generators and it is _always_ a better idea to generate your resources using generators, because they will also create the matching unit test for you in the test folder. What you see in the pod takes care of listing posts, creating a new post and viewing a single post by id. Here we’re using pod structure which is more convenient and tidy and is described at http://www.ember-cli.com/ and this is made discoverable in the browser by the following router config:

this.resource(‘posts’, function() {
this.route(‘post’, {
path: ‘:post_id’
});

this.route(‘create’, {
path: ‘create’
});
});

The ‘resource’ automatically gives you an index route, and the other 2 are defined explicitly. In each case the data request is handled in the model hook of the route file in the pod, and in the case of the create, we are creating a fresh empty model client-side which is then populated with data by binding the fields in the template and then saving it in the action which makes a POST request to the server which saves it in the database, assigns it an id and returns it to the client which then transitions to that post by passing the id to the router. The save, post, wait for response and redirect are achieved with the following line of code (and awesome ES6 arrow functions syntax):

model.save().then(post => this.transitionTo(‘posts.post’, post));

A note about Ember’s routes and populating them with models. Ember is smart enough to figure out that when you are making a find request with no id as a param ‘this.store.find(‘post’) you are asking for an index of posts and it creates  an array in that route. Because of this in the template we have an array as a model to work with and we iterate as follows:

{{#each model as |post|}}
<h4>{{post.title}}</h4>
<p>{{post.body}}</p>
{{/each}}

And this really is it. With these few steps you are able to whip up a whole web development stack, set up an API and create a UI for listing, viewing and creating resources. Give it a try and let us know how it goes!

8 thoughts on “Getting started with the Sane stack – Installation and CRUD

  1. Permalink  ⋅ Reply

    Micah Miller-Eshleman

    December 31, 2014 at 9:40pm

    Thanks for starting this series. I’m looking forward to a post on user authentication/authorization.

  2. Permalink  ⋅ Reply

    Manuel Reil

    January 6, 2015 at 3:32pm

    Thank you, this is very good. Same as for Micah, I am really looking forward to auth!

  3. Permalink  ⋅ Reply

    Ryan Gill

    January 15, 2015 at 4:15pm

    Thanks for doing this tutorial. I’m trying to follow along and I’m running into an error when trying to build the new project.

    I’m currently using a windows pc. I ran npm install -g sails ember-cli sane-cli and everything installed fine. Then I ran sane new project and I got the following error.

    Any ideas of what might be causing this error?

  4. Permalink  ⋅ Reply

    Ryan Gill

    January 15, 2015 at 4:18pm

    var {spawn} = require(‘child_process’);

    SyntaxError: Unexpected token {
    at Module._compile (module.js:439:25)
    at Module._extensions..js (module.js:474:10)
    ….

    Sorry the link to the screenshot in my previous post did not render.

    http://i.imgur.com/zVYPdho.png

  5. Permalink  ⋅ Reply

    Jj

    January 16, 2015 at 1:47am

    Thanks for the post! Looking forward to following along for the rest of the series. We use Ember at work and I’m interested in using SANE to brush up my knowledge on Sails/EmberCLI.

  6. Permalink  ⋅ Reply

    Pete

    January 28, 2015 at 11:06am

    The error is thrown, because you wrap your variable’s name in brackets.
    Don’t

    var {spawn} = require(‘child_process’);

    Do

    var spawn = require(‘child_process’);

    • Permalink  ⋅ Reply

      mgenev@gmail.com

      February 12, 2015 at 10:31pm

      Thank you, I had not come across this yet.

Leave a Reply

Your email will not be published. Name and Email fields are required.