Intro to Sail.js

67 %
33 %
Information about Intro to Sail.js

Published on February 27, 2014

Author: NicholasMcClay



Sails.js is a realtime MVC framework for Node.js that is inspired by some of the best ideas behind Ruby on Rails and realtime frameworks like Meteor.js.

In this presentation I'll overview getting started with Sails.js, its architecture and features, as well as some advice on place to look at when you are getting started.

Learn a brand new way to think about web application development with Node.js!

NICHOLAS MCCLAY UX Developer @nickmcclay


Framework Overview

SAILS HIGHLIGHTS • Robust Node.js MVC web server framework ! • Railsy features - scaffolding, DB agnostic ORM ! • Automatically generated RESTful JSON API ! • Out-of-the-box real-time integration ! • Role based access policies and ACL ! • JS/CSS asset bundling and minification (Grunt)

QUICK NOTE: Convention > Configuration = Magic



Response HTML JavaScript CSS



Application Response HTML JavaScript CSS

/kitten/1?format=json GET /kitten/1 A JAX Request

 "_id" : "abc124efg345",
 "lives" : 9,
 "curiousity" : "massive",
 "cuteness" : 9999,
 "eyes" : "blue",
 "fur" : "yellow"
 }] Response JSON


Heading out to sea

SAILS VERSIONS V0.9 Coming V0.10 V0.10 Soon • Current NPM default • beta version (RC3) • Reliable starting place • Significant Refactors • What I’ll be demoing • API changes in this presentation • Associations • Here be dragons…

DOCUMENTATION SOURCES Official Website Documentation!documentation GitHub Documentation Repo Coming V0.10 Soon


0.10.0 NPM INSTALL WEIRDNESS If you encounter this, try: npm install -g

SAILS CLI BASICS Turn on asset linking Make a new app sails new <appName> Run App sails lift --linker Set Env Config Display all logs --dev --prod --verbose Display Sails.js Version sails version

SAILS SCAFFOLDING Generate Scaffolding sails generate (type) <id> model, controller, default is both Pluggable Generators for Scaffolding Coming V0.10 Soon sails generate (type) <id> model, controller, api, blog, user, whatever you want!

MODELS (Waterline Collection) api/models var Person = {
 schema : true,
 attributes: {
 firstName: 'string',
 lastName: 'string',
 password : {
 type : 'string',
 required : true,
 notEmpty : true
 age : {
 type: 'integer',
 max: 150,
 required: true
 birthDate: 'date',
 phoneNumber: {
 type: 'string',
 defaultsTo: '111-222-3333'
 emailAddress: {
 type: 'email', // Email type will get validated by the ORM
 required: true
 model.exports = Person;

BEYOND ATTRIBUTES // Define a custom instance method
 fullName: function() {
 return this.firstName + ' ' + this.lastName;
 // Lifecycle Callbacks
 beforeCreate: function(values, next) {
 bcrypt.hash(values.password, 10, function(err, hash) {
 if(err) return next(err);
 values.password = hash;
 // Override toJSON instance method
 // to remove phoneNumber value
 toJSON: function() {
 var obj = this.toObject();
 delete obj.password;
 return obj;

ORM - WATERLINE • ActiveRecord, Hibernate, and Mongoose • emphasis on modularity, testability, and consistency across adapters • Waterline Adapter -> DB Query • Custom Adapter methods

Coming ASSOCIATIONS V0.10 Associate models across different data stores Defining Association var Blog = {
 attributes : {
 title : 'string',
 body : 'string',
 author : {
 model : 'person'
 }; Soon Relationship Types • One way • One-to-One • One-to-Many • Many-to-Many Blog.find({title:'Sails.js Presentation'}).populate('author').exec(console.log);

Full Sail Ahead!

RESOURCEFUL ROUTING CRUD Routes get /:controller/:id? post /:controller put /:controller/:id delete /:controller/:id FREE To disable set the ‘shortcuts’ flag to false in config/controllers.js, REST Routes /:controller/find/:id? /:controller/create /:controller/update/:id /:controller/destroy/:id FREE ! To disable set the ‘rest’ flag to false in config/controllers.js

CONTROLLERS api/controllers var ChickenController = {
 // Peck the chicken specified by id (subtract 50 HP)
 peck: function (req,res) {
 Chicken.find(req.param('id')).exec(function (err, chicken) {
 if (err) return res.send(err,500);
 if (!chicken) return res.send("No other chicken with that id exists!", 404);
 if (chicken.hp <= 0) return res.send("The other chicken is already dead!", 403);
 chicken.hp -= 50; // Subtract 50 HP from the chicken (err) { // Persist the change
 if (err) return res.send(err,500);
 // Report back with the new state of the chicken
 module.exports = ChickenController;

SOCKET.IO // all controller routes return valid responses
 socket.get('/todo/count', function(results) { console.log(results) });
 // create a new item'/todo', {"title" : "this is from sockets"}, function(err,results) { console.log(err,results) });
 // all valid ways to update with websockets
 socket.put('/todo', {'id' : 1, 'title' : "updated1"}, function(results) { console.log(results) });
 socket.put('/todo/1', {'title' : "updated2"}, function(results) { console.log(results) });
 socket.get('/todo/update/1', {'title' : "updated3"}, function(results) { console.log(results) });
 // all valid ways to delete with websockets
 socket.delete('/todo', {'id' : 1}, function(results) { console.log(results) });
 socket.delete('/todo/1', function(results) { console.log(results) });
 socket.get('/todo/delete/21',function(results) { console.log(results)});
 // listen for messages
 socket.on('message', function(message) { console.log(message) });
 // listen for messages from a specific controller
 socket.on('todo',function(message) { console.log(message) }); Coming V0.10 Soon

POLICIES api/policies/isAuthenticated.js module.exports = function(req, res, next) {
 // User is allowed, proceed to the next policy, 
 // or if this is the last policy, the controller
 if (req.session.authorized == true) {
 return next();
 // User is not allowed
 // (default res.forbidden() behavior can be overridden in `config/403.js`)
 return res.forbidden('You are not permitted to perform this action.');
 }; config/policies.js module.exports.policies = {
 // Default policy for all controllers and actions
 // (`true` allows public access) 
 '*': true,
 // Policies for /Foo/* routes
 FooController: {
 "*" : true,
 'update' : 'isAuthenticated',
 'destroy' : ['isAuthenticated','isOwner']

ASSET MANAGEMENT assets/linker/ Enabling Asset Linking sails new <appName> --linker Place Assets in between special linker flags


THANKS! @nickmcclay

Add a comment

Related presentations

Related pages

Intro to Sails.js - YouTube Sails.js makes it easy to build custom, ... Intro to Sails.js - Duration: 20:54. Next Day Video 4,205 views. 20:54
Read more

Intro to Sail.js - Technology -

Sails.js is a realtime MVC framework for Node.js that is inspired by some of the best ideas behind Ruby on Rails and realtime frameworks like Meteor.js. In ...
Read more

Creating a restful json api in less than 15 seconds with ...

Creating a restful json api in less than 15 seconds with sails.js. ... Intro to Sails.js - Duration: 20:54. Next Day Video 4,205 views. 20:54
Read more

sails.js + Can't receive standard sail.js ...

sails.js + Can't receive standard sail.js/ messages on client. ... (which the Intro to Sails.js video shows) and the latest version.
Read more

StrongLoop | StrongLoop Videos

In this presentation recorded on March 31, 2016, StrongLoop evangelist Raymond Camden introduced the LoopBack framework. ... Hapi, restify, sail.js, ...
Read more

IDE for Node.js / Javascript? - Stack Overflow

IDE for Node.js / Javascript? [closed] up vote 214 down vote favorite. 168. What is your preference when it comes to editing/debugging large JavaScript ...
Read more

sails-docs/ at master · balderdashy/sails-docs · GitHub

sails-docs - This is the source markdown files for the official Sails.js documentation, which get compiled, squeezed, and stretched into HTML when we ...
Read more

PHP: POST method uploads - Manual

POST method uploads. This feature lets people upload both text and binary files. With PHP's authentication and file manipulation functions, you have ...
Read more