An explosive MVC Framework for NodeJS
var express = require('express'),
app = express();
app.get('/hello.txt', function(req, res){
res.send('Hello World');
});
app.listen(3000);
Generators
Using the Compound scaffolding
Generate an application
compound init myApp && cd myApp
npm install
compound generate app myApp
Generate CRUD functionality
compound generate crud user name bio age:number createdAt:date
Running the application
Start the server
compound server 3000
Controllers
exports.routes = function (map) {
// Maps CRUD methods map.resources('users');
// Maps a custom method map.get('users/login', 'users#login');
// Maps the homepage map.root('users#dashboard'); map.all(':controller/:action'); map.all(':controller/:action/:id'); };
The anatomy of a controller
load('application');
before(function () {
// ...
}, {
only: ['edit']
});
action('login', function () {
render();
});
action(function edit() {
//...
});
Status code
action('destroy', function () {
send(403); // Forbidden
});
Json
action('find', function () {
send({
name: 'Darth Vader',
age: 45
});
});
In the controller
action(function create() {
flash('info', 'User created');
redirect(path_to.users);
});
In the view
<% var flash = request.flash('info').pop(); if (flash) { %>
<div class="alert alert-info">
<a class="close" data-dismiss="alert">×</a>
<%- flash %>
</div>
<% } %>
Views
What view renderers are supported in Compound?
Render a different view
render('viewName');
Pass data in directly
render(undefined, { name: 'Darth Vader' });
<%- include _form %>
<html>
<head>
<title><%= title %></title> <%- stylesheet_link_tag('bootstrap') %> <%- javascript_include_tag('application') %>
</head>
<body>
<%- body %>
</body>
</html>
What Does it do?
What it looks like
Defining a database schema:
User = schema.define('User', {
name: String,
bio: Text,
approved: Boolean,
joinedAt: Date,
age: Number
});
Post = schema.define('Post', {
title: { type: String, length: 255 },
content: { type: Text },
date: { type: Date, default: Date.now },
published: { type: Boolean, default: false }
});
User.create({
name: 'Anakin Skywalker',
bio: 'Jedi and pilot',
approved: false,
joinedAt: new Date(),
age: 12
}, function (err, user) {
console.log(user);
});
Get everybody
User.all(function (err, users) {
console.log(users); // Array
});
Get a few certain people
User.all({
where: { age: 12 }
}, function (err, users) {
console.log(users); // Array
});
Get someone special
var id = 1;
User.find(id, function (err, user) {
console.log(user); // Array
});
var id = 1;
User.find(id, function (err, user) {
user.updateAttributes({
name: 'Darth Vader',
bio: 'Dark Lord of the Sith',
approved: true,
age: 45
}, function (err, user) {
console.log(user);
});
});
var id = 1;
User.find(id, function (err, user) {
user.destroy(function (err) {
console.log('BOOM!');
});
});
module.exports = function (compound, User) {
User.splitName = function () {
return this.name.split(' ');
};
User.hasMany(Post, {
as: 'posts',
foreignKey: 'userId'
});
User.belongsTo(Affiliation, {
as: 'affiliation',
foreignKey: 'affiliationId'
});
};
User.validatesPresenceOf('bio', 'name');
User.validatesLengthOf('name', { min: 3 });
Built in validation
User.validate('validateType', function (err) {
if (this.type === 'Droid') {
err();
}
}, {
message: 'We don\'t serve their kind here!'
});
Why do tests matter?
How do tests work in Compound?
How to write Unit
tests for Compound
function ValidAttributes () {
return {
name: 'Boba Fett',
age: 1
};
}
exports['models controller'] = {
'POST create': function (test) {
var model = new ValidAttributes;
var create = Model.create;
Model.create = sinon.spy(function (data, callback) {
test.strictEqual(data, model);
callback(null, model);
});
test.post('/models', {Model: model}, function () {
test.redirect('/models');
test.flash('info');
test.done();
});
},
...
};
Compound on the client-side
Asset compiler
Included compilers:
app.configure(function(){
app.use(compound.assetsCompiler.init());
app.set('cssEngine', 'sass');
});
Compound tools
Run compound commands from the terminalcompound.tools.starwars = function () { switch (compound.args.shift()) { case 'episode4':
break; case 'episode5':
console.log('The Empire Strikes Back'); break; }; }
In the terminal
compound starwars episode5