mBaaSを使って、Monacaテンプレート「おみくじアプリ」の拡張性を向上させる

#本記事の概要

mBaaSとMonacaを連携させる一例を示します。

今回はmBaaSとして
**Nifty cloud mobile backend** （以下NCMB）
http://mb.cloud.nifty.com/about.htm
を用いました。
（登録方法等は省略）

これを用いることにより、以下で述べるMonacaテンプレート「おみくじアプリ」の
拡張性を向上させることが出来ます。

#Monacaテンプレート「おみくじアプリ」とは

「開発をスタート」をクリックし、さらに「Monaca.ioで開発」をクリックするといくつかのテンプレートを選択することができます。

![monaca_start.png](https://qiita-image-store.s3.amazonaws.com/0/87987/bb3b9410-3ee9-a5dd-7a44-19d4de7a9f0f.png)
トップ画面(2015/8/11現在)

![monaca_omikuji.png](https://qiita-image-store.s3.amazonaws.com/0/87987/47474f36-67ce-ec9e-4a7f-a901bf104165.png)
テンプレート選択画面(2015/8/11現在)

この中のテンプレートの一つ「Omikuji Fortune Telling App」が今回の題材です。  
プロジェクトを選択した後にMonacaデバッガーを使うか、「プレビュー」を実行し、実際のアプリの動きを確かめてください。

##ディレクトリ構造
![directory.png](https://qiita-image-store.s3.amazonaws.com/0/87987/b52db9f5-5c0b-adec-1811-c7a0a3beb86d.png)
(2015/8/11現在)

componentsにはJS・CSS 関連のコンポーネントと Cordova プラグインが含まれます。

imagesには、本アプリで使用する以下の画像が一括で格納されています。

* 背景画像
* ボタン2種　（「はじめる」、「やり直す」）
* みくじ箋3種（平、中吉、大吉）


index.htmlの中身は次のようになっています。

## index.html

```html:index.html
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    
    <script>
        function omikuji (){
            var dice = Math.floor(Math.random() * 3);
            var image_name;
            if (dice == 0) {
                image_name = "omikuji-daikichi.png";
            } else if  (dice == 1) {
                image_name = "omikuji-chuukichi.png";
            } else {
                image_name = "omikuji-hei.png";
            }
        
            document.getElementById("saisyo").style["display"] = "none";
            document.getElementById("kekka").src = "images/" + image_name;
            document.getElementById("kekka").style["display"] = "inline";
            document.getElementById("button").src = "images/omikuji-btn-yarinaosu.png";
        }
    </script>
    <style>
        body {
            background-image: url("images/omikuji-bg.png");
            background-size: cover;
            background-repeat: no-repeat;
            margin: 0;
            padding: 0;
            text-align: center;
        }
        #hako {
            margin-top: 15%;
            margin-left : 0;
            margin-right : 0;
        }
        
        img {
           width: 70%; 
        }

        #bottombar {
            position: absolute;
            bottom: 30px;
            width: 100%;
        }
    </style>
</head>
<body>
    <div id="hako">
        <img id="saisyo" src="images/omikuji-box.png" />
        <img id="kekka" style="display : none;"/>
    </div>
    <div id="bottombar">
        <img id="button" src="images/omikuji-btn-hajimeru.png" onclick="omikuji()">
    </div>
</body>
</html>
```

ご覧の通り、スクリプトとスタイルをhtmlの中に直接埋め込む形となっています。
おみくじのロジックは、コードの下部

```html:
    <div id="bottombar">
        <img id="button" src="images/omikuji-btn-hajimeru.png" onclick="omikuji()">
    </div>
```
で omikuji() を呼び出し実行しています。

```js:
   function omikuji (){
            var dice = Math.floor(Math.random() * 3);
            var image_name;
            if (dice == 0) {
                image_name = "omikuji-daikichi.png";
            } else if  (dice == 1) {
                image_name = "omikuji-chuukichi.png";
            } else {
                image_name = "omikuji-hei.png";
            }

            document.getElementById("saisyo").style["display"] = "none";
            document.getElementById("kekka").src = "images/" + image_name;
            document.getElementById("kekka").style["display"] = "inline";
            document.getElementById("button").src = "images/omikuji-btn-yarinaosu.png";
        }
```

乱数を取得し、その数値に応じて表示させる運勢を場合わけするという流れになっています。

しかしこのサンプルは、マジックナンバーを含み、可読性が低いものとなっています。また、新たな運勢（たとえば凶）を追加したい場合、修正箇所が多いという欠点があります。

NCMBをつかってこの問題を解決するとともに、Monacaと連携する方法を示します。

他記事を参照の上、NCMBをあらかじめ登録してください。
（とっても簡単に出来きます）

本記事では、NCMBが提供している機能

* 会員管理
* データストア
* ファイルストア
* プッシュ通知

のうち、データストア機能を使い、運勢をこのデータベースに格納します。
そしてMonacaからNCMBにアクセスしデータを引き出して利用することにより
拡張性・保守性を向上させます。

では、具体的な作業にうつっていきましょう。

以下の順番は必ずしも保つ必要はありません。
必要に応じて、やりやすい順番でおこなってください。

# Step1:アプリを作成する(NCMB)
NCMBにログインしたら、画面右上にある「+新しいアプリ」をクリックしてください。

![ncmb1.png](https://qiita-image-store.s3.amazonaws.com/0/87987/625f95cb-5814-5930-07fd-82356b96070e.png)

アプリ名を入れて、新規作成を押してください。
本例では「omikuji」としました。
すると、アプリが作成され、以下の画面が表示されます。

![ncmb2.png](https://qiita-image-store.s3.amazonaws.com/0/87987/cb1160ae-4389-7256-64fd-6c5bab4bf9a8.png)

このアプリケーションキー、クライアントキーは後ほど使います。



# Step2:SDKのインストール(NCMB→Monaca)
下記のリンクから、NCMBのSDKをダウンロードしてください。

[SDKのダウンロード](http://mb.cloud.nifty.com/assets/sdk/javascript/ncmb-latest.min.js)

（ブラウザでソースコードが表示されてしまう場合は、右クリック「名前をつけてリンク先を保存」を押下してお好きな場所に保存してください）

次に、Monacaに移動し、左ペインWWWディレクトリ配下に先ほどダウンロードしたSDKを入れてください（ドラッグ&ドロップで出来ます）

![installsdk.png](https://qiita-image-store.s3.amazonaws.com/0/87987/acb49994-0e15-7915-f34e-291f31e01d88.png)


これでSDKのインストールは完了です。



# Step3:ファイルの移動(Monaca→NCMB)
Monacaにある画像を、NCMBのファイルストアに保存します。
また、運勢のデータをデータストアに入れます。

## ファイルのエクスポート(Monaca)
Monacaで、上部メニューの中から、　ファイル > エクスポート　と選択してください。　さらに中央ペイン右下「エクスポートを実行する」を押下してください。

お好きな場所にproject.zipを保存してください。
このzipファイルを展開し、www > images の中にある運勢画像
（「大吉」「中吉」「平」）を、NCMBのデータストアに入れます。

## ファイルのインポート(NCMB)
NCMBに移動し左メニューからファイルストアを押下してください。
次に、「アップロード」ボタンを押下してください。
下図のようにファイルを移します。

![move.png](https://qiita-image-store.s3.amazonaws.com/0/87987/9a77c7c9-24ff-092d-767e-01c0cf2d2c18.png)


これで、ファイルの移動は完了です。
Monacaの中にある運勢画像3種は削除してかまいません。
## 公開ファイルに設定(NCMB)
NCMBにインポートしたファイルを外部から参照するため、公開ファイルに設定します。
下図のように、左メニューの　アプリ設定> データファイルストア から設定してください。

![public.png](https://qiita-image-store.s3.amazonaws.com/0/87987/7f9344c5-d221-1bdf-fe93-4d350b4f111b.png)


# Step4:運勢データベースの作成(NCMB)
NCMBで、左メニューからデータストアを押下します。
「+作成」ボタン、「新規作成」と押下していきます。

任意のクラス名を記入してください（例では「Omikuji」としました）
※ここでいう「クラス」はリレーショナルデータベースにおける「テーブル」
に相当する概念です。

「+新しいフィールド」をクリックしてください。
今回のデータベースの属性として
運勢と、それについての画像が必要だと考え

* fortune
* image

を追加します。

次に、レコードを登録していきます。
「+新しいレコード」をクリックして、
fortune、imageにそれぞれの運勢、対応する画像のファイル名を記入してください
確定する際はエンターキーを押下してください。

次々と運勢を追加してください。下図のようになればOKです。
![ncmb_datastore.png](https://qiita-image-store.s3.amazonaws.com/0/87987/ed86b01e-cc4a-97cd-6975-9741247adfd9.png)

これで、データベースの登録が完了しました。

# Step5:SDKの利用(Monaca)
Monacaでの作業となります。
index.htmlを開き、headタグ内に以下の行を追加します。

```js 
 <script type="text/javascript" src="./ncmb-latest.min.js" charset="utf-8"></script>
```
さらに、omikuji()の実装部分があるscriptタグ内を次のように書き換えます

```js
<script>
        // information of this app
        var appkey = "YOUR_APPLICATIONKEY";
        var clientkey = "YOUR_CLIENTKEY";
        var appID = "YOUR_APPLICATIONID";
        var commonURL = "https://mb.api.cloud.nifty.com/2013-09-01/applications/"+ appID +"/publicFiles/";
        
        function omikuji (){
            // Initialize and set the app to use NCMB in Monaca
            NCMB.initialize(appkey, clientkey);
            var Omikuji = NCMB.Object.extend("Omikuji");
            var query = new NCMB.Query(Omikuji);
         
            query.find({
              success: function(results) {
                  // Get a random image name of the picture from the class "randomFortune" in NCMB  
                  var image_name = results[Math.floor(Math.random()*results.length)].get("image");
                  
                  // Change the css styles and srcs according to the omiukji states  
                  document.getElementById("saisyo").style["display"] = "none";
                  document.getElementById("kekka").src = commonURL +image_name;
                  document.getElementById("kekka").style["display"] = "inline";
                  document.getElementById("button").src = "./images/omikuji-btn-yari naosu.png";
              },
              error: function(error) {
                  alert(error.toString() + "error occured")
              }
            });
        
</script>
```

YOUR_APPLICATIONKEY, YOUR_CLIENTKEYをNCMBアプリ作成時に発行したアプリケーションキー、クライアントキーに置き換えてください。これらの情報はNCMBの左メニュー内「アプリ設定」からも確認できます。

また、YOUR_APPLICATIONIDは、NCMBのURI（ダッシュボードを開いたときのURI）

https://console.mb.cloud.nifty.com/#/applications/YOUR_APPLICATIONID

のapplications/以下の文字列です。

# omikuji()の解説
NCMBのオブジェクトを扱うには、クエリを使う必要があります。


```js
NCMB.initialize(appkey, clientkey); //SDKの初期化
var Omikuji = NCMB.Object.extend("Omikuji"); //Omikujiクラスのインスタンスを生成
var query = new NCMB.Query(Omikuji); //クエリの生成
```

queryオブジェクトのfind()メソッドで、条件にマッチしたレコードを取得します。
今回は、条件メソッドを実行していないので、全検索となります。

ここでは、JavaScriptで非同期処理を実装する典型的なPromiseパターンをつかっています。

フェッチが成功（success）した場合、全検索した結果はresultsオブジェクト配列に入っています。

次は、おみくじロジックの核となる部分です。

```js
var image_name = results[Math.floor(Math.random()*results.length)].get("image");
document.getElementById("saisyo").style["display"] = "none";
document.getElementById("kekka").src = commonURL +image_name;
document.getElementById("kekka").style["display"] = "inline";
document.getElementById("button").src = "./images/omikuji-btn-yari naosu.png";
```
              
Math.random()メソッドで0から1の浮動小数を取得しています。さらにresults.lengthでレコード数Nを取得しています。これらを掛けることにより0からNまでの浮動小数点を表すことが出来ます。
これを、0からNまでの整数に置き換えるためにMath.floor()メソッドを使っています。
こうすることにより、データストアに格納されているランダムなオブジェクトを取得することが
出来ます。さらにget("image")メソッドにより、取得したオブジェクトのimage属性における値を
得ることが出来ます（これは画像の名前（文字列）となります）

以降は典型的なDOM操作となっています。詳しくは他の記事や書籍等で参照してください。

以上で、すべて完了しました。実行してみてください。

本プロジェクト（ソースコード）を下記にアップロードしましたのでよろしければご参照ください。
[ソースコードはこちら](https://github.com/SatoshiRoppongi/omikuji_NCMB)

#まとめ
本記事ではMonaca上の諸ファイルをNCMBへ移行させる手続きと、その連携法を示しました。
新たな運勢（たとえば凶）を追加する場合は、NCMB上へファイルストアとデータストアを更新する
だけでOKです。以前より拡張性・保守性が向上しました。
しかし、欠点もあります。インターネットを介してデータのやり取りがあるため、ターンアラウンドタイムが低下します。

どのくらいの速度低下があるのか検証し、またどのような解決策があるか模索することが今後の課題となっています。