MVCアプリケーションを作る際、コントローラ(C)とビュー(V)は前回紹介したexpress-resourceが面倒を見てくれる。REST APIの場合はビューと呼ぶほどのものではないが、APIの出力形式をXML、JSONと複数対応するにはコンテントネゴシエーションが強力なビュー機能を提供してくれると言える。
さて、今回はモデル(M)に相当する部分を作る際に欠かせないSequelizeを紹介しよう。 Sequelizeを使うと、DBのスキーマやデータを、node.jsアプリケーション内でJavaScriptオブジェクトとして扱えるようになる。いわゆるO/Rマッパーを実現してくれる。MySQL、SQLite、 PostgreSQLと主なオープンソースのRDBMSはサポートされており、RDBMS毎に微妙に異なるSQLの方言などを吸収してくれるので、仮に開発過程でRDBMSを乗り換えることがあったとしても、アプリ側のコードに大掛かりな修正が生じなくて済む。
早速インストールしてみる。前回のpackage.jsonを引き続き編集してsequelizeを追加したら、npm installを実行する。
{
"name": "application-name"
, "version": "0.0.1"
, "private": true
, "dependencies": {
"express": "2.5.8"
, "express-resource": "latest"
, "sequelize": "latest"
, "jade": ">= 0.0.1"
}
}
続いて、app.jsでSequelizeをインスタンス化するコードを追加する。
var express = require('express')
, resource = require('express-resource')
, Sequelize = require('sequelize')
, app = module.exports = express.createServer();
sequelize = new Sequelize('database', 'username', 'password');
app.resource('users', require('./routes/users'), { id: 'id' });
と、サンプルではこう書かれることが多いが、データベースの接続情報をapp.jsにハードコーディングするのはまったく実用的ではない。production版かdevelopment版かによって環境が変わるのが普通なので、データベースの接続情報は別の設定ファイルに書くようにしたい。
そこで、node-configをインストールする。再度、package.jsonを編集してnpm installを実行しよう。
{
"name": "application-name"
, "version": "0.0.1"
, "private": true
, "dependencies": {
"express": "2.5.8"
, "express-resource": "latest"
, "sequelize": "latest"
, "config": "latest"
, "jade": ">= 0.0.1"
}
}
モジュール名はnode-configだが、NPMに登録されているパッケージ名は単にconfigなので注意。
node-configは、configディレクトリ内にある以下のファイルを順に読み込むようになっている。読み込むディレクトリは環境変数NODE_CONFIG_DIRで変更することもできる。
default.EXT hostname.EXT deployment.EXT hostname-deployment.EXT runtime.json
EXTの部分は設定ファイルの書式によって変わり、json、js、yaml、coffeeがサポートされている。設定をホスト名で分けることができるのは、痒いところに手が届く感じで嬉しい。
Sequelizeのコンストラクタに渡す引数を、config/development.jsonに書いておく。
{
"sequelize": {
"database": "test"
, "username": "h2plus"
, "password": "password"
, "options": {
"host": "localhost"
, "dialect": "mysql"
, "pool": {
"maxConnections": 5
, "maxIdleTime": 30
}
}
}
}
先ほどapp.jsでSequelizeのインスタンス化をするときに、optionsは渡していなかったが、Sequelizeの4番目のコンストラクタ引数で細かい設定オプションを渡すことができる。詳しくは本家のUsageに書いてあるが、MySQL限定でコネクションプーリングも使えるようだ。
めでたくデータベースの接続情報を設定ファイルに分離できたわけだが、Sequelizeをインスタンス化するコードをapp.jsに直接書きたくないので、自前で専用のモジュールを作ってしまおう。アプリケーションのディレクトリ構造はこんな感じになる。
myrest/ ├── app.js ├── config/ │ └── development.json ├── libs/ │ └── dbconn/ │ └── index.js ├── node_modules/ ├── package.json ├── public/ │ ├── images/ │ ├── javascripts/ │ └── stylesheets/ │ └── style.css ├── routes │ ├── index.js │ └── users.js └── views ├── index.jade └── layout.jade
libs/dbconn/index.jsには以下のようなコードを書く。
/**
* config.sequelize = {
* database: <string>
* , username: <string>
* , password: <string>
* , options: <object>
* };
*/
module.exports = function(config) {
var Sequelize = require('sequelize')
, params = config.sequelize || {};
params.options = params.options || {};
console.log('Sequelize connecting to %s on %s as %s', params.database, params.options.host || 'localhost', params.username);
return new Sequelize(params.database, params.username, params.password, params.options);
};
app.jsではSequelizeを直接インスタンス化せずに、このdbconnモジュールを使うようにする。
var express = require('express')
, resource = require('express-resource')
, config = require('config')
, sequelize = require('dbconn')(config)
, app = module.exports = express.createServer();
app.resource('users', require('./routes/users'), { id: 'id' });
スッキリ!
自前で作ったモジュールは、デフォルトではnode.jsは読み込んでくれないので、package.jsonを編集して、起動時に環境変数NODE_PATHで指定してやる。
{
"name": "application-name"
, "version": "0.0.1"
, "private": true
, "dependencies": {
"express": "2.5.8"
, "express-resource": "latest"
, "sequelize": "latest"
, "config": "latest"
, "jade": ">= 0.0.1"
}
, "scripts": {
"start": "NODE_PATH=libs node app.js"
}
}
package.jsonにscripts.startを書いておくと、通常のnode.jsの起動コマンド(node app.js)を使わずに、npm startでnode.jsを起動できるようになる。環境変数なんかを設定する場合はこっちの方が断然便利。
Sequelizeを使うための準備だけなのに、だいぶ長くなってしまったので中編に続く…
3 コメント