Dropbox Datastore APIの使い方とか色々

![snapshot](http://gyazo.com/9330dbcfd9f8f18928cfe64e82aa1236.png)

## 枕詞
Vim Advent Calendar 2012 373日目……じゃなくて、 JavaScript - Client Side - Advent Calendar 2013の8日目担当の[Arc Cosine](https://twitter.com/ArcCosine)です。
まだVim初心者なので、Vim Advent Calendarに参加出来ませんが、いつか参加できるようになりたいです。
さて、今回のJavascript Client Sideは、最近、（俺の中で）大人気のDropbox Datastoreについてです。

##時間がない人用アジェンダ
このエントリに書いてあること

1. [Dropbox Datastore API](https://www.dropbox.com/developers/datastore)を使えるようになるまでのチュートリアル
2. Dropbox Datastore APIのJavaScriptコードサンプル
3. リアルタイム同期をお手軽に見れるという事
4. リリースにDropboxを使うと楽だという事
5. 独自ドメインで運用する場合は[Gehirn](http://www.gehirn.jp/rs2.html) オススメ（魔法石85個以下)
6. 実際に動くアプリは[こちら](https://dl.dropboxusercontent.com/u/335896/clonequill/index.html)
7. ソースコードは[こちら](https://github.com/ArcCosine/clonequill)

## Dropbox Datastore APIとは
言うまでも無いことではありますが、デキる社会人や学生はDropboxを活用しています（Arc Cosine調べ）。
しかしながら、Dropbox Datastore APIはと言うと、なかなか使われていないイメージです。

今年の７月にリリースされたAPIなので仕方がないかもしれません。
参考:[オフラインWebアプリを実現するDropboxの新API「Datastore API」。Dropboxは実質的にBaaS市場へ参入した](http://www.publickey1.jp/blog/13/webdropboxapidatastore_apidropboxbaas.html)

ものすごく簡単に説明すると、key-valueのデータ保存がAPI経由で出来るようになりました。
これまで、データ保存と言えば、ファイルへの保存(テキストファイルやXMLファイル等）やデータベースへの保存(MySQLやPostgress等)、そしてドキュメント形式(MongoDB等)での保存といった形式がありましたが、Dropbox Datastoreは、それらの概念の延長線上にあるものです。
key-valueと言えば、JavaScriptでお馴染みの連想配列です。それと同じ感覚でデータを保存できるというのは、Javascripterとしては非常に扱いやすい方式であると言えます。
JSON.parseやevalなどを使わなずに、データ保存出来るのがとても嬉しいです。

対応ブラウザは下記の通り
IE10、Safari 6、Firefox、Google Chrome.

Operaが記載されていませんが、Operaでも使えます。
Operaが記載されていませんが、Operaでも使えます（大事なことなので二度書きました）。

仕様はこんな感じです。

|項目|サイズ|
|:----------------------------------:|:-----:|
|最大レコードサイズ                  |100KiB |
|最大レコード数                      |100,000|
|最大データサイズ                    |10MiB  |
|Maximum size of a single sync() call|2MiB   |

KiB(kibibyte),MiB(mebibyte)という珍しい単位を使っているのが印象的ですね。
最後の行は英語力()な人なので翻訳できませんでしたが、同期関数の呼び出しサイズだと思います、多分。
参考:[Datastore API documentation - Dropbox](https://www.dropbox.com/developers/datastore/docs/js)

## 実際に、Dropbox Datastore APIへの登録を行なう。
まずは、開発者用のページへアクセスしましょう。
[Developers - Dropbox](https://www.dropbox.com/developers)

![screenshot](http://gyazo.com/57cffa8b554384bcec9c07dff922ca12.png)

**App Console** を選択します。

![screenshot](http://gyazo.com/8d00f4bea3805f69f7e1bbe3019c07cc.png)

右上の **Create app** をクリックします。

![screenshot](http://gyazo.com/ef789453dd2ed4ac9bf31f960e81833b.png)

**Dropbox API app** を選択します。

![screenshot](http://gyazo.com/972bff6e6fd04bf7ec5f29f371847413.png)

今回は、Fileも扱いたいので、 **Files and datastores** を選択しましたが、場合によっては **Datastores only** を選択しても良いです。

![screenshot](http://gyazo.com/9e95a477981e0cad8c556252f07ed763.png)

Appフォルダの下のみのアクセス権が必要なので、Yesを選択します。

![screenshot](http://gyazo.com/cff1e2d4a15863caaadf724975ebbde5.png)

アプリの名前を入力し（今回僕はclonequillという名前にしました)、Create appをクリックします。
尚、注意点として、アプリ名に「drop」やDropboxに似た感じの言葉を入れると弾かれるっぽいので気をつけてください。[ガイドライン](https://www.dropbox.com/developers/reference/branding)に書いてありました。

![screenshot](http://gyazo.com/df3417a2a9b490c66c3496cf30c4be5d.png)

これで登録はほぼ終わりです。

自分以外も使用する可能性がある場合は、 **Enable additional users** をクリックすると100人まで使用する事が出来ます。
申請すれば、ちゃんとしたアプリとして扱ってもらえて、人数制限が無くなります。
申請は **Apply for production** をクリックしてページ遷移後、下記のフォームから行います。

![screenshot](http://gyazo.com/eabc35c85829b5f598db18a217a47e57.png)

このアプリがDropboxをどう扱うのか、どうやったらそのアプリを試せるのかを問われていますので、頑張って英語で書きます。
拙い英語でも、なんとかなりましたので、その辺はチャレンジしてみてください。
どうしても英語が書けない場合は、丁寧で簡潔で分かりやすい日本語を書いて、翻訳サイトで変換し、違和感を感じる所を自分のフィーリングで修正すれば大丈夫です。

## 認証ページ指定
認証ページは、App Consoleから指定出来ます。
先ほど作成したアプリのリンクをクリックすると、Settings タブがあり、その中に **OAuth redirect URIs** があります。
ここに、認証ページのURIを入力します。
認証には、httpsが有効になるサーバが必要です。
localhostを指定する場合は、https無効でも大丈夫です。

![screenshot](http://gyazo.com/0032cbb9949e78917933d5cba00d0c42.png)

SSL証明書インストールしたサーバとか用意できねえよ！！！　という貧乏人でも、作成したファイルをDropboxのPublicフォルダに突っ込めば、簡単に動作確認する事が出来ます。

DropboxのPublicフォルダはリリースが超ラクチンなので、オススメします。
なにせ、Dropboxにファイルコピーするだけですからね。

`リリースコマンド例: cp -r ~/TestFolder/ ~/Dropbox/Public/`

その他にも、Google Driveにコピーして公開という方法もありますが、今回は省略します。興味がある方はやり方を探して試してみてください。

## 独自ドメインで運用する場合

![snapshot](http://gyazo.com/dbeb0a1f74ec9df484167fbb769390ee.png)

独自ドメインで運用しようとするとSSL証明書をインストールしたサーバを用意しなければなりませんが、[Gehirnのサーバ](http://www.gehirn.jp/rs2.html)が非常に安価に使うことができるのでそこをオススメします（ステマ）

![snapshot](http://gyazo.com/98e237feaac293318174073f7b2ca582.png)

初期費用(1,050)＋年間使用料(3,780)＝4,830円。初年度の使用料が **魔法石85個以下** と考えたら非常に安いですね！　Gehirnの中の人は、是非このキャッチフレーズ使ってください（使えない）。
月額換算だと400円ちょっとです。初年度は松屋の牛めし野菜セット１食分で運用できます。
２年目以降は月額315円なので、スタバコーヒー１杯分で運用出来ます。
ここまで安いレンタルサーバーはなかなか無いですよね。
学生のお小遣いでもなんとかなりそうな額です。

SSL証明書はStart SSLをチョイスすれば、無料で取得できます。
参考:[無料のSSL証明書StartSSLを活用する](http://qiita.com/k-shogo/items/870b6d3939dd08da2de4)

尚、GehirnへのStart SSL証明書のインストールは、中の人が詳しく書いてくださっていますので、それを参考にしてください
参考:[無料SSL証明書＋Gehirn RS2でセキュアなドメイン環境をキメる！](http://isid.ai/tips/2011/11/01/488)


## Dropbox Datastore APIの使い方
基本的には[チュートリアル](https://www.dropbox.com/developers/datastore/tutorial/js)の通りにコードを書けば誰でも簡単にアクセスする事が出来ます。
とは言え、現代人は忙しいので、一々リンク先を見なくても良いように、ここにサンプルコードを貼り付けますね。
これをそのままコピペしたら使えるかというとそうでもないので、チュートリアルをキチンと見てください(ヲィ

#### HTML

```html:sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
        <meta charset="UTF-8">
        <title>sample</title>
</head>
<body>
<div id="list-datas"></div>
<input type="button" value="login" />
<script src="//www.dropbox.com/static/api/dropbox-datastores-1.0-latest.js" type="text/javascript"></script>
<script src="js/cq_auth.js"></script>
<script src="js/cq_list.js"></script>
<!-- 他にも色々必要なjsをここに -->
</body>
</html>
`````

特になにもひねっていません。場合によっては、dropbox-datasotres-1.0-latest.jsをダウンロードしてローカルに置いても良いでしょう。
呼び出しを//から始める事で、http／httpsを気にせずにコードが書けるって所がちょっとしたテクニックです。


### 認証部分

```javascript:cq_auth.js
//Set auth class.
function CQAuth(){
  this.init();
}

CQAuth.prototype = {
  init: function(){

    var DROPBOX_APP_KEY = "SET_YOUR_APP_KEY";  //Set your app key

    this.client = new Dropbox.Client({key: DROPBOX_APP_KEY});

    // OAuth check
    this.client.authenticate({interactive:false}, function (error) {
      if( error ){
        alert('Authentication error: ' + error);
      }
    });
  },
  login: function(){
    this.client.authenticate();
  },
  logout: function(){
    this.client.signOut({mustInvalidate: false}, function(error){
      if( error ){
        alert('Sign out error: ' + error);
      }
    });
    location.reload();
  },
  isLogin: function(){
    return this.client.isAuthenticated();
  }
}

//Entry Point
//*
var auth = new CQAuth();

if( auth.isLogin() ){
    alert("Login Success");
}
var login=document.getElementById("login");
document.addEventListener(login,"click", function(){
	auth.login();
});
//*/
```

認証関係の処理コードは全部Dropboxに丸投げできます。
チュートリアルのコードにはログアウトのコードが無いのですが、↑のコード通りに書けば、ログアウト出来ます。APIドキュメント見れば誰でも書けますけれどねｗ

### データ取得
データ取得のコードです。

```javascript:cq_list.js
//Set list class.
function CQList(){
  this.init();
}

CQList.prototype = {
  init : function(){
    this.client = null;
    this.table = null;
  },
  load: function(client){
    this.client = client;
  },
  create: function(){
    var _self = this;

    this.client.getDatastoreManager().openDefaultDatastore(function (error, datastore) {
      if (error) {
        alert('Error opening default datastore: ' + error);
      }

      _self.table = datastore.getTable('quill');
      _self.update();

      datastore.recordsChanged.addListener(function(){ _self.update() });
    })
  },
  update: function() {
	// clear lists.
	document.getElementById('list-datas').innerHTML="";
	var records = this.table.query();
	var list = document.createDocumentFragment();

	// Add an item to the list for each task.
	for (var i = 0, iz = records.length; i < iz; i++) {
		var record = records[i];
		var li = list.appendChild(document.createElement("li"));
		li.innerHTML=record.get("title");
    }
	document.getElementById('list-datas').appendChild(list);
  }
}

// Entry Point
/*

var auth = new CQAuth();
var list = new CQList();
if( auth.isLogin() ){
    list.load(auth.client);
    list.create();
    //Do Code.
}

//*/
```

サンプルなので、色々と端折っていますが、基本的には、datastore.getTable()でtableを取得し、tableから、query()でrecordを取得して、recordにget()する事で、データを取り出します。
珍しいコードとして、datastore.recordsChanged.addListenerという部分がありますが、これは **リアルタイム同期** の仕組みです。
具体的には、PCとスマートデバイスで同じDatastoreを見ていた場合、PCで更新した内容がリアルタイムでスマートデバイスに更新されるという動きをします。
もちろん、その逆も然り。後で紹介する、Clone Quillで実際に試すことが出来ます（オープンマーケティング）

### データ保存
データの保存は、tableのinsert()で出来ます。

```javascript:save.js
var auth = new CQAuth();
var list = new CQList();
if( auth.isLogin() ){
	list.load(auth.client);
	list.create();
	var table=list.table;
	var title = "ABC";
	var content = "DEF";
	var share = "private";

	table.insert({
  		title: title,
  		content: content,
  		share: share
	});
}
```
insertの部分を見ると分かる通り、連想配列そのままで保存出来てるってのが最高に<del>『ハイ！』ってやつだアアアアアア！</del>素敵です。


### データ更新
データの更新は、recordのset()で出来ます。

```javascript:update.js

//一括更新の場合
var auth = new CQAuth();
var list = new CQList();
if( auth.isLogin() ){
	list.load(auth.client);
	list.create();
	var table = list.table;
	var records = table.query();

	for( var i=0, iz = records.length; i<iz; i++ ){
  		var record = records[i];

  		record.set('share','public');
	}

	//こんなことも出来る
	var record=records[0];
	var id = record.getId(); 
	save(id);

	function save(rid){
  		var record = table.get(rid);
  		record.set('share','private');
	}

}



```

いずれにせよ、詳しいことは[チュートリアル](https://www.dropbox.com/developers/datastore/tutorial/js)のコードを読むのが一番早いです。

## Dropbox Datastore APIを使って、quill.toクローン作った
先日、Clone QuillというWebアプリケーションを作り公開しました。
これは、知る人ぞ知るquill.toというメモサービスのクローンもどきです。
尚、quill.toは[今年の五月](http://blog.livedoor.jp/quillstaff/archives/1611421.html)にお亡くなりなりました。残念です。

今回作ったClone Quillは、Dropbox Datastore API経由でデータ保存しています。
つまり、データ保存先をDropboxに丸投げしています。
普通はちゃんとしたDBやらなんやらを用意するのですが、それを用意していない＝サーバ側コードゼロ！という点が新しいです（別に新しくない）。
基本的にはメモ内容は非公開設定なのですが、Dropboxを経由して公開設定にする事も出来ます。

[Clone Quill](https://dl.dropboxusercontent.com/u/335896/clonequill/index.html)

![screenshot](http://gyazo.com/52723980bd773cb6f28d86391198088f.png)


オレオレ仕様なので、色々独自仕様です。
今回は、下記のような事にこだわりました。

* モバイルファースト
 * iPhone等のスマートデバイスからの入力を想定
* 申し訳程度のレスポンシブデザイン
 * まあ、モバイルファーストだしやっておけーみたいなっ
* **キーボードファースト**
 * リスト部分の操作はキーボードで操作(J/Kでの上下移動等)出来るようになっている
 * ?キーでショートカット一覧が出る
 * 隠しショートカットもあるらしい
 * 隠しショートカットはWindowsとMacで動きが違っていて、笑える
* 公開／非公開機能
 * 公開リンクは、Dropboxにテキストファイルを吐き出してそのリンクを習得している
 * 尚、生成したテキストファイルは削除されない模様
 * 今後の更新を待つべし
* Twitter Bootstrapライクなボタンデザイン
 * **ぱくった**
* Font Awesomeカスタマイズ
 * 最近は素敵なサービスがいっぱいある
 * 参考:[http://fontello.com](http://fontello.com)
* 敢えてjQuery
 * モバイルファーストなら、jQuery Mobileだろ、JKって感じなのだが、敢えてjQueryを使った。
 * 単にjQuery 2.xを使いたかっただけ。
 * と言っても、jQuery 2.xで搭載した機能は一切使ってないとかなんとか
 * jQueryだと、touchstartがpreventDefault()できない事がある
 		* CSSにcursor:pointerを指定すると解決する。これテストに出るからメモしておくこと
 * $(document).on(eventName,selector,callback)が面白い
    	* node削除しても、ちゃんとイベント復活する
    	* liveからの移行
    	* この機能により、datastore.recordsChanged.addListenerと結びついているレンダリング処理とイベント処理の分離が可能になった


総括としては、試験的な事がたくさん出来て楽しかったです。
やはり、コード書くのは楽しいですね。

## 薀蓄はいいからコード晒せ
[ArcCosine/clonequill - GitHub](https://github.com/ArcCosine/clonequill)
どうぞ、お納めください、ユーザ様。
ライセンスは、Public DomainとNYSLのダブルライセンスです。
お好きな方をお選びください。
ちなみに、このダブルライセンスは高度なジョークなので、分かる人だけ笑ってください（意味なしジョークが一番面白い）。
js/cq_auth.jsのDROPBOX_APP_KEYをご自身のアプリキーに切り替えて、Dropboxの公開フォルダへコピペすればすぐに動かす事が出来ます。
なお、そのままコピーしても、OAuth認証で弾かれるますのでご注意を。
詳しくはREADME.md読んでください。

## 最後に
リアルタイム同期をDropbox Datastore APIでお手軽に作れたり、サーバを用意しなくても色々なサービスを公開できたりと、実に素晴らしい時代になったなと思いました。
少しだけお時間のある方は、Dropboxの利用例として、サーバ側コードを一切書いてないこの[クソゲー](https://dl.dropboxusercontent.com/u/335896/yoke/index.html)で遊んでみてください。６面クリアができたら凄い（笑）。<del>スペースキー押しっぱでクリア出来るクソゲー</del>
長文でしたが、ここまで読んで下さり、ありがとうございました。
以上です。

明日は[yuku_t](http://qiita.com/yuku_t)さんです。