Bien, el caso de uso es el siguiente: tenemos varios templates en los que queremos mostrar mensajes al usuario si los hubiera.
Lo normal seria hacer algo así a la hora de renderizar un template:
Para la página principal:
app.get('index', function (req, res) {
var messages = req.flash();
var render_options = {
titulo: "Página principal"
};
if (messages.error || messages.info || messages.success) {
if (messages.error) messages.hasError = messages.error.length > 0;
if (messages.info) messages.hasInfo = messages.info.length > 0;
if (messages.success) messages.hasSuccess = messages.success.length > 0;
render_options.messages = messages;
}
res.render('index', render_options);
});
Para la página del usuario:
app.get('user', function (req, res) {
var messages = req.flash();
var render_options = {
titulo: "Perfil de " + req.session.user.name
};
if (messages.error || messages.info || messages.success) {
if (messages.error) messages.hasError = messages.error.length > 0;
if (messages.info) messages.hasInfo = messages.info.length > 0;
if (messages.success) messages.hasSuccess = messages.success.length > 0;
render_options.messages = messages;
}
res.render('index', render_options);
});
Bien, la idea se aprecia, constantemente tenemos que trabajarnos la variable “messages” y si hay mensajes la incluimos en las opciones de renderizado del template.
¿El inconveniente? el código se repite, lo que lo hace poco mantenible y ensucia. Solo por dar un ejemplo, podés ver que estamos preparando errores del tipo “error“, “info” y “success“, y si quisieras agregar un nuevo tipo de error llamado “warning“, te las verías p… negras. Bueno se entiende el inconveniente.
Solución: Encapsular en un preprocesador
Express nos da la posibilidad de preparar variables que van a parar al template haciendo uso de app.use() y res.locals.
NOTA importante: da igual el sistema de templates que uses: Jade, Hogan.js, Mustache, Handlebars, etc. Express es agnóstico en este sentido a la hora de preparar variables. Un puntazo.
Bueno, como decía, podemos agregar un app.use() en app.configure(function () {}); (suele estar en app.js, la base de tu aplicación).
Acá está el ejemplo. Hemos quitado la lógica de tratamiento de mensajes y la hemos colocado en este middleware (si, es uno de esos famosos):
app.use(function (req, res, next) {
var messages = req.flash();
if (messages.error || messages.info || messages.success) {
if (messages.error) messages.hasError = messages.error.length > 0;
if (messages.info) messages.hasInfo = messages.info.length > 0;
if (messages.success) messages.hasSuccess = messages.success.length > 0;
res.locals.messages = messages;
}
next();
});
Lo mas notable del código anterior es que hemos asignado el resultado a res.locals.messages. res.locals, va a “mergearse” con las variables que uses en res.render() antes de llamar al template.
NOTA: next(); es necesario para que el flow de ejecución siga adelante.
Hecho lo anterior, les presento las versiones simplificadas de los ejemplos que di al principio:
app.get('index', function (req, res) {
var render_options = {
titulo: "Página principal"
};
res.render('index', render_options);
});
app.get('user', function (req, res) {
var render_options = {
titulo: "Perfil de " + req.session.user.name
};
res.render('index', render_options);
});
Mucho mejor ¿no?
Chau!