@ledsun blog

無味の味は佳境に入らざればすなわち知れず

YEOMANを使ってMEAN(MongoDB + Express.js + Angular.js + Node.js)のWebアプリケーションを作る

MEANとは

MongoDB + Express.js + Angular.js + Node.js を組み合わせてWebアプリケーションを作成することです。

手順

Windows上で簡単なユーザ登録アプリケーションを作ってみましょう。 次の手順で進めていきます。

  1. アプリケーションの雛形を作成
  2. ユーザページを追加
  3. htmlを修正してユーザ一覧を追加
  4. クライアントのJavaScript(Angular.js)を修正
  5. サーバのJavaScript(Express.js)を修正
  6. MongoDBを参照
  7. ユーザの登録機能を追加

完成したものはGitHubにおいてあります。 Chocolatey本体のインストール以外はMinGW Bash*1で実行可能です。

事前準備

ChocolateyでMongoDBとNode.jsをインストールします。Chocolateyをインストールしていなかったら次のコマンドを実行してください。

@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%systemdrive%\chocolatey\bin

MoongDBのインストール

cinst gb.MongoDB

Node.jsのインストール

cinst nodejs.install

YOEMANのインストール

YOEMANはGruntとBowerを使用します。一緒にインストールします。

npm install -g yo grunt-cli bower
npm install -g generator-angular-fullstack

※執筆時点のgenerator-angular-fullstackのバージョンは1.0.1でした。2014年1月16日の時点で既に1.2.1までバージョンが上がっています。

RubyCompassのインストール

generator-angular-fullstackはCompassを使用するのでRubyCompassをインストールします。

cinst ruby
gem install compass

アプリ作成

YOEMANを使ってアプリケーションの雛形を作ります。  

mkdir register-user && cd $_
yo angular-fullstack register-user

いろいろ聞かれるのですべてをYにする

  • Twiiter Bootstarp
  • SCSS
  • angularのモジュール4つ
  • MongoDB デフォルトがNなので注意

起動確認

grunt serve

YOMENで生成されたアプリケーションがブラウザで起動します

f:id:ledsun:20131227115044p:plain

固定のユーザ一覧を表示をする

ページを追加する

Ctrl + C でgruntを一度止め、次のコマンドを実行します。

yo angular-fullstack:route user
grunt serve 

http://localhost:9000/user が開けるようになります。

f:id:ledsun:20131227115217p:plain

ユーザ一覧を追加

app/views/partials/user.html を編集します。

<h2>ユーザ一覧</h2>
<ul>
    <li ng:repeat="user in users">
        {{user.name}}
    </li>
</ul>

f:id:ledsun:20131227122406p:plain

ダミーのユーザを表示

app/scripts/controllers/user.js の5~7行目を編集します。

before

    $http.get('/api/awesomeThings').success(function(awesomeThings) {
      $scope.awesomeThings = awesomeThings;
    });

after

    $http.get('/api/awesomeThings').success(function() {
      $scope.users = [{name:'田中'},{name:'鈴木'}];
    });

f:id:ledsun:20131227122509p:plain

サーバのAPIを作成

lib/controllers/api.jsの最後に次のコードを追記します。

exports.users = function(req, res) {
  return res.json([{name:'田中_1'},{name:'鈴木_1'}]);
};

ルートディレクトリにある、server.js の Server Routes のブロックに次の行を追記します。

app.get('/api/users', api.users);

http://localhost:9000/api/usersJSONが取得できるようになります。

f:id:ledsun:20140109113551p:plain

APIに接続

app/scripts/controllers/user.js の5~7行目をもう一度編集します。

    $http.get('/api/users').success(function(users) {
      $scope.users = users;
    });

http://localhost:9000/userAPI版のユーザ情報が出ます。

f:id:ledsun:20131227122946p:plain

MongoDBと接続

lib/models/user.jsを作る

'use strict';

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;
    
// Schema
var UserSchema = new Schema({
  name: String
});

mongoose.model('User', UserSchema);

lib/db/dummydata.jsの末尾に追記します。

var User = mongoose.model('User');
User.find({}).remove(function() {
    User.create({
        name: '田中_2'
    }, {
        name: '鈴木_2'
    }, function(err) {
        console.log('finished populating Users');
    });
});

lib/controllers/api.jsをMongoDBを参照するように修正します。

exports.users = function(req, res) {
    mongoose.model('User').find(function(err, users) {
        if (!err) {
            return res.json(users);
        } else {
            return res.send(err);
        }
    });
};

http://localhost:9000/user に dummydata.js で MongoDB に登録したユーザー情報が出ます。

f:id:ledsun:20131227123158p:plain

ユーザの登録

ユーザ登録フォームを追加

ユーザ登録用に app/view/partial/user.htmlを書き換えてフォームを追加します。

<div ng-controller="UserCtrl">
    <h2>ユーザ登録</h2>
    <form >
        <legend>ユーザ登録</legend>
        <label>名前</label> 
        <input type="text" id="name" name="name" ng-model="user.name"> 
        <button class="btn btn-primary" ng-click="createUser()">登録</button>
    </form>

    <h2>ユーザ一覧</h2>
    <ul>
        <li ng:repeat="user in users">
            {{user.name}}
        </li>
    </ul>
</div>

http://localhost:9000/user にフォームが表示されます。

f:id:ledsun:20131227130559p:plain

登録ボタンのイベントハンドラを設定

この時点ではボタンがまだ動作しないのでイベントハンドラを設定します。

app/script/controllers/user.js に$scope.createUser関数を追加します。

'use strict';

angular.module('registerUserApp')
    .controller('UserCtrl', function($scope, $http) {
        $http.get('/api/users').success(function(users) {
            $scope.users = users;
        });

        $scope.createUser = function() {
            if ($scope.user && $scope.user.name) {
                $scope.users.push({
                    name: $scope.user.name
                });
                $scope.user.name = '';
            }
        };
    });

名前欄に名前を入力し、登録ボタンを押すと一覧にユーザを追加します。

f:id:ledsun:20131227131159p:plain

ユーザ登録用のPOST APIを作成

まだ、サーバには保存できていません。ブラウザをリロードすると登録したユーザは消えてしまいます。 ユーザ登録用のPOST APIを作成します。

lib/controllers/api.jsの最後に追記します。

exports.createUser = function(req, res) {
    var User = mongoose.model('User');
    new User({
        name: req.body.name
    }).save(function() {
        res.end();
    });
};

server.js の Server Routes のブロックに追記します。

app.post('/api/users', api.createUser);

app/script/controllers/user.js のイベントハンドラを修正します。

      $scope.createUser = function() {
            if ($scope.user && $scope.user.name) {
                $http({
                    method: 'POST',
                    url: '/api/users',
                    data: $scope.user
                }).success(function() {
                    $scope.users.push({
                        name: $scope.user.name
                    });
                    $scope.user.name = '';
                });
            }
        };

これで登録したユーザがMongoDBに保存されるようになりました。*2

参考リンク

Full-Stack JavaScript With MEAN And Yeoman にMEAN用のGeneratorがいくつか紹介されています。

おわりに

今回の作業で特に良いと思う点

  • YOEMANでアプリケーションの雛形を作る簡単さ
  • 画面をデザインするために作ったJSONファイルをそのままDBに保存できる統一感

すごくいいです。

*1:Git for WindowsでインストールされるGit BashMinGW Bashです。

*2:gurnt serve でサーバを再起動すると dummydata.js が実行されてデータは削除されます。