ニフクラmBaaSお役立ちブログ

スマホアプリ開発にニフクラmBaaS。アプリ開発に役立つ情報をおとどけ!

mBaaSを使ってブログを作る(その1)「投稿&一覧表示」

mBaaSというとモバイルアプリ向けというイメージが強いですが、それ以外の用途でも利用できます。例えばmBaaSのデータベースにはMongoDBが採用されており、実際その操作もMongoDBのオペランドが利用できるなど、近いものがあります。

MongoDBを使ったWebアプリケーションを作る場合、MongoLabなどを使っているのではないでしょうか。それらのサービスに接続する際にはHTTPS経由で接続します。それはニフティクラウド mobile backendでも同じです。

そこでサーバサイドのデータベース部分にmBaaSを使ったらどうなるのか、コードを使って紹介します。今回はブログを作ってみます。

言語はNode.js

サーバサイドに対応しているSDKとしてJavaScript SDKが挙げられます(非公式であればRubyもあります)。そこでNode.jsでWebアプリケーションフレームワークとしてExpressを用いて開発を行っていきます。

Express Generatorを使うとベースが簡単に作れます。

$ npm install express-generator -g
$ express ncmb_blog_nodejs -e # テンプレートエンジンをejsにしています
$ cd ncmb_blog_nodejs
$ npm install
$ npm install ncmb --save

Bowerでライブラリを管理

今回は表示にBootstrapを使います。そこでBowerを使ってライブラリを追加します。Bowerはnpmを使ってインストールできます。その際、デフォルトのインストール先ではなく public/vendors 以下にインストールしたいのでプロジェクトルートに .bowerrc を作成します。

{
  "directory": "public/vendors"
}

そしてライブラリをインストールします。

$ bower init
$ bower install bootstrap --save

新規投稿ページの作成

URLは /posts/new とします。そこで app.js を編集します。

var posts = require('./routes/posts'); // 追加
  :
app.use('/users', users);
app.use('/posts', posts); // 追加

次に routes/posts.js を追加します。

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/new', function(req, res, next) {
  res.render('posts/new');
});

module.exports = router;

最後に views/posts/new.ejs を追加します。

<!DOCTYPE html>
<html>
  <head>
    <title>新規投稿</title>
    <link rel='stylesheet' href='/vendors/bootstrap/dist/css/bootstrap.min.css' />
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="col-md-8 col-md-offset-2">
          <h1>新規投稿</h1>
          <p>新しいブログ記事を書きます</p>
          <form id="post_form">
            <div class="form-group">
              <label for="inputTitle">記事のタイトル</label>
              <input type="text" class="form-control" id="inputTtitle" name="title" placeholder="Post title">
            </div>
            <div class="form-group">
              <label for="inputBody">記事の内容</label>
              <textarea id="body" class="form-control" cols="50" rows="10" name="body"></textarea>
            </div>
            <button type="submit" class="btn btn-default">投稿</button>
          </form>
        </div>
      </div>
    </div>
    <script src='/vendors/jquery/dist/jquery.min.js'></script>
    <script src='/vendors/bootstrap/dist/js/bootstrap.min.js'></script>
    <script src='/javascripts/app.js'></script>
  </body>
</html>

これで投稿画面ができあがりました。

投稿処理を作る

投稿処理はAjaxで行います。 public/javascripts/app.js を作成します。以下のようにフォームの送信イベントを使います。投稿がうまくいったらトップページにリダイレクトします。

$('#post_form').on('submit', function(e) {
  e.preventDefault();
  var data = $(this).serialize();
  $.ajax({
    url: '/posts',
    type: 'POST',
    data: data
  })
  .then(function(data) {
    location.href = "/";
  },
  function(err) {
    console.error(err);
  });
  
})

NCMBの読み込み

NCMBの読み込みは多くのコードから行いますので、都度アプリケーションキーなどを記載するのは面倒です。そこで、プロジェクトルートに config.js を作成します。内容は次のようにアプリケーションキー(application_key)とクライアントキー(client_key)が入ったオブジェクトです。

const config = {
  application_key: "d4...ca",
  client_key: "89...a0"
}
module.exports = config;

このファイルを libs/ncmb.js を作成して、そこで読み込みます。

var NCMB = require('ncmb');
var config = require('../config');

var ncmb = new NCMB(config.application_key, config.client_key);
module.exports = ncmb;

後はこの libs/ncmb.js をmBaaSを利用するファイルから読み込むだけです。

var ncmb   = require('../libs/ncmb');

これでアプリケーションキー、クライアントキーが適用済みのNCMBオブジェクトが取得できるようになります。OAuth2や認証情報など、他でも使う情報を扱う際にはこの手法が便利です。

投稿処理を作る

ではサーバサイドの投稿処理を作ります。 routes/posts.js を編集します。内容としてはPOSTメソッドを受け取り、データストアに対してPostという名前のクラスでブログのコンテンツを投稿します。

var ncmb   = require('../libs/ncmb');

router.post('/', function(req, res, next) {
  let Post = ncmb.DataStore('Post');
  var post = new Post;
  post.set('title', req.body.title);
  post.set('body', req.body.body);
  post.save()
    .then(function(obj) {
      res.status(201).json(obj);
    })
    .catch(function(err) {
      res.status(401).json(err);
    })
});

保存処理がうまくいった場合は201、失敗した場合はエラーメッセージを返します。

一覧表示を作る

ブログの投稿がうまくいったら、次は一覧表示を行います。この修正は routes/index.js に対して行います。ブログは最新のものが上に表示されますので、orderを使って並べ替えを指定します。後はデータが取れたら、それを使ってレンダリング処理を行います。

var ncmb = require('../libs/ncmb');

/* GET home page. */
router.get('/', function(req, res, next) {
  var Post = ncmb.DataStore('Post');
  Post.order('createDate', true).fetchAll()
    .then(function(posts) {
      res.render('index', { posts: posts });
    })
});

module.exports = router;

最後に表示画面を用意します。これは views/index.js になります。

<!DOCTYPE html>
<html>
  <head>
    <title>ブログ</title>
    <link rel='stylesheet' href='/vendors/bootstrap/dist/css/bootstrap.min.css' />
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="col-md-8 col-md-offset-2">
          <div class="row">
            <div class="col-md-10">&nbsp;
            </div>
            <div class="col-md-2">
              <a href="/posts/new" class="btn btn-info">新規投稿</a>
            </div>
          </div>
          <% for (var i = 0; i < posts.length; i++) { %>
            <% var post = posts[i]; %>
            <div class="row">
              <h2><a href="/posts/<%= post.objectId %>"><%= post.title %></a></h2>
            </div>
          <% } %>
        </div>
      </div>
    </div>
    <script src='/vendors/jquery/dist/jquery.min.js'></script>
    <script src='/vendors/bootstrap/dist/js/bootstrap.min.js'></script>
    <script src='/javascripts/app.js'></script>
  </body>
</html>

詳細表示画面を作る

一覧表示において、各記事タイトルに詳細ページへのリンクを追加しています。

<a href="/posts/<%= post.objectId %>"><%= post.title %></a>

利用しているのはユニークなobjectIdです。このリンクをクリックした時の処理として、まずは routes/posts.js を修正します。

router.get('/:objectId', function(req, res, next) {
  let Post = ncmb.DataStore('Post');
  Post.equalTo('objectId', req.params.objectId)
    .fetch()
    .then(function(post) {
      res.render('posts/show', { post: post });
    });
});

一覧ページとは異なり、特定のデータだけが欲しいので検索条件を追加しています。equalToを使ってオブジェクトIDを指定してデータを取得しています。結果が返ってきたら、そのデータをレンダリングに使っています。

表示は views/posts/show.ejs になります。内容は次の通りです。

<!DOCTYPE html>
<html>
  <head>
    <title>ブログ <%= post.title %></title>
    <link rel='stylesheet' href='/vendors/bootstrap/dist/css/bootstrap.min.css' />
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="col-md-8 col-md-offset-2">
          <a href="/">Top</a>
        </div>
        <div class="col-md-8 col-md-offset-2">
          <h1><%= post.title %></h1>
          <div>
            <%= post.body %>
          </div>
        </div>
      </div>
    </div>
    <script src='/vendors/jquery/dist/jquery.min.js'></script>
    <script src='/vendors/bootstrap/dist/js/bootstrap.min.js'></script>
    <script src='/javascripts/app.js'></script>
  </body>
</html>

これでブログとしての一通りの機能が揃いました。起動する際には DEBUG=ncmb_blog_nodejs:* npm start と実行します。

トップページにアクセスすると、最初は何もありません。

新規投稿をクリックして記事を書きます。

投稿ボタンを押して保存が完了するとトップページに戻ります。今投稿した記事が表示されるはずです。

記事のタイトルをクリックすると、記事詳細ページに遷移します。


まずブログの基礎を作るところまでできあがりました。これをベースに、次は認証を組み込んでみたいと思います。

MongoDBをそのままJavaScriptから扱うのに比べてSDKがある分、使いやすいでしょう。また、プッシュ通知や認証など通常のMongoDBで行うのが面倒な仕組みもあらかじめ用意されているのが利点です。

今回のコードはNCMBMania/ncmb_blog_nodejsにアップロードしてあります。不明点があれば参考にしてください。