実践入門 Ember.js

第7回 データの永続化(Ember Data)

この記事を読むのに必要な時間:およそ 11 分

CRUD を扱う

ここまではデータを取得方法を紹介してきましたが,このセクションではデータの作成と削除を紹介します。

まずはアダプタを設定します※7⁠。

※7
ちなみにここで利用しているAPIではデータの登録・削除ができますが,登録した内容は閲覧制限をかけていないので他のユーザからも見えてしまいます。パスワードなどの秘密の情報を公開しないように気をつけください。
App.ApplicationAdapter = DS.RESTAdapter.extend({
  host: 'https://tricknotes-gihyo-ember-07.herokuapp.com',
  namespace: 'v5'
});

JSONの形式はv1と同じものを使っているため,関連の非同期フラグは外します。

App.Post = DS.Model.extend({
  // ...

  comments: DS.hasMany('comment')
});

次は記事詳細画面からコメントの投稿/削除のUIを準備します。

<script type="text/x-handlebars" data-template-name="post">
  <h1>{{model.title}}</h1>

  <pre>
    {{model.body}}
  </pre>

  <ul>
  {{#each comment in model.comments}}
    <li>{{comment.text}} <a href="#" {{action "deleteComment" comment}}>&times;</a></li>
  {{/each}}
  <li>{{input value=text action="createComment" required=true placeholder="どうでしたか?"}}</li>
  </ul>

  {{link-to "戻る" "posts"}}
</script>

記事詳細画面に対応するコントローラを作成して,コメントの投稿/削除に対応します。

App.PostController = Ember.Controller.extend({
  text: null,
  actions: {
    createComment: function() {
      var controller = this;
      var text = this.get('text');

      var comment = this.get('model.comments').createRecord({text: text});

      comment.save().then(function() {
        controller.set('text', null);
      }, function() {
        alert('保存に失敗しました');

        comment.unloadRecord();
      });
    },

    deleteComment: function(comment) {
      comment.destroyRecord();
    }
  }
});

新しく登場した記述を解説します。

createRecord()

モデルのオブジェクトを生成するメソッドです。ここではpostの関連であるcommentsに対してcreateRecord()メソッドを呼び出しているため,記事への関連を保持した状態のコメントを生成します。この状態ではまだサーバに保存はされません。関連を元にせずオブジェクトを生成したい場合はstore.createRecord()を利用します。この場合,第一引数はモデル名,第二引数は初期値を指定します。

save()

モデルをサーバに保存します。クライアントサイドで生成されたモデルであれば新規保存され,サーバから取得してきたモデルであれば更新されます。サーバに送信されるデータはシリアライザによって決定されます。関連するリソースも一緒にサーバに送信したいという場合は前述のDS.EmbeddedRecordsMixinを使います。サーバに送信されるデータをあらかじめ確認したい場合は,モデルのserialize()メソッドを利用してデータを取得します。また,save()メソッドはPromiseを返します。保存に成否を待ってから実行したい処理がある場合,Promiseのコールバックを利用してください。

unloadRecord()

クライアントサイドのモデルを破棄します。クライアントでモデルが不要になった際に呼び出します。

destroyRecord()

モデルをサーバから削除します。似たような機能を持つdeleteRecord()メソッドもあります。前者はすぐにサーバのデータも削除されるのに対し,後者はsave()メソッドを呼ぶまでサーバのデータは削除されないという違いがあります。

これらのメソッドは,HTTPリクエストを発行してサーバのリソースを更新します。意図した通り動作させるためには,対応するAPIをサーバでサポートしている必要があります。

メソッドとAPIの対応は次のとおりです。

メソッド URL リクエストメソッド
comment.save() (新規) /comments/ POST
comment.save() (更新) /comments/1 PUT
comment.destroyRecord() /comments/1 DELETE

動作するサンプルはこちらです。

ここまでは,Ember DataのDS.RESTAdapter/DS.RESTSerializerが期待する形のAPIサーバを前提として解説をしてきました。APIサーバを実装しつつアプリケーションを開発する際にはここまでで紹介した方法で十分でしょう。

著者プロフィール

佐藤竜之介(さとうりゅうのすけ)

株式会社えにしテック所属。JavaScriptとRubyが好きなウェブ系プログラマ。オープンソースソフトウェアに強い関心がありEmber.jsにも数多くのパッチを送っている。

ブログ:http://tricknotes.hateblo.jp/
Twitter:@tricknotes