20

I want to display a flash message after a user fails to sign in but I just can't get the variables to show up in my Jade views.

I have some pieces, I know I have to use this in my app.configure():

    app.use (req, res, next) ->
      res.locals.session = req.session

And I'll set what the flash message is after the user POSTS the wrong password:

     exports.postSession = (req, res) ->
       users = require '../DB/users'
       users.authenticate(req.body.login, req.body.password, (user) ->
       if(user)
         req.session.user = user
         res.redirect(req.body.redirect || '/')
       else
         req.session.flash = 'Authentication Failure!'
         res.render('sessions/new', {title:'New', redirect: req.body.redirect })
      )

I don't know how to access res.locals.session in my Jade file. I doubt I am setting everything up right. This question is a lot like this one: Migrating Express.js 2 to 3, specifically app.dynamicHelpers() to app.locals.use? but I still can't get it to work. It would be much appreciated if someone could show me just a simple example of setting values in res.local and accessing them in a view.

p.s. I do know about connect-flash but I need to understand how to make things available in views.

This is my app:

app.configure(() -> 
  app.set('views', __dirname + '/views')
  app.set('view engine', 'jade')
  app.use(express.bodyParser())
  app.engine('.jade', require('jade').__express)
  app.use(express.methodOverride())
  app.use(express.cookieParser())
  app.use(express.session({ store: new express.session.MemoryStore({reapInterval: 50000 * 10}), secret: 'chubby bunny' }))
  app.use(express.static(__dirname + '/public'))
  app.use((req, res, next) ->
    res.locals.session = req.session
    next()
  )
  app.use(app.router)
)
Community
  • 1
  • 1
aeyang
  • 807
  • 4
  • 9
  • 18
  • p.p.s Also where is the documentation for this? I've been looking at [Migration guide](https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x), the [Express site](http://expressjs.com/api.html), and [Connect website](http://www.senchalabs.org/connect/) yet I still can't figure it out... Maybe its just me but I feel like I'm struggling to learn ExpressJS because its documentation is so sparse. – aeyang Sep 23 '12 at 05:55
  • you can't access it as `session.flash`? – Jonathan Ong Sep 23 '12 at 06:41
  • When i do this in jade: `- if(session.flash)` it gives me an error that says session is not defined.. But there is nothing off about how i set things up above? – aeyang Sep 23 '12 at 06:56
  • is your app.use about app.router or app[VERB]? – Jonathan Ong Sep 23 '12 at 19:17
  • i don't know the distinction between app.use being about app.router or app[VERB]. In my head its for the router as in these statements in app.use are evaluated against the immediate state of the server before a request gets routed... im not sure what app.use means in the context of app[VERB]. – aeyang Sep 23 '12 at 21:37
  • 1
    app[VERB] is anything like app.get app.post. these are all routes within app.use(app.router), which should be after any other `app.use` except any error handlers. what order are you putting them in? – Jonathan Ong Sep 23 '12 at 23:01
  • Oh Ok, my app.use(app.router) is definitely after my `app.use (req, res, next) -> res.locals.session = req.session`. So beyond the order of my app.use() statements, is this basically the way to create res.local variables? Also, I'm trying to access these res.local variables in my layout file. i don't think this is the problem, but are there restrictions on which views have access to your res.locals?? – aeyang Sep 23 '12 at 23:37
  • no there are not. can you just post your app? – Jonathan Ong Sep 24 '12 at 00:16
  • OK I posted my app. app.use(app.router) is below all of the middleware statements. – aeyang Sep 24 '12 at 01:07
  • remove `app.engine`. see what happens. you don't need it since you already did `app.set('view engine', 'jade')` – Jonathan Ong Sep 24 '12 at 01:40
  • Hey Jonathan. Thanks for your replies, I managed to fix my issue because I realized that I was doing redirect like this: `res.redirect('sessions/new',{title: 'New'})` I'm not even sure why that even brought the page up but res.redirect is supposed to be used like this now: `res.redirect([code,] url)` Anyways, stupid mistake on my part, thanks again for your attention. – aeyang Sep 24 '12 at 01:47
  • lol that wasn't in your code. and yeah a redirect should never have an object either. – Jonathan Ong Sep 24 '12 at 02:07

2 Answers2

38

Just to give a short summary for everyone who has the same problem and got the impression that is was solved changing res.redirect.

It is very important to put your app.use middleware before app.router. See the comments by TJ Holowaychuck, the author of express

Here is an example using a fresh installation of express v3.0.0rc4

app.js:

app.use(function(req, res, next){
  res.locals.variable = "some content";
  next();
})

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

index.jade:

extends layout

block content
  h1= title
  p Welcome to #{title}
  p= variable
zemirco
  • 16,171
  • 8
  • 62
  • 96
9

If you are using express.session() you must call your function AFTER express.session() but BEFORE app.router, inside of app.configure().

app.js

app = express();

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.session());

  // Give Views/Layouts direct access to session data.
  app.use(function(req, res, next){
    res.locals.session = req.session;
    next();
  });

  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

index.jade

extends layout

block content   
  h1= title   
  p My req.session.var_name is set to #{session.var_name}
Adam Albright
  • 5,917
  • 1
  • 21
  • 14