2

I just inherited a project with node.js/express written in coffeescript and using jade to render views. In my views folder I have about 20 jade files that need to have routes set up. Rather than repeat myself over and over like so (which is currently working just fine):

app.get '/html/404.html', (req,res) ->
  res.render '404',

app.get '/html/503.html', (req,res) ->
  res.render '503', 

app.get '/html/foo.html', (req,res) ->
  res.render 'foo', 

I'd prefer to keep this less messy by creating an array of the urls and using a for loop to iterate over it, something like this:

urls = [
  "404"
  "503"
  "foo"
]

for url in urls
  app.get "/html/#{url}.html", (req,res) ->
    res.render "#{url}",

Unfortunately this isn't working. Any advice?

satyrsynth
  • 399
  • 1
  • 4
  • 14

2 Answers2

3

This is a classic problem that happens when you define a closure in a loop in JavaScript: You expect the value of url in your route function to be whatever it was when you defined that function, but in fact, it's whatever the last value in the loop was. There's only one url variable, after all.

The fix is to "capture" that variable in an outer closure, which is why CoffeeScript has the do syntax:

for url in urls
  do (url) ->
    app.get "/html/#{url}.html", (req,res) ->
      res.render "#{url}"

For more on this, see my PragPub article A CoffeeScript Intervention.

(Having said this, Arnaud's suggestion of using an Express param in the route is a much more elegant solution. If you can avoid a loop entirely, do so!)

Trevor Burnham
  • 76,828
  • 33
  • 160
  • 196
  • Thanks Trevor! I was just about to post the same answer from my coworker regarding this. Another related article: http://rzrsharp.net/2011/06/27/what-does-coffeescripts-do-do.html – satyrsynth Jun 15 '12 at 15:07
1

Quick response :

for url in urls
  app.get "/html/#{url}.html", (req,res) ->
    res.render req.params.url
Arnaud Rinquin
  • 4,296
  • 1
  • 30
  • 51