Skip to content

Commit

Permalink
Added res.locals.use(). Closes expressjs#1120
Browse files Browse the repository at this point in the history
  • Loading branch information
tj committed May 3, 2012
1 parent f3a32f2 commit dd33ef2
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 25 deletions.
23 changes: 4 additions & 19 deletions lib/application.js
Expand Up @@ -14,6 +14,7 @@ var connect = require('connect')
, methods = Router.methods.concat('del', 'all')
, middleware = require('./middleware')
, debug = require('debug')('express:application')
, locals = require('./utils').locals
, View = require('./view')
, url = require('url')
, utils = connect.utils
Expand Down Expand Up @@ -64,25 +65,6 @@ app.defaultConfiguration = function(){
this.use(connect.query());
this.use(middleware.init(this));

// app locals
this.locals = function(obj){
for (var key in obj) self.locals[key] = obj[key];
return self;
};

// response locals
this.locals.use = function(fn){
if (3 == fn.length) {
self.viewCallbacks.push(fn);
} else {
self.viewCallbacks.push(function(req, res, done){
fn(req, res);
done();
});
}
return this;
};

// inherit view callbacks
this.on('mount', function(parent){
this.request.__proto__ = parent.request;
Expand All @@ -101,6 +83,9 @@ app.defaultConfiguration = function(){
return this._router.middleware;
});

// setup locals
this.locals = locals(this);

// default locals
this.locals.settings = this.settings;

Expand Down
13 changes: 8 additions & 5 deletions lib/middleware.js
@@ -1,10 +1,16 @@

/*!
* Express - middleware
* Copyright(c) 2010-2011 TJ Holowaychuk <tj@vision-media.ca>
* Copyright(c) 2010-2012 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/

/**
* Module dependencies.
*/

var utils = require('./utils');

/**
* Initialization middleware, exposing the
* request and response to eachother, as well
Expand All @@ -26,10 +32,7 @@ exports.init = function(app){
req.__proto__ = app.request;
res.__proto__ = app.response;

res.locals = function(obj){
for (var key in obj) res.locals[key] = obj[key];
return res;
};
res.locals = utils.locals(res);

next();
}
Expand Down
2 changes: 1 addition & 1 deletion lib/response.js
Expand Up @@ -627,7 +627,7 @@ res.render = function(view, options, fn){
}

// invoke view callbacks
var callbacks = app.viewCallbacks
var callbacks = app.viewCallbacks.concat(self.viewCallbacks)
, pending = callbacks.length
, len = pending
, done;
Expand Down
33 changes: 33 additions & 0 deletions lib/utils.js
Expand Up @@ -11,6 +11,39 @@

var mime = require('mime');

/**
* Make `locals()` bound to the given `obj`.
*
* This is used for `app.locals` and `res.locals`.
*
* @param {Object} obj
* @return {Function}
* @api private
*/

exports.locals = function(obj){
obj.viewCallbacks = obj.viewCallbacks || [];

function locals(obj){
for (var key in obj) locals[key] = obj[key];
return obj;
};

locals.use = function(fn){
if (3 == fn.length) {
obj.viewCallbacks.push(fn);
} else {
obj.viewCallbacks.push(function(req, res, done){
fn(req, res);
done();
});
}
return obj;
};

return locals;
};

/**
* Check if `path` looks absolute.
*
Expand Down
104 changes: 104 additions & 0 deletions test/res.locals.use.js
@@ -0,0 +1,104 @@

var express = require('../')
, request = require('./support/http');

describe('res', function(){
describe('.locals.use(fn)', function(){
it('should run in parallel on res.render()', function(done){
var app = express();
var calls = [];
app.set('views', __dirname + '/fixtures');

app.locals.first = 'tobi';

app.use(function(req, res, next){
res.locals.use(function(req, res, done){
process.nextTick(function(){
calls.push('one');
res.locals.last = 'holowaychuk';
done();
});
});
next();
});

app.use(function(req, res, next){
res.locals.use(function(req, res, done){
process.nextTick(function(){
calls.push('two');
res.locals.species = 'ferret';
done();
});
});
next();
});

app.use(function(req, res){
calls.push('render');
res.render('pet.jade');
});

request(app)
.get('/')
.end(function(res){
calls.should.eql(['render', 'one', 'two']);
res.body.should.equal('<p>tobi holowaychuk is a ferret</p>');
done();
})
})

describe('with arity < 3', function(){
it('should done() for you', function(done){
var app = express();

app.set('views', __dirname + '/fixtures');
app.locals.first = 'tobi';

app.use(function(req, res, next){
app.locals.use(function(req, res){
res.locals.last = 'holowaychuk';
res.locals.species = 'ferret';
});
next();
});

app.use(function(req, res){
res.render('pet.jade');
});

request(app)
.get('/')
.end(function(res){
res.body.should.equal('<p>tobi holowaychuk is a ferret</p>');
done();
})
})
})

it('should not override res.render() locals', function(done){
var app = express();

app.set('views', __dirname + '/fixtures');
app.locals.first = 'tobi';

app.use(function(req, res, next){
app.locals.use(function(req, res){
res.locals.last = 'holowaychuk';
res.locals.species = 'ferret';
});
next();
});

app.use(function(req, res){
res.render('pet.jade', { last: 'ibot' });
});

request(app)
.get('/')
.end(function(res){
res.body.should.equal('<p>tobi ibot is a ferret</p>');
done();
})
})
})
})

0 comments on commit dd33ef2

Please sign in to comment.