node.jsのwebアプリケーションフレームワークであるexpressで、ORMのSequelizeを使ってみる
環境
ArchLinux : バージョンは多分現在の最新
MariaDB : 5.5.32 (MySQLの姉妹実装。archlinuxではこれが公式となる)
node.js : 0.10.9
express : 3.3.4
sequelize : 2.0.0
node-mysql : 2.0.0
expressのインストール
npm install -g express
- gオプションをつけてグローバルインストールしておく
expressアプリケーションの作成
express ormtest -c css
これでormtestというディレクトリが作られ、中にアプリのガラが作られる
package.jsonにmysqlとsequelizeの追記をしてモジュールをインストールする
{ "name": "application-name", "version": "0.0.1", "private": true, "scripts": { "start": "node app.js" }, "dependencies": { "express": "3.3.4", "jade": "*", "css": "*", "mysql": "*", "sequelize": "*" } }
ディレクトリ構成はこんな感じに
. ├── app.js ├── node_modules │ ├── css │ ├── express │ ├── jade │ ├── mysql │ └── sequelize ├── package.json ├── public │ ├── images │ ├── javascripts │ └── stylesheets ├── routes │ ├── index.js │ └── user.js └── views ├── index.jade └── layout.jade
ここで主なファイル/ディレクトリの説明をざっとしておく
app.js: アプリケーションの起動ファイル。アプリケーションで使うミドルウェアや、ルーティングなどを定義する
package.json: 依存モジュールを書くファイル。RailsでいうGemfileに相当
routes: app.jsで設定したルーティングに沿ってアクションを定義するファイルを置くディレクトリ
各ファイルはRailsでいうContorollerに相当する
views: routes以下のファイルで呼び出すHTMLテンプレートを置くディレクトリ
expressではデフォルトのレンダリングエンジンはjadeとなっている
これ以上のexpressの説明は本エントリの主旨から若干外れるので割愛
下記コマンドを実行して起動を確認する
node app.js
ブラウザからhttp://localhost:3000/にアクセスしてexpressの画面が表示されれば成功
Sequelizeを使う
デフォルトではモデル用のディレクトリがないのでディレクトリを作成する
mkdir models
この配下にモデルを書く
今回はシンプルに名前とemailを持つuserモデルを書いてみる
models/user.js
var Sequelize = require('sequelize'); var Seq = new Sequelize('DBNAME', 'DBUSER', 'DBPASS',{ host: 'localhost', port: 3306 }); var User = Seq.define('User', { name: Sequelize.STRING, email: { type: Sequelize.STRING, validate: {isEmail: true} } }); //Seq.sync(); exports.User = User;
DBNAME,DBUSER,DBPASSは各環境ごとに設定が必要
Seq.sync()の行を有効にするとDBに定義をしてくれる
本来はここに書くべきではないかも
routes/index.js
/* * GET home page. */ exports.index = function(req, res){ var User = require('../models/user').User; var new_user = User.build({ name: "test", email: "hoge@example.com" }); new_user.save().success(function(){ var show_user; User.find({ where: {name: "test"} }).success(function(user){ show_user = { name: user.name, email: user.email }; res.render('index', { title: 'Express',show_user: show_user }); }); }); };
index.jsではmodelを呼び出して新しく値をsaveし、さらに今saveしたデータを引っ張ってきてviewに渡すということをする
ここで、saveのcallbackであるsuccessの中でfindするのがポイント
saveでコールバックを受けずにfindするとsaveが終わる前にfindしてしまってデータが見つからないということが起きる
nodeは非同期でメソッドを実行するのでこのような事が起こる
この事に気づくまで2時間ほど悩みまくったorz
あと、findのsuccessの中でshow_user = userなどとしても正しくデータがとれない
どうやら定義したまんまのUserモデルが返ってくるわけではないらしい
また、saveしたデータは実際にはid,createdAt,updatedAtというカラムが追加され下記の様になっている
MariaDB [DBNAME]> select * from Users; +------+------------------+----+---------------------+---------------------+ | name | email | id | createdAt | updatedAt | +------+------------------+----+---------------------+---------------------+ | test | hoge@example.com | 1 | 2013-08-05 13:37:18 | 2013-08-05 13:37:18 | +------+------------------+----+---------------------+---------------------+
views/index.jade
extends layout block content h1= title p Welcome to #{title} p #{show_user.name} p #{show_user.email}
viewでは持ってきたデータをシンプルに表示してみる
以下のように表示された
Sequelizeでは他にもModelメソッドを定義したり、今回のemailのフィールドで定義したようなバリデータも使えるなどまだまだ機能が豊富なようだ
node.js関連のドキュメントではありがちだが、seauelizeも2.0.0系から変わったのか古いドキュメントのコードをそのまま使っても動かないことが多かった
公式ドキュメントを参考にすることをお勧めする