【vte.cx入門】6.登録したデータの内容を上書き・更新する：jQuery実践編

[データの登録](http://qiita.com/takeyama/private/80669a5ccd65e77761a2)と[データの参照](http://qiita.com/takeyama/private/38035d510ebcea5e124e)ができるようになったら、今度は参照したデータを更新してみましょう。

ここではjQueryを利用したデータの更新方法を記します。

# 1.更新するデータを準備する。
サーバから更新したい[データを取得](http://qiita.com/takeyama/private/38035d510ebcea5e124e)してください。


仮に以下のデータとします。

```
{"feed" : {
    "entry" : [
        {
          "userinfo" : {
              "id" : 1234,
              "email" : "hoge@foo.com"
          },
          "favorite" : {
              "food" : "りんご",
              "music" : "J-POP"
          },
          "author" : [{"uri" : "urn:vte.cx:created:21"}],
          "id" : "/11/0-8-2-9-1-1-1,1",
          "link" : [{"___href" : "/11/0-8-2-9-1-1-1","___rel" : "self"}],
          "published" : "2015-12-01T13:44:46.067+09:00",
          "updated" : "2015-12-01T13:44:46.067+09:00"
        }
    ]
}}
```

更新内容は、favoriteのfood項目を「みかん」に書き換えてみます。

```
feed.entry[0].favorite.food = 'みかん';
```


# 2.ajaxでデータを更新する（PUTリクエスト）
上記データをjQueryのajax通信を使用し、PUTリクエストを実行します。

```lang:javascript
var request = {"feed" : {"entry" : [{"userinfo" : {"id" : 1234,"email" : "hoge@foo.com"},"favorite" : {"food" : "みかん","music" : "J-POP"},"author" : [{"uri" : "urn:vte.cx:created:21"}],"id" : "/11/0-8-2-9-1-1-1,1","link" : [{"___href" : "/11/0-8-2-9-1-1-1","___rel" : "self"}],"published" : "2015-12-01T13:44:46.067+09:00","updated" : "2015-12-01T13:44:46.067+09:00"}]}};

$.ajax({
	url: '/d/',
	method: 'put',
	dataType: 'json',
	data: JSON.stringify(request)
}).done(function(res) {
	alert('更新成功');
}).fail(function( jqXHR, textStatus, errorThrown ) {
	alert('更新失敗');
});
```
## ■リクエスト
| param | 値 | 例 |
|:-----------|:------------|:------------|
|url|/d/||
|method|PUT||
|dataType|json||
|data|更新データ|上記参照|

### 更新先はlinkタグのrel="self"で指定する【ポイント】

ajaxのリクエストURLが「/d/」なのに注目してください。
更新先はajax通信のリクエストURLを見るのではなく、**データのlink項目のrel="self"のhref属性を元に実行します。**

```lang:link項目のrel="self"の例
"link" : [{"___href" : "/11/0-8-2-9-1-1-1","___rel" : "self"}]  ← このhrefが更新先になる
```

更新するデータのlink項目のrel="self"と、更新したいデータのlink項目のrel="self"のhref属性が一致していることを必ず確認してください。


## ■レスポンス
### 成功ステータス

| ステータス | メッセージ | レスポンス |
|:-----------|:------------|:------------|
|200|OK|{"feed" : {"title" : "Updated."}}|

このレスポンスが返って来れば、正しく更新ができたということになります。
サーバからデータを取得して更新内容が正しく反映されているか確認しましょう。

#### データの更新が成功するとリビジョン番号が更新される【ポイント】
vte.cxでは登録データの管理を[リビジョン管理](http://reflexworks.jp/documentation.html#taggingservice.html#R5)で行っており、**リビジョン番号がサーバと同一であれば更新を実行できます。**
リビジョン番号は**id項目の「,（カンマ）」の後ろ**に格納されています。

```lang:リビジョン番号の例
"id" : "/11/0-8-2-9-1-1-1,1"   ←   リビジョン番号は「1」
```
更新が成功すると、リビジョン番号がカウントアップします。

```
"id" : "/11/0-8-2-9-1-1-1,1"   ←   更新前

 ↓   更新成功

"id" : "/11/0-8-2-9-1-1-1,2"   ←   更新後

 ↓   さらに更新

"id" : "/11/0-8-2-9-1-1-1,3"   ←   このようにカウントアップされる
```
こうしたリビジョン管理を行うことで、最新のデータを正しく管理しています。

##### リビジョン番号のカウントアップはサーバが自動で行います。
ユーザはサーバのリビジョン番号が更新データのリビジョン番号と一致しているかどうかだけを確認していただければ大丈夫です。

### 失敗ステータス

以下の仕様書の下部に細かく記載されています。ステータスコードに沿って正しいデータを登録してみてください。
[HTTPステータス一覧](http://reflexworks.jp/documentation.html#taggingservice.html#H)

#### ステータス：409になった場合【ポイント】

このエラーは楽観的排他チェックが行われた結果起こることがあります。
つまり、**データの競合が発生したケース**になります。

##### データの競合とは
同じデータを同時に更新しようとして起こるエラーです。
自分が保持していたデータが古くなってしまい、リビジョン番号がサーバと一致せずに更新の実行できなくなってしまう状態です。

##### データの競合が起きてしまった場合の回避策
###### 【方法1】最新のデータを取得し直す
データの競合が起きてしまった場合は、**もう一度サーバから最新のデータを取得**し、そのデータに沿って更新を行ってください。
###### 【方法2】リビジョン番号のみをサーバのデータと一致させる
もう一つは、サーバのデータのリビジョン番号と更新データのリビジョン番号のみを一致させる方法です。
**リビジョン番号がサーバと一致さえすれば更新は実行できる**ので、状況によっては必ずしもすべてのデータを最新の内容にする必要はありません。

```
"id" : "/11/0-8-2-9-1-1-1,23"   ←   サーバのリビジョン番号
"id" : "/11/0-8-2-9-1-1-1,20"   ←   更新しようと思ったデータのリビジョン番号

 ↓   リビジョン番号を一致させる

"id" : "/11/0-8-2-9-1-1-1,23"   ←   更新するデータのリビジョン番号
```

# 楽観的排他処理を行わずに強制的に上書きする
PUT更新では強制的に上書きする方法があります。
以下のようにid項目を省略して更新することができます。

```lang:id項目を省略した更新データの例
{"feed" : {
    "entry" : [
        {
          "userinfo" : {
              "id" : 1234,
              "email" : "hoge@foo.com"
          },
          "favorite" : {
              "food" : "りんご",
              "music" : "J-POP"
          },
          "author" : [{"uri" : "urn:vte.cx:created:21"}],
          "link" : [{"___href" : "/11/0-8-2-9-1-1-1","___rel" : "self"}],
          "published" : "2015-12-01T13:44:46.067+09:00",
          "updated" : "2015-12-01T13:44:46.067+09:00"
        }
    ]
}}

```
この場合、楽観的排他チェックは行われず、常に上書き更新になります。
強制的に上書きされることでデータが失われることもありますのでidを省略するのはなるべく避けた方がいいでしょう。

# 終わりに
データの更新時は、必ずそのデータが最新かどうかを必ずチェックし、競合が起こらないようにコントロールしていく必要があります。
リビジョン番号をどのようにサーバと同期させるのかは、作成するアプリによって方法は変わると思うので、その都度方法を検討してみてください。

以上で、更新の方法についての説明を終わりたいと思います。

更新についてより詳しく知りたい方は[仕様書](http://reflexworks.jp/documentation.html#taggingservice.html#U)をご参照ください。

次回はサーバのデータ削除の方法です。