ニフクラ mobile backend(mBaaS)お役立ちブログ

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

既存のカンバンシステムをmBaaSに置き換えてみよう(タスクの保存)

f:id:mbaasdevrel:20180119145425p:plain

既存のWebアプリケーションのバックエンドをmBaaSに置き換えてみる連載になります。一つずつ順番に紹介していきますので、同じようなシステムのリプレイスで参考にしてもらえるはずです。

前回はワークスペースのCRUD操作をmBaaSに対応させましたので、今回はタスクについて処理をしていきたいと思います。

タスクの読み込み

タスクを読み込む処理はワークスペースが選択された後で行われます。行っているのは restoreTasks というメソッドになります。

function restoreTasks(){
  tasks = JSON.parse(window.localStorage.getItem(getWorkspaceName(currentWorkspace)));
  if(tasks == null || tasks === "undefined"){
    tasks = {};
  }
}

mBaaSに対応させると次のようになります。ここでの注意点としては、ワークスペースにリレーションで紐付いたタスクの取得方法です。検索対象になるのはTaskクラスになります。そして、relatedToを使って現在選択されているワークスペース(currentWorkspace)を指定し、そのワークスペース側でリレーションが貼られているタスク(tasks)を指定します。

function restoreTasks(){
  return new Promise((res, rej) => {
    Task
      .relatedTo(currentWorkspace, 'tasks')
      .fetchAll()
      .then((results) => {
        tasks = {};
        for (var i = 0; i < results.length; i += 1) {
          var task = results[i];
          tasks[task.objectId] = task;
        }
        res();
      })
  });
}

タスクの移動

カンバンシステムの目玉とも言えるのがタスクの移動ではないでしょうか。マウスでドラッグして別なカラムに移動した時の処理は onDropTask になります。

function onDropTask(event, ui) {
  draggedTo = $(this).attr("kanban-column-id");  
  if(draggedFrom != draggedTo){
    var id = $(ui.draggable).attr("id");
    tasks[id].state = draggedTo;
    if(!tasks[id].history){
      tasks[id].history = [];
    };
    tasks[id].history.push({"date": new Date(), "state":draggedTo})
    drawTask(id);
    saveTasks();
    ui.draggable.remove();
  }
}

書き換えた処理は次のようになります。殆ど変わっていませんが、大きな違いはデータの更新方法です。元々はプロパティにそのまま値を適用していましたが、mBaaSの場合はsetメソッドを使わなければなりません。

function onDropTask(event, ui) {
  draggedTo = $(this).attr("kanban-column-id");  
  if(draggedFrom != draggedTo){
    var id = $(ui.draggable).attr("id");
    tasks[id].set('state', draggedTo);
    if(!tasks[id].history){
      tasks[id].set('history', []);
    };
    tasks[id].history.push({"date": new Date(), "state":draggedTo})
    drawTask(id);
    saveTasks();
    ui.draggable.remove();
  }
}

タスクの保存

タスクの保存は saveTasks で行います。ネットワークを使っていますので非同期処理ですが、特にその後の処理に引き継ぐものはないので thenを使っていません。元々の処理は次のようになります。

function saveTasks(){
  window.localStorage.setItem(getWorkspaceName(currentWorkspace), JSON.stringify(tasks));
}

それに対して mBaaS で置き換えると次のようになります。リレーションを使って処理を行うため、処理全体が長くなってしまっています。前半の処理でTaskクラスに新規作成または更新を行っています。後半では保存したデータをリレーションにつないでいます。リレーションは現在のワークスペース(currentWorkspace)に保存します。

function saveTasks(){
  var promises = [];
  for (var i in tasks) {
    var task = tasks[i];
    if (task.objectId) {
      promises.push(task.update());
    } else {
      var t = new Task;
      for (var k in task) {
        t.set(k, task[k]);
      }
      promises.push(t.save());
    }
  }
  Promise
    .all(promises)
    .then((results) => {
      var relation = new ncmb.Relation();
      tasks = {};
      for (var i = 0; i < results.length; i += 1) {
        var task = results[i];
        relation.add(task);
        tasks[task.objectId] = task;
      }
      redrawKanban();
      return currentWorkspace
        .set('tasks', relation)
        .update();
    })
    .then((workspace) => {
      console.log('Save tasks');
    })
}

分解して書くと次のようになります。

function saveTasks(){
  saveAllTasks()
    .then(results => saveRelation(results))
    .then(() => redrawKanban())
}

function saveAllTasks() {
  var promises = [];
  for (var i in tasks) {
    var task = tasks[i];
    if (task.objectId) {
      promises.push(task.update());
    } else {
      var t = new Task;
      for (var k in task) {
        t.set(k, task[k]);
      }
      promises.push(t.save());
    }
  }
  return Promise.all(promises)
}

function saveRelation(results) {
  var relation = new ncmb.Relation();
  tasks = {};
  for (var i = 0; i < results.length; i += 1) {
    var task = results[i];
    relation.add(task);
    tasks[task.objectId] = task;
  }
  return currentWorkspace
    .set('tasks', relation)
    .update();
}

タスクの削除

タスクを削除する場合は、mBaaS上からタスクデータを削除後、タスクの集合体である tasks から該当データを消して表示を更新します。元々の処理は次のようになります。

function onClickRemoveTask(e){ 
  id = e.target.parentElement.id;
  if(confirm(message("confirm_remove_task",tasks[id].title))){      
    delete tasks[id];
    saveTasks();
    $("#"+id).remove();
  }
}

元々の処理が変数から削除するだけだったのに対して、mBaaSからデータを削除する処理が追加されています。

function onClickRemoveTask(e){ 
  id = e.target.parentElement.id;
  if(confirm(message("confirm_remove_task",tasks[id].title))){      
    tasks[id]
      .delete()
      .then(() => {
        delete tasks[id];
        saveTasks();
        $("#"+id).remove();
      })
  }
}

ここまでの処理でタスクの表示、追加、更新、削除について行えるようになりました。localStorageが同期なのに対してmBaaSは非同期になるので処理が若干変わりますが、それほど大きな修正をせずにデータストレージの変更が実現できます。

次回はデータのインポート、エクスポートについて解説します。

中津川 篤司

中津川 篤司

NCMBエヴァンジェリスト。プログラマ、エンジニアとしていくつかの企業で働き、28歳のときに独立。 2004年、まだ情報が少なかったオープンソースソフトの技術ブログ「MOONGIFT」を開設し、毎日情報を発信している。2013年に法人化、ビジネスとエンジニアを結ぶDXエージェンシー「DevRel」活動をスタート。