4.MVCアーキテクチャー
今回は、ExpressのスケルトンをベースにしてMVCアーキテクチャを構成しています。ご存知のようにMVCアーキテクチャーとは、ユーザーインターフェースを持つアプリケーションケーションの実装パターンのひとつで以下の3つから構成されます。
- Model (データやロジック)
- View (ユーザーインターフェース)
- Controller (入力を受け取りModelとViewをコントロールする)
Expressは制約の少ない柔軟なフレームワークなので、スケルトンをベースに様々な機能を加えていくときに、どのようにでも構成できてしまいます。そのような状況で、MVCは設計に明確な指針を与えてくれる存在でもあります。
4.1 スケルトンとMVC
Expressジェネレータが作成するスケルトンは下図のような構成でした。スケルトンの初期状態からMVCの「V」に相当するものは存在しています。
次に、Sequelize-CLIを使ってModelを作成した結果、下図のような状態になりました。(静的ファイルの図は省略します。)
この段階でMVCの「V」と「M」に相当するものができました。Contorollerはまだありませんが、その代わりにRouteのroutes/users.js
がその役割をしています。
4.2 今回のレッスンで作るもの
今回は、「C」のControllerを追加します。Controllerはその名の通り、ModelやViewをコントロールする存在で、Expressに導入する場合はRouteから呼び出してもらうように配置することができます。図解すると下図のようなイメージです。
また、ユーザーを表示するためのviewも新たに追加します。下図のピンク色の長方形の部分が今回追加する部分です。
そして、以下の3つの機能を実装します。
パス | 機能 | |
---|---|---|
機能1 | /users/ | 全ユーザーのリストを表示 |
機能2 | /users/:userId | ユーザーIDで指定されたユーザーを表示 |
機能3 | /uses/json | DBのデータをJSON形式で返す |
機能1の表示結果
機能2の表示結果
機能3の表示結果
4.2 MVCに関するディレクトリ
ディレクトリ構成としては、段階を追って以下のように変化します。
4.3 今回のスタート地点
今回のレッスンで新しい機能を実装する前に、現在のコード状況をもう一度整理しておきましょう。これまでのレッスンで./routes/users.jsファイルに2つのルートを追加した結果、現在は以下の3つのルートが存在しています。
パス | レスポンス内容 | |
---|---|---|
ルート1 | /users/ | “respond with a resource”と返す |
ルート2 | /users/:userId | “ok”と返す。 console.logでメッセージ出力。 |
ルート3 | /uses/json | DBのデータをJSON形式で返す |
./routes/users.js
全体としては以下のような状態です。現状ではレスポンスを返す処理などもこのファイルに実装されていますので、これらの部分をControllerに移すことにします。
1 | // |
このルーティングを以下のように変更します。
4.4 新しいルーティング実装
上記のように前回のレッスンでは./routes/users.js
にレスポンスを返す処理が実装されていましたが、これを、シンプルにコントローラを呼び出す形に変えます。
1 | // |
4.5 Controllerの仕様
今回作成するControllerは、以下の3つのメソッドを持つものとします。
パス | メソッド名 | レスポンス内容 | |
---|---|---|---|
メソッド1 | /users/ | showAllUsers | Viewを使って全ユーザーのリストを表示する。 |
メソッド2 | /users/:userId | showUserById | Viewを使って、ユーザー名を表示する。 |
メソッド3 | /uses/json | sendJson | DBのデータをJSON形式で返す |
4.6 Viewの実装
Controllerの実装を行う前に、Viewをあっさりと作ってしまいましょう。./views/フォルダの下に、ファイルを2つ作ります。
- allUsers.ejs メソッド1用のView。全ユーザーを表示する。
- oneUser.ejs メソッド2用のView。1人のユーザーを表示する。
先ず、メソッド1用のviewファイルをallUsers.ejs
という名前で以下のように作成します。この中で使われているusersという変数は、後ほどController側で用意します。
1 |
|
次に、メソッド2用のviewファイルをoneUser.ejs
という名前で以下のように作成します。この中で使われているuserという変数に関しても、後ほどController側で用意します。
1 |
|
4.7 Controllerの実装
それでは、Controllerを実装していきます。
先ず、Controllerモジュールの大枠を考えます。3つのメソッドを以下のように実装することにします。
1 | var userController = { |
余談になりますが、モジュールのメソッドを実装するときのスタイルはいろいろあり、例えば以下のAとBは同じように動作します。
1 | var foo = { |
1 | var foo = {}; |
また、今回のメソッドはどれもreq
、 res
、 next
の3つのパラメータを受け取るように設計してあります。
1 | function(req, res, next){ |
メソッド 1 : 全てのユーザーを表示する
それでは、/users/に対応する機能から取り組みます。前回のレッスンで、DBのデータをJSON形式で表示する機能を以下のように実装しました。
1 | // Sequelizeのモデルを使ってデータを取得する |
このコードの中でjsonを返している行を変更します。
1 | //変更前 |
res.render
はViewエンジンを使ってレンダリングするメソッドです。パラメータは2つあり、1つは使用するビューの名前、もうひとつはビューへ渡す情報です。Viewに渡す情報はJSON形式であれば内容は自由です。
1 | res.render("Viewファイル名", {Viewへ渡す情報}); |
この変更を反映すると、メソッド1は以下のようになります。
1 | // |
メソッド 2 : IDで指定されたユーザーを表示する
メソッド2は、ユーザーIDを受け取って、そのユーザーの情報を表示する処理です。前回のレッスンで学んだように、URL中のユーザーIDはリクエストオブジェクト(req)にセットされています。
1 | router.get('/:userId',function(req, res, next){ |
このようにして取得したユーザーIDを、SequelizeのfindByPk()
メソッドに渡して、指定ユーザーのデータを取得します。findByPk
のPk
というのはPrimary Key(主キー)のことです。背後では、SQLのSELECT文が実行されます。
1 | dbModels.User.findByPk(userId).then(user => { |
前回のレッスンでも触れましたが、Nodeのデータ取得は非同期で、SequelizeはPromiseを返すので、then(funcfiton(user){})
という形式で取得データを受け取ります。
1 | // |
メソッド 3 : DBのデータをJSON形式で返す
次に3つめのメソッドを実装します。3つめのメソッドは、DBから取得したユーザーのリストをJSONで返すものです。メソッドの中身の処理は前回のレッスンで実装したものと同じものです。
1 | sendJson: function(req, res, next) { |
以上3つのメソッドをまとめると、/controllers/user.js全体としては以下のようになります。
1 | // |
アプリを起動して確認する
それではアプリを起動して、3つの機能を確認してみましょう。
1 | $ npm start |
機能1
ブラウザで次のURLにアクセスします。
以下のようにユーザーの一覧が表示されれば成功です。
機能2
以下のURLにアクセスします。
機能2の表示結果
機能3
機能3の表示結果
まとめ
今回は、第2回のコードをベースにして、MVCの構成を作成しました。第2回のコードでは、Ruotes以下に実装していたロジックを、Controllerの部分にまとめることができました。