express 3.x のダイナミックヘルパの書き方 [Node.js]

f:id:u-jiro:20130512151951p:plain
express 3.x で、ダイナミックヘルパが app.locals.use に変更になったらしいので使おうとしたら怒られました。ダイナミックヘルパにはミドルウェアを使うようです。

問題

express 3.x でも app.locals.use は存在しないようです。

2.x

まずは express 2.x までの書き方。

routes/login.js

index:  (req, res) ->
  res.local 'resources', [
    { type: 'css',        uri: '/stylesheets/login.css' }
    { type: 'javascript', uri: '/stylesheets/login.js' }
  ]
  res.render 'login'

app.js

app.dynamicHelpers
  resources: (req, res) ->
    return res.local('resources') || []

3.x

次に express 3.x で、失敗した書き方。
日本最速express3入門 の情報をもとに、app.locals.use を使ってみる。

app.js

app.locals.use (req, res) ->
  app.locals.resources = res.local('resources') || []

しかし下記エラーが発生する。
app.locals.use は無いらしい...?

/Users/tu/workspace/express/fileupload/app.coffee:42
  app.locals.use(function(req, res) {
             ^
TypeError: Object function locals(obj){
    for (var key in obj) locals[key] = obj[key];
    return obj;
  } has no method 'use'
    at Object.<anonymous> (/Users/tu/workspace/express/fileupload/app.coffee:42:14)
    at Object.<anonymous> (/Users/tu/workspace/express/fileupload/app.coffee:61:4)
    at Module._compile (module.js:449:26)
    at Object.loadFile (/Users/tu/workspace/express/fileupload/node_modules/coffee-script/lib/coffee-script/coffee-script.js:179:19)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:362:17)
    at require (module.js:378:17)
    at Object.<anonymous> (/Users/tu/workspace/express/fileupload/server.js:2:1)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:492:10)
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)
DEBUG: Program node server.js exited with code 1

解決方法

express 3.0 how to use app.locals.use and res.locals.use の情報を元に、ミドルウェアにする。
また、res.locals に従って、res からの取得方法も変更する。

routes/login.js

index:  (req, res) ->
  res.locals.resources = [
    { type: 'css',        uri: '/stylesheets/login.css' }
    { type: 'javascript', uri: '/stylesheets/login.js' }
  ]
  res.render 'login'

app.js

resources = (req, res, next) ->
  app.locals.resources = res.locals.resources || []
  next()

app.use resources

できたー!
バージョン差分怖い・・・。