LoginSignup
33
36

More than 5 years have passed since last update.

オフラインデータをオンラインに同期できる「PouchDB」でEvernoteの卵的なものを作ってみた。

Posted at

pouchdb.png

1. PouchDBの概要

「PouchDB」は、ドキュメント指向データベース「Apache CouchDB」に触発されて開発されたオープンソースのデータベース。PouchDBを利用すると、オフライン時はローカルにデータを保存し、オンラインに戻ったタイミングでクライアント間でデータを同期するため、アプリケーションのユーザーは利用環境を気にすることなく最新のデータにアクセス可能となる。CouchDBと互換性のあるデータベースに対応している。
offline_replication.gif

2. remoteサーバーにCouchDBをインストールする

brew install couchdb
npm install -g pouchdb-server

3. remoteサーバーを立ち上げる

pouchdb-server --port 5984

ブラウザで「http://localhost:5984」にアクセスして
{"express-pouchdb":"Welcome!","version":"0.10.0"}
が表示されてたら無事サーバーは立ち上がっている。

4. CouchDBに直接replicateできるようにするためにcorsをインストール

npm install -g add-cors-to-couchdb
add-cors-to-couchdb
#もしlocalhostじゃないサーバーをしている場合
#add-cors-to-couchdb #{your-serevr-root-url} -u myusername -p mypassword

5. 実際に利用してみる

1. pouchdbのjsをダウンロード
pouchdbのダウンロードはこちらから

2. indexedDBとremoteServerでレプリケーションしてみる

htmlファイルにこう書いて〜、

index.html
<script src="pouchdb-3.2.0.min.js"></script>
<script src="app.js"></script>
<h1>Home#index</h1>                                                                                        
<p>Find me in app/views/home/index.html.erb</p>
<div id="display_stored_data"></div>
<div id="display_localdb"></div>
<%= link_to "get local memo", "javascript:void(0);", class: "getLocalData" %>
<div id="display_remotedb"></div>
<%= link_to "get remote memo", "javascript:void(0);", class: "getRemoteData" %><br>
<%= link_to "show all local memo", "javascript:void(0);", class: "showAllLocalData" %><br>
<ul id="show_all_local_memo"></ul>
<%= link_to "show all remote memo", "javascript:void(0);", class: "showAllRemoteData" %>
<ul id="show_all_remote_memo"></ul>
<%= link_to "sync to remote", "javascript:void(0);", class: "syncDataToRemote" %><br>
<%= link_to "delete local memo", "javascript:void(0);", class: "deleteAllLocalData" %><br>
<%= link_to "delete remote memo", "javascript:void(0);", class: "deleteAllRemoteData" %>

jsファイルにこう書いて〜、

app.js
$(function(){
  var user_id = 1;                                                                                         
  var db_name = "documents";
  var remote_db_name = "http://127.0.0.1:5984/documents";
  //PouchDB.debug.enable('*');
  var ts = new Date().getTime().toString();
  var doc = {
    "_id": ts,
    "user_id": user_id,
    "title": "test document title" + new Date().getTime(),
    "body": "test document body" + new Date().getTime()
  };

  PouchDB.destroy(db_name).then(function () {
    return new PouchDB(db_name);
  }).then(function (db) {
    //
    // IMPORTANT CODE STARTS HERE
    //
    db.put(doc).then(function () {
      return db.get(ts);
    }).then(function (doc) {
      document.getElementById('display_stored_data').innerHTML = 'We stored a memo: ' + JSON.stringify(doc);
    });
    var remote_db = new PouchDB(remote_db_name);
    //db.replicate.to(remote_db);
    //db.replicate.from(remote_db);
  });
  //remoteサーバーからデータを取得する
  $(document).on("click",".getRemoteData",function(){
    var remote_db = new PouchDB(remote_db_name);
    remote_db.get(ts,[],function(err, data){
      document.getElementById('display_remotedb').innerHTML = 'We get a remote memo: ' + JSON.stringify(data);
    });
  });

  //indexedDBからデータを取得する
  $(document).on("click",".getLocalData",function(){
    var local_db = new PouchDB(db_name);
    local_db.get(ts,[],function(err, data){
      document.getElementById('display_localdb').innerHTML = 'We get a local memo: ' + JSON.stringify(data);
    });
  });

  //remoteサーバーからデータを全データを取得する
  $(document).on("click",".showAllRemoteData",function(){
    var target = document.getElementById('show_all_remote_memo');
    target.innerHTML = "";
    var remote_db = new PouchDB(remote_db_name);
    remote_db.allDocs({include_docs: true}, function(err, doc) {
      doc.rows.forEach(function(row){
        var content = document.createElement("li");
        content.innerHTML =("<p>user:"+row.doc.user_id+" > "+row.doc.title+"</p><span>"+row.doc.body+"</span>");
        target.appendChild(content);
      });
    });
  });

  //indexedDBからデータを全データを取得する
  $(document).on("click",".showAllLocalData",function(){
    var target = document.getElementById('show_all_local_memo');
    target.innerHTML = "";
    var db = new PouchDB(db_name);
    db.allDocs({include_docs: true}, function(err, doc) {
      doc.rows.forEach(function(row){
        var content = document.createElement("li");
        content.innerHTML =("<p>user:"+row.doc.user_id+" > "+row.doc.title+"</p><span>"+row.doc.body+"</span>");
        target.appendChild(content);
      });
    });
  });

  $(document).on("click",".deleteAllLocalData",function(){
    var db = new PouchDB(db_name);
    db.destroy();
  });

  $(document).on("click",".deleteAllRemoteData",function(){
    var remote_db = new PouchDB(remote_db_name);
    remote_db.destroy();
  });

  $(document).on("click",".syncDataToRemote",function(){
    var local_db = new PouchDB(db_name);
    var remote_db = new PouchDB(remote_db_name);
    local_db.replicate.to(remote_db);
  });
});

3. 実践!

  1. pageを読み込むと、

Screen Shot 2014-12-24 at 6.41.03 PM.png

  1. 「show all local memo」をクリックするとローカルDBのデータが取得できる

Screen Shot 2014-12-24 at 6.43.01 PM.png

  1. 「show all remote memo」をクリックするとremoteサーバーのデータが取得できる

ただ、まだlocalのデータをremoteにsyncしてないので、表示されない。
Screen Shot 2014-12-24 at 6.43.01 PM.png

  1. 「sync to remote」をクリックしてから「show all remote memo」をクリック

Screen Shot 2014-12-24 at 6.53.16 PM.png

きたきた。

  1. pageをreloadして、localとremoteの両方のデータを見てみる

Screen Shot 2014-12-24 at 6.54.26 PM.png

  1. 再度「sync to remote」をクリックしてから「show all remote memo」をクリックすると、

Screen Shot 2014-12-24 at 6.55.52 PM.png

remoteには2つ目のレコードもsyncされましたね。

6. まとめ

今回はpageのロードでデータをlocalにテストデータを保存して、クリックでsyncしましたが、todoやnote系のアプリだったら、ちゃんとフォームを作って保存ボタンでlocalに保存して、ネットに繋がっていたらサーバーに同期して、いなかったらlocalに保存したままにしておくとかすれば、簡単なevernote的なアプリを作れますね。

33
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
36