Backbone.sync の応答をexpress server とconsoleで確認する



http://www.2-hats.net/2013/05/backbonejssynccolleciton.html

を参考にさせていただきました。

google chrome上で、amCoffee もしくは coffee consoleを使用して、backbone.jsのsyncメソッドの応答を確かめる。
jquery, underscore, backbone を読み込んでおく。
crudを実現するためにexpress上でapiを作っておいた。apiがリターンするjsonは ROUTING で res.jsonで示す。

以下coffee
例えば200番でJSONを返す場合はこうなる。

~~~
res.json 200, [JSON]
~~~


Model.sync編 
----------

~~~coffee

Model = Backbone.Model.extend
		urlRoot: '/foo'
		defaults:
			hoge: 'hoge'
sample = new Model()

fire = () ->
	d = new $.Deferred()
	d.resolve()
	return d.promise()
fire()
.then(modelFetch)
.then(modelUpdate)
.then(modelRead)
.then(modelDelete)

~~~
シンプルなモデルを用意した。$.Deferredを用いて、順番だけは整える。
以下fireに続く実行処理を順に示します。

### model.post

~~~coffee

# IDを持っていない、save はPOSTメソッドになる。
modelFetch = () ->
	d = new $.Deferred()
	sample.save null,
		success: (model, res, options) ->
			console.log "post success :", model.attributes
			alert()
			d.resolve()
		error: () -> alert "error"
	d.promise()

########################
# SERVER LOG
######################
# ---post---
# query:  {}
# params:  []
# body:  { hoge: 'hoge' }
########################
# ROUTING
########################
# (req, res) -> res.json 201, {id: id? or id = 12314134}
########################
# RETURN
########################
# XHR finished loading: POST "http://localhost:3000/foo".
# post success : Object {id: 12314134}
# ID を所持するようにリターンを返した。
~~~

下のほうはログです。
saveの第１引数は追加するデータ。
idを持っていないので POST を期待します。
SERVER LOG はサーバーで取れるログです。
paramsはクエリーから取れたデータ。
bodyはメソッドに投げられたデータ。
ROUTINGで、返すデータを示しました。
RETURNは、console上のログです。XHR〜はajaxした時の、jqueryのログです。

### model.put

~~~coffee

# IDをもっているので、save はPUTメソッドになる。
modelUpdate = () ->
	d = new $.Deferred()
	sample.save {foo: "foo"}, # 第一引数は任意の追加パラメータ
		success: (model, res, options) ->
			console.log 'put success : ' , model.attributes
			alert()
			d.resolve()
		error: () -> alert "error"
	d.promise()
########################
# SERVER LOG
######################
# ---put---
# query:  {}
# params:  [ id: '12314134' ]
# body:  { hoge: 'hoge', foo: 'foo', id: 12314134 }
########################
# ROUTING
########################
# (req, res) -> res.json 201, {}
########################
# RETURN
########################
# XHR finished loading: PUT "http://localhost:3000/foo/12314134".
# put success :  Object {id: 12314134, foo: "foo"}

~~~

IDを持っているので、PUTを期待しました。

### model.get

~~~coffee
modelRead = () ->
	d = new $.Deferred()
	sample.fetch
		success: (model, res, options) ->
			console.log "get success : ", model.attributes
			alert()
			d.resolve()
		error: () -> alert "error"
	d.promise()
########################
# SERVER LOG
######################
# ---get---
# query:  {}
# params:  [ id: '123124134' ]
# body:  {}
########################
# ROUTING
########################
# (req, res) -> res.json 200, {bar: "bar", id: req.params.id + 0}
########################
# RETURN
########################
# XHR finished loading: GET "http://localhost:3000/foo/12314134".
# get success :  Object {id: "123141340", foo: "foo", bar: "bar"}
~~~

id持ちfetch はgetです。
res.jsonでStringを返すとはまるのでちゃんとキャストしとく。

### model.delete

~~~coffee
# id を所持しているdestroyはdeleteする
modelDelete = () ->
	sample.destroy
		success: (model, res, options) ->
			console.log "delete success : ", model.attributes
			alert()
			alert "completed!"
		error: () -> alert "error"
	d.promise()
########################
# SERVER LOG
######################
# ---delete---
# query:  {}
# params:  [ id: '123141340' ]
# body:  {}
########################
# ROUTING
########################
# (req, res) -> res.json 200, {}
########################
# RETURN
########################
# XHR finished loading: DELETE "http://localhost:3000/foo/123141340".
# delete success :  Object {id: "123141340", foo: "foo", bar: "bar"}
~~~






Collection.sync 編
-------------

~~~coffee
Model = Backbone.Model.extend
    defaults:
        hoge: 'hoge'

Collection = Backbone.Collection.extend
	model: Model
	url: '/foo2'
	parse: (res) ->
		console.log 'receive collection : ', @toJSON()
		console.log 'parse success : ', res
		return res
samples = new Collection()

fire = () ->
	d = new $.Deferred()
	d.resolve()
	return d.promise()

fire()
.then(collectionFetch)
.then(collectionFetchOne)
.then(collectionCreate)
.then(collectionUpdate)
.then(collectionDelete)
.then(collectionReset)
~~~

collection編です。
modelにはurlRootを指定しません。指定するとOneFetchで優先される。
parseは、持ってきたresをそのまま扱います。fetchした時は、ここで配列で返されてはじめて、collectionにマージされていきます。今回はきっちり配列jsonがかえってくるので整形してません。

fire().then はモデルの時と同じです。
以下、実行する処理を順に示します。

### collection.get

~~~coffee
collectionFetch = () ->
	d = new $.Deferred()
	samples.fetch
		success: (collection, res, options) ->
			console.log 'fetch the collection : ', collection.toJSON()
			alert()
			d.resolve()
		error: () -> alert "error"
	d.promise()
##############################
# SERVER LOG
##############################
# ------GET: the collection ------
# query:  {}
# params:  []
# body:  {}
##############################
# ROUTING
##############################
# res.json 200, [{id: 1, data: 'before'},{id: 2, data: 'before'},{id: 3, data: 'before'}]
##############################
# RETURN
##############################
# XHR finished loading: GET "http://localhost:3000/foo2".
# receive collection :  []
# parse success : [Object, Object, Object]
###
0: Object
data: "before"
id: 1
__proto__: Object
1: Object
data: "before"
id: 2
__proto__: Object
2: Object
data: "before"
id: 3
###
# fetch the collection : [Object, Object, Object]
###
0: Object
data: "before"
hoge: "hoge"
id: 1
__proto__: Object
1: Object
data: "before"
hoge: "hoge"
id: 2
__proto__: Object
2: Object
data: "before"
hoge: "hoge"
id: 3
###
~~~

下のほうはログです。
これはfetchでgetしてとってくるコードです。コレクションとはサーバーストレージと同期したいものです。

parseは受けたデータそのものなのでhogeがないのですが、fetchで返ってくるcollectionにはデフォルトのhogeがあるのに注目。

### model.get

~~~coffee
collectionFetchOne = () ->
	d = new $.Deferred()
	samples.at(0).fetch
		success: (model, res, options) ->
			console.log 'one fetch : ', model.attributes
			alert()
			d.resolve()
		error: () -> alert 'error'
	d.promise()
##############################
# SERVER LOG
##############################
# ------GET: a model in the collection ------
# query:  {}
# params:  [ id: '1' ]
# body:  {}
##############################
# ROUTING
##############################
# res.json 200, {data: 'after', data2: 'add'}
##############################
# RETURN
##############################
# XHR finished loading: GET "http://localhost:3000/foo2/1".
# one fetch :  Object {id: 1, data: "after", hoge: "hoge", data2: "add"}
~~~

collection.at(0).fetchなので普通のモデルの場合のget


### collection.post
~~~coffee
collectionCreate = () ->
	d = new $.Deferred()
	samples.create {
		data: 'create' # crud method を指定する
	},{
		success: (model, res, options) ->
			console.log 'create a model in the collection : ', model.attributes
			alert()
			d.resolve()
	}
	d.promise()
##############################
# SERVER LOG
##############################
# ------POST: a model in the collection ------
# query:  {}
# params:  []
# body:  { data: 'create', hoge: 'hoge' }
##############################
# ROUTING
##############################
# res.json 201, {id: 4}
##############################
# RETURN
##############################
# XHR finished loading: POST "http://localhost:3000/foo2".
# create a model in the collection :  Object {data: "create", hoge: "hoge", id: 4}
~~~

モデルを新規作成
createはpostになります。

### collection.put
~~~coffee
collectionUpdate = () ->
	d = new $.Deferred()
	samples.at(3).save {
		data: 'update' # crud method を指定する。
	},{
		success: (model, res, options) ->
			console.log 'update a model in the collection : ', model.attributes
			alert()
			d.resolve()
	}
	d.promise()
##############################
# SERVER LOG
##############################
# ------PUT: a model in the collection ------
# query:  {}
# params:  [ id: '4' ]
# body:  { data: 'update', hoge: 'hoge', id: 4 }
##############################
# ROUTING
##############################
# res.json 200, {}
##############################
# RETURN
##############################
# XHR finished loading: PUT "http://localhost:3000/foo2/4".
# update a model in the collection :  Object {data: "update", hoge: "hoge", id: 4}
~~~

一部上書き
idがあるのでsaveはputになりました。


### collection.delete
~~~coffee
collectionDelete = () ->
	d = new $.Deferred()
	samples.at(0).destroy
		success: (model, res, options) ->
			console.log 'delete a model in the collection : ', model.attributes
			console.log 'after delete : ', samples.toJSON()
			alert()
			d.resolve()
	d.promise()
##############################
# SERVER LOG
##############################
# ------DELETE: collection delete -----
# query:  {}
# params:  [ id: '1' ]
# body:  {}
##############################
# ROUTING
##############################
# res.json 200, {}
##############################
# RETURN
##############################
# XHR finished loading: DELETE "http://localhost:3000/foo2/1".
# delete a model in the collection :  Object {id: 1, data: "after", hoge: "hoge", data2: "add"}
# after delete :  [Object, Object, Object]
~~~

一部削除
下は元に戻すだけ

~~~coffee
collectionReset = () ->
	samples.fetch
		reset: true
		success: (collection , res, options) ->
			console.log 'reset the collection : ', collection.toJSON()
			alert()
			console.log 'Completed!'
##############################
# SERVER LOG
##############################
# ------GET: the collection ------
# query:  {}
# params:  []
# body:  {}
##############################
# ROUTING
##############################
# res.json 200, [{id: 1, data: 'before'},{id: 2, data: 'before'},{id: 3, data: 'before'}]
##############################
# RETURN
##############################
# XHR finished loading: GET "http://localhost:3000/foo2".
# receive collection :  []
# parse success : [Object, Object, Object]
# reset the collection : [Object, Object, Object]
# Completed!
~~~

元に戻しただけ
最初と同じ