Permalink
Browse files

Added new mvc example

  • Loading branch information...
1 parent c33f1ba commit d0bc0ad2caef182fddc025470c326d43dae29922 @tj tj committed Apr 26, 2012
View
4 examples/mvc/controllers/main/index.js
@@ -0,0 +1,4 @@
+
+exports.index = function(req, res){
+ res.redirect('/users');
+};
View
26 examples/mvc/controllers/pet/index.js
@@ -0,0 +1,26 @@
+
+var db = require('../../db');
+
+exports.engine = 'jade';
+
+exports.show = function(req, res, next){
+ var pet = db.pets[req.params.pet_id];
+ if (!pet) return next(new Error('Pet not found'));
+ res.render('show', { pet: pet });
+};
+
+exports.edit = function(req, res, next){
+ var pet = db.pets[req.params.pet_id];
+ if (!pet) return next(new Error('Pet not found'));
+ res.render('edit', { pet: pet });
+};
+
+exports.update = function(req, res, next){
+ var id = req.params.pet_id;
+ var pet = db.pets[id];
+ var body = req.body;
+ if (!pet) return next(new Error('Pet not found'));
+ pet.name = body.user.name;
+ res.message('Information updated!');
+ res.redirect('/pet/' + id);
+};
View
7 examples/mvc/controllers/pet/views/edit.jade
@@ -0,0 +1,7 @@
+link(rel='stylesheet', href='/style.css')
+h1= pet.name
+form(action='/pet/#{pet.id}', method='post')
+ input(type='hidden', name='_method', value='put')
+ label Name:
+ input(type='text', name='user[name]', value=pet.name)
+ input(type='submit', value='Update')
View
6 examples/mvc/controllers/pet/views/show.jade
@@ -0,0 +1,6 @@
+link(rel='stylesheet', href='/style.css')
+
+h1= pet.name
+ a(href='/pet/#{pet.id}/edit') edit
+
+p You are viewing #{pet.name}
View
17 examples/mvc/controllers/user-pet/index.js
@@ -0,0 +1,17 @@
+
+var db = require('../../db');
+
+exports.name = 'pet';
+exports.prefix = '/user/:user_id';
+
+exports.create = function(req, res, next){
+ var id = req.params.user_id;
+ var user = db.users[id];
+ var body = req.body;
+ if (!user) return next(new Error('User not found'));
+ var pet = { name: body.pet.name };
+ pet.id = db.pets.push(pet) - 1;
+ user.pets.push(pet);
+ res.message('Added pet ' + body.pet.name);
+ res.redirect('/user/' + id);
+};
View
28 examples/mvc/controllers/user/index.js
@@ -0,0 +1,28 @@
+
+var db = require('../../db');
+
+exports.list = function(req, res, next){
+ res.render('list', { users: db.users });
+};
+
+exports.edit = function(req, res, next){
+ var user = db.users[req.params.user_id];
+ if (!user) return next(new Error('User not found'));
+ res.render('edit', { user: user });
+};
+
+exports.show = function(req, res, next){
+ var user = db.users[req.params.user_id];
+ if (!user) return next(new Error('User not found'));
+ res.render('show', { user: user });
+};
+
+exports.update = function(req, res, next){
+ var id = req.params.user_id;
+ var user = db.users[id];
+ var body = req.body;
+ if (!user) return next(new Error('User not found'));
+ user.name = body.user.name;
+ res.message('Information updated!');
+ res.redirect('/user/' + id);
+};
View
12 examples/mvc/controllers/user/views/edit.html
@@ -0,0 +1,12 @@
+<link rel="stylesheet" href="/style.css" />
+<h1><%= user.name %></h1>
+<form action='/user/<%= user.id %>' method='post'>
+ <input type="hidden" name="_method" value="put" />
+ <label>Name: <input type="text" name="user[name]" value="<%= user.name %>" /></label>
+ <input type="submit" value="Update" />
+</form>
+
+<form action='/user/<%= user.id %>/pet' method='post'>
+ <label>Pet: <input type="text" name="pet[name]" placeholder="name" /></label>
+ <input type="submit" value="Add" />
+</form>
View
8 examples/mvc/controllers/user/views/list.html
@@ -0,0 +1,8 @@
+<link rel="stylesheet" href="/style.css" />
+<h1>Users</h1>
+<p>Click a user below to view their pets.</p>
+<ul>
+ <% users.forEach(function(user){ %>
+ <li><a href="/user/<%= user.id %>"><%= user.name %></a></li>
+ <% }) %>
+</ul>
View
21 examples/mvc/controllers/user/views/show.html
@@ -0,0 +1,21 @@
+<link rel="stylesheet" href="/style.css" />
+<h1><%= user.name %> <a href="/user/<%= user.id %>/edit">edit</a></h1>
+
+<% if (hasMessages) { %>
+ <ul id="messages">
+ <% messages.forEach(function(msg){ %>
+ <li><%= msg %></li>
+ <% }) %>
+ </ul>
+<% } %>
+
+<% if (user.pets.length) { %>
+ <p>View <%= user.name %>s pets:</p>
+ <ul>
+ <% user.pets.forEach(function(pet){ %>
+ <li><a href="/pet/<%= pet.id %>"><%= pet.name %></a></li>
+ <% }) %>
+ </ul>
+<% } else { %>
+ <p>No pets!</p>
+<% } %>
View
15 examples/mvc/db.js
@@ -0,0 +1,15 @@
+
+// faux database
+
+var pets = exports.pets = [];
+
+pets.push({ name: 'Tobi', id: 0 });
+pets.push({ name: 'Loki', id: 1 });
+pets.push({ name: 'Jane', id: 2 });
+pets.push({ name: 'Raul', id: 3 });
+
+var users = exports.users = [];
+
+users.push({ name: 'TJ', pets: [pets[0], pets[1], pets[2]], id: 0 });
+users.push({ name: 'Guillermo', pets: [pets[3]], id: 1 });
+users.push({ name: 'Nathan', pets: [], id: 2 });
View
68 examples/mvc/index.js
@@ -0,0 +1,68 @@
+
+var express = require('../..');
+
+var app = express();
+
+// settings
+
+// map .renderFile to ".html" files
+app.engine('html', require('ejs').renderFile);
+
+// make ".html" the default
+app.set('view engine', 'html');
+
+// define a custom res.message() method
+// which stores messages in the session
+app.response.message = function(msg){
+ // reference `req.session` via the `this.req` reference
+ var sess = this.req.session;
+ // simply add the msg to an array for later
+ sess.messages = sess.messages || [];
+ sess.messages.push(msg);
+ return this;
+};
+
+// expose the "messages" local variable when views are rendered
+app.locals.use(function(req, res){
+ var msgs = req.session.messages || [];
+
+ // expose "messages" local variable
+ res.locals.messages = msgs;
+
+ // expose "hasMessages"
+ res.locals.hasMessages = !! msgs.length;
+
+ /*
+
+ This is equivalent:
+
+ res.locals({
+ messages: msgs,
+ hasMessages: !! msgs.length
+ });
+
+ */
+
+ // empty or "flush" the messages so they
+ // don't build up
+ req.session.messages = [];
+});
+
+// serve static files
+app.use(express.static(__dirname + '/public'));
+
+// session support
+app.use(express.cookieParser('some secret here'));
+app.use(express.session());
+
+// parse request bodies (req.body)
+app.use(express.bodyParser());
+
+// support _method (PUT in forms etc)
+app.use(express.methodOverride());
+
+// load controllers
+require('./lib/boot')(app);
+
+app.listen(3000);
+console.log('\n listening on port 3000\n');
View
64 examples/mvc/lib/boot.js
@@ -0,0 +1,64 @@
+
+var express = require('../../..')
+ , fs = require('fs');
+
+module.exports = function(parent){
+ console.log();
+ fs.readdirSync(__dirname + '/../controllers').forEach(function(name){
+ console.log(' %s:', name);
+ var obj = require('./../controllers/' + name)
+ , name = obj.name || name
+ , prefix = obj.prefix || ''
+ , app = express()
+ , method
+ , path;
+
+ // allow specifying the view engine
+ if (obj.engine) app.set('view engine', obj.engine);
+ app.set('views', __dirname + '/../controllers/' + name + '/views');
+
+ // generate routes based
+ // on the exported methods
+ for (var key in obj) {
+ // "reserved" exports
+ if ('name' == key || 'prefix' == key || 'engine' == key) continue;
+ // route exports
+ switch (key) {
+ case 'show':
+ method = 'get';
+ path = '/' + name + '/:' + name + '_id';
+ app[method](path, obj[key]);
+ break;
+ case 'list':
+ method = 'get';
+ path = '/' + name + 's';
+ break;
+ case 'edit':
+ method = 'get';
+ path = '/' + name + '/:' + name + '_id/edit';
+ break;
+ case 'update':
+ method = 'put';
+ path = '/' + name + '/:' + name + '_id';
+ break;
+ case 'create':
+ method = 'post';
+ path = '/' + name;
+ break;
+ case 'index':
+ method = 'get';
+ path = '/';
+ break;
+ default:
+ throw new Error('unrecognized route: ' + name + '.' + key);
+ }
+
+ path = prefix + path;
+ app[method](path, obj[key]);
+ console.log(' %s %s -> %s', method.toUpperCase(), path, key);
+ }
+
+ // mount the app
+ parent.use(app);
+ });
+};
View
14 examples/mvc/public/style.css
@@ -0,0 +1,14 @@
+body {
+ padding: 50px;
+ font: 16px "Helvetica Neue", Helvetica, Arial;
+}
+a {
+ color: #107aff;
+ text-decoration: none;
+}
+a:hover {
+ text-decoration: underline;
+}
+h1 a {
+ font-size: 16px;
+}
View
6 lib/application.js
@@ -83,6 +83,12 @@ app.defaultConfiguration = function(){
return this;
};
+ // inherit view callbacks
+ this.on('mount', function(parent){
+ this.engines.__proto__ = parent.engines;
+ this.viewCallbacks = parent.viewCallbacks.slice(0);
+ });
+
// router
this._router = new Router(this);
this.routes = this._router.routes;

0 comments on commit d0bc0ad

Please sign in to comment.