Emberjs-data Trying

In my old emberjs project(money,food-ntpc) i didn’t use ember-data to handle data processing with backend server. The ember-data is closed to 1.0.0(now is 1.0.0.beta4) so i give it a try. The official document is quite less and some posts in StackOverflow are out of date. Checkout their source code is the quickest way to understand how they work and do customized. I write down tips here for my reference in the future.

Define your store to use ember-data

1
2
3
4
5
MyAdapter = DS.RESTAdapter.extend

MyApp.Store = DS.Store.extend
  revision: 11
  adapter: MyAdapter

Assume your have a record object and json format is

1
2
3
4
5
6
7
8
{
  "record": {
    "id":"1",
    "amount":150,
    "category_id":1,
    "description":"dinner"
  }
}

Define your model object.

1
2
3
4
MyApp.Record = DS.Model.extend
  category_id: DS.attr 'number'
  amount: DS.attr 'number'
  description: DS.attr 'string'

Get all MyApp.Record from backend server.

1
2
3
4
MyApp.ApplicationRoute = Ember.Route.extend
  model: (params)->
    model = @store.find 'record'
    return model

If you want to use store without in route,controller

1
MyApp.__container__.lookup('store:main').find 'record'

The backend should provide the REST api path http://127.0.0.1/records.
Server response json should be like

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "records": [{
    "id":"1",
    "amount":150,
    "category_id":1,
    "description":"dinner"
  },
  {
    "id":"2",
    "amount":250,
    "category_id":1,
    "description":"lunch"
  }]
}

The default root of json become records not record and content should be a Array.
In case you want to pass parameter into URL like http://127.0.0.1/records?year=2014.

1
2
3
4
MyApp.ApplicationRoute = Ember.Route.extend
  model: (params)->
    model = @store.find 'record', { year: 2014 }
    return model

Get single record.

1
2
3
4
5
MyApp.RecordRoute = Ember.Route.extend
  model: (params)->
    # assume params.id is 1
    model = @store.find 'record', params.id
    return model

The backend should provide the REST api path http://127.0.0.1/record/1.

Customerized

change default request url

Your backend server may provide REST api like http://127.0.0.1/api/records. You could add namesapce to your rest adapter.

1
2
MyAdapter = DS.RESTAdapter.extend
  namespace: 'api'

change single model request url

Your backend server doesn’t provide REST api http://127.0.0.1/api/records but http://127.0.0.1/api/usages. The responsed json format doesn’t change.

1
2
3
4
5
6
7
8
9
10
11
records_pattern = ///
  api/records
///

MyAdapter = DS.RESTAdapter.extend
  namespace: 'api'
  buildURL: (type,id)->
    url = @._super(type, id)
    if url.match records_pattern
      url = url.replace 'records', 'usages'
    return url

change root of responsed json

Your backend server change the default json format from

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "records": [{
    "id":"1",
    "amount":150,
    "category_id":1,
    "description":"dinner"
  },
  {
    "id":"2",
    "amount":250,
    "category_id":1,
    "description":"lunch"
  }]
}

to

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "usages": [{
    "id":"1",
    "amount":150,
    "category_id":1,
    "description":"dinner"
  },
  {
    "id":"2",
    "amount":250,
    "category_id":1,
    "description":"lunch"
  }]
}

Simple extend the original serializer and overwrite methods

1
2
3
MyApp.RecordSerializer = DS.RESTSerializer.extend
  typeForRoot: (root) ->
    return "usage"

Refer to rest_serializer.js to know more customerized.

Comments