タスクの完了をDBに保存する(Electron+Vue.jsで作るTodoアプリ)

Electron

はじめに

本日もディア○スティーニ。
タスクの完了もDBに保存してきましょう。

NeDBの使い方は方々のサイトに出ているのでそれらを見れば良いのですが、自ら手を動かすのが楽しいのです。
いろいろ調べてやってみて、NeDBチョットデキルと言ってみたいではないですか!

どのタスクが完了したかをどうやって特定するか?

さて、完了時の処理を手直しする前に、考えないといけないことがあります。

どのタスクが完了したかをどうやって特定するか?

今は配列とリスト表示の順序が一致しているので、実際に渡されるものはチェックがクリックされたリストの行数にしましょうかね。
ソートや絞り込みなどを行うならば、この方法は利用できません。
別途タスクID等で完了済みにしたいタスクの特定を行う必要があります。

データを永続化する(Electron+Vue.jsで作るTodoアプリ)

配列に入れていたときは、アプリを起動してから終了するまでの間タスクが特定できればOKだったので、リストの行数を使っていました。しかし、DBにタスクを保存するようにしたので、この際リストの行数方式を捨ててみましょう。

では、何を使うかといえば、データを永続化する(Electron+Vue.jsで作るTodoアプリ)の_idフィールドのことを思い出してください。
NeDBはJSONデータを投入すると_idフィールドを作って一意の値を割り当ててくれます。これを使います。

チェックマークをクリックしたときに渡す値を修正する

早速引数を変えていきます。

タスクが完了したときに、リストの左端に用意したチェックマークをクリックします。このチェックをクリックしたときに呼び出される処理がcompleteTaskメソッドです。

これまでチェックマークをクリックしたときは、completeTask(record.$index)として行番号を渡していました。これを_idフィールドの値を渡すように修正します。

<el-table-column label="button" width="50">
    <template slot-scope="record">
        <el-button size="mini" icon="el-icon-check" circle @click="completeTask(record.row._id)">
        </el-button>
    </template>
</el-table-column>

完了の処理をチョット変える

メソッドはなに使うのん?

これまでに作ったcompleteTaskメソッドでは、配列にタスク完了の情報を記録します。ただ、このままではアプリを起動し直したときにタスク完了の情報がなくなってしまいます。

なので、DBへ保存するよう修正します。NeDBの更新はupdateメソッドを使います。

updateメソッドの引数

引数は3つです。

1つ目

引数1つ目は更新対象のデータの抽出条件です。これはfindメソッドのときにも出てきたのと[同じパターン]()で、

{ fruit: 'orange' }

のように指定します。

2つ目

2つ目には更新する内容を指定します。

既存のフィールドの値を更新するには、

$set{ fruit: 'watermelon' }

のように指定します。このようにすると、先ほどの抽出条件と合わせてオレンジ🍊がスイカ🍉になります。

なお、ここで存在しないフィールド名を渡してしまうと、そのフィールドが新しく作られてしまうので注意してください。

更新したはずが値が変わらず、かつ妙なフィールドがJSONに入っていて、「おかしいなぁ」と悩むことになります。

3つ目

3つ目は処理のオプションを指定します。
なんとこのupdateメソッドは抽出条件で取り出したデータセットのうち、1つ(おそらく任意)だけが更新されます。

たくさんのデータの中から特定の1つを変更するだけ、というパターンなら問題ないです。しかし、例えば「年齢が20歳以上」など複数のデータが抽出される可能性がある場合は困ったことになります。

こういうときには、{multi: true}を指定します。

残るは例のコールバックのあれです。errorはいつものエラー情報。numOfDocsは更新した件数が返ってきます。

引数2つ目と3つ目は先ほど示したもの以外にもいろいろあるので調べてみてね。

Todoアプリの修正

さて、Todoアプリに戻って考えます。

引数一つ目の検索条件は、引数で持ってきた_idフィールドの値です。_idフィールドは一意(のハズ)なので、引数3つ目のオプションは不要です。つまり{}
引数2つ目は更新する内容なので、isCompleteフィールドをtrueにしておきましょう。

結果を示します。

completeTask (targetTask) {
    this.$db.update({_id: targetTask}, {$set: {isComplete: true}}, {}, (error, numOfDocs) => {
        if (error !== null) {
        }
        this.fetchTask()
    })
}

ついでと言ってはなんですが、エラーなく更新ができた後にfetchTaskメソッドを実行しています。

保存されているか確かめてみます

タスク完了の情報が保存されているか確認してみましょう。

この画像だけで「完了した事実は保存されてました」と無理やり言い切る

「完了済みチェックをしたことが保存されてます!」と示しにくいですが、アプリを開き直してもタスクに取り消し線が付き完了扱いになっています。

今日はここまで

少し無理がある実行結果でしたが良しとしてください。「うそだぁあ〜」と思われた方は、ぜひご自身でもやってみてください。

削除の処理は落ち着いて次回です。