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?
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!)
Quick response :
for url in urls
app.get "/html/#{url}.html", (req,res) ->
res.render req.params.url