Upload
nicholas-mcclay
View
1.660
Download
0
Embed Size (px)
DESCRIPTION
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!
Citation preview
http://www.meetup.com/Pittsburgh-Node-js/
NICHOLAS MCCLAYUX Developer
@nickmcclay
MEET YOUR NEIGHBOR
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 socket.io integration !
• Role based access policies and ACL !
• JS/CSS asset bundling and minification (Grunt)
QUICK NOTE:Convention > Configuration = Magic
WHAT IS A SINGLE PAGE APPLICATION?
TRADITIONAL WEB APPLICATION
One Kitten Please!
HTTP Request
http://www.cutekitties.com/kitten/1
Response
HTMLJavaScript
CSS
TADA! WEB PAGE!
SINGLE PAGE APPLICATION
One Kitten Please!
HTTP Request
http://www.cutekitties.com#/kitten/1
Response
HTMLJavaScript
CSS
Application
GET /kitten/1
A JAX Request
/kitten/1?format=json
Response
JSON
[{ "_id" : "abc124efg345", "lives" : 9, "curiousity" : "massive", "cuteness" : 9999, "eyes" : "blue", "fur" : "yellow"}]
TADA! WEB APP!
Heading out to sea
SAILS VERSIONS
V0.9 V0.10
• Current NPM default • Reliable starting place • What I’ll be demoing
in this presentation
• beta version (RC3) • Significant Refactors • API changes • Associations • Here be dragons…
https://github.com/balderdashy/sails-docs/blob/master/Migration-Guide.md
Coming
V0.10 Soon
DOCUMENTATION SOURCES
https://github.com/balderdashy/sails-docs/tree/0.10Coming
V0.10 Soon
http://sailsjs.org/#!documentation
Official Website Documentation
GitHub Documentation Repo
CREATE A NEW SAILS PROJECThttp://sailsjs.org/#!getStarted
0.10.0 NPM INSTALL WEIRDNESS
If you encounter this, try:
npm install -g
SAILS CLI BASICS
sails lift --dev --prod
sails new <appName> --linker
sails version
--verbose
Make a new app Turn on asset linking
Run App Set Env Config Display all logs
Display Sails.js Version
SAILS SCAFFOLDING
sails generate (type) <id>
Generate Scaffolding
model, controller, default is both
sails generate (type) <id>
model, controller, api, blog, user, whatever you want!
Pluggable Generators for ScaffoldingComing
V0.10 Soon
MODELSvar 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;
(Waterline Collection)api/models
BEYOND ATTRIBUTES// Define a custom instance methodfullName: function() { return this.firstName + ' ' + this.lastName; }, // Lifecycle CallbacksbeforeCreate: function(values, next) { bcrypt.hash(values.password, 10, function(err, hash) { if(err) return next(err); values.password = hash; next(); });}, // Override toJSON instance method// to remove phoneNumber valuetoJSON: function() { var obj = this.toObject(); delete obj.password; return obj; }
ORM - WATERLINEhttps://github.com/balderdashy/waterline
• ActiveRecord, Hibernate, and Mongoose
• emphasis on modularity, testability, and consistency across adapters
• Waterline Adapter -> DB Query • Custom Adapter methods
ASSOCIATIONSComing
V0.10 SoonAssociate models across different data stores
var Blog = { attributes : { title : 'string', body : 'string', author : { model : 'person' } }};
• One way • One-to-One • One-to-Many • Many-to-Many
Blog.find({title:'Sails.js Presentation'}).populate('author').exec(console.log);
Relationship TypesDefining Association
Full Sail Ahead!
RESOURCEFUL ROUTING
/:controller/find/:id? /:controller/create /:controller/update/:id /:controller/destroy/:id
get /:controller/:id? post /:controller put /:controller/:id delete /:controller/:id
!To disable set the ‘rest’ flag to false in config/controllers.js
To disable set the ‘shortcuts’ flag to false in config/controllers.js,
CRUD Routes
REST Routes
FREE
FREE
CONTROLLERSapi/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 chicken.save(function (err) { // Persist the change if (err) return res.send(err,500); // Report back with the new state of the chicken res.json(chicken); }); }); }}; module.exports = ChickenController;
SOCKET.IO
// all controller routes return valid responsessocket.get('/todo/count', function(results) { console.log(results) });// create a new itemsocket.post('/todo', {"title" : "this is from sockets"}, function(err,results) { console.log(err,results) });// all valid ways to update with websocketssocket.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 websocketssocket.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 messagessocket.on('message', function(message) { console.log(message) });// listen for messages from a specific controllersocket.on('todo',function(message) { console.log(message) }); Coming
V0.10 Soon
http://socket.io/
POLICIESapi/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.jsmodule.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
sails new <appName> --linker
Enabling Asset Linking
Place Assets in between special linker flags
assets/linker/
GET STARTED BUILDING
https://github.com/cgmartin/sailsjs-angularjs-bootstrap-example
https://www.npmjs.org/package/generator-sails
http://irlnathan.github.io/sailscasts/
THANKS!
@nickmcclay