はじめに
Expressでテンプレートエンジンejsを使った実装をする時に、ejs内ではExpressのlocalsを参照できるという事を知ったので、具体的にどうなるのか?を少しまとめてみた。
ejs内ではexpressのapp.localsやres.localsのlocalsを参照できる
res.render(view [, locals] [, callback])には、
locals, an object whose properties define local variables for the view(ビューのローカル変数を定義するプロパティを持つオブジェクト).
と書かれているので、あくまでres.render()の第二引数に渡す値のみがテンプレートエンジン内(ejs)で使えるのかと思っていたが、実際にはejs内ではlocals
というオブジェクトに、res.render()の第二引数のオブジェクトと、expressのlocals(app.localsやres.localsのlocals)に定義済みのオブジェクトが全て組み込まれており、それらがすべて使える。
実際に、以下のようなソースを書いてみた時にの画面の描画内容からもこの事は確認できた。
<body>
...
<% for (let local of Object.keys(locals)) { %>
<li><%= local %></li>
<% } %>
...
</body>
↑ は、以下の実装において、app.locals.pool
やapp.locals.fsSql
、res.locals.moment
やres.locals.padding
という設定をしていることにより、locals内にpool
・fsSql
・moment
・padding
などが存在している。また、その他のid
、name
などは、SQLの戻り値として返ってきたもので、res.render()の第二引数に渡しているので存在している。
※padding
は関数であるが、これはexpressのres.localsには変数(値)だけでなく、オブジェクトや関数を渡す事もできるので、ejs内でlocals内に定義した関数を呼び出す事も可能。関数をejs内で呼び出す例としては、ここを参照。また、関数をres.localsに定義している部分は、ここを参照(locals
を明示的に書いているが、省略してpadding
とする事も可能)。
// https://github.com/yuta-katayama-23/post-restaurant-reviews/blob/657bfebd338886c532a32f80b65146543de75623/src/lib/database/client.js#L7
app.locals.pool = pool;
app.locals.fsSql = new SqlQueryLoader({
path: 'src/lib/database/sqls'
});
// https://github.com/yuta-katayama-23/post-restaurant-reviews/blob/657bfebd338886c532a32f80b65146543de75623/src/app.js#L22
app.use((req, res, next) => {
res.locals.moment = moment;
res.locals.padding = padding;
next();
});
// https://github.com/yuta-katayama-23/post-restaurant-reviews/blob/657bfebd338886c532a32f80b65146543de75623/src/routes/shops.js#L14
try {
const [rows] = await pool.query(
fsSql.readSync('tran_shops', 'SELECT_SHOP_DETAIL_BY_ID'),
[id]
);
res.render('./shops/index.ejs', rows.shift());
} catch (err) {
next(err);
}
※ソースコードの全体は以下。
※expressのapp.locals
については、app.localsを参照。