For Ember Data
This is up to date as of Ember Data 1.0 beta 9.
Extend one of the Ember Data Adapters. To make it site wide:
App.ApplicationAdapter = DS.RESTAdapter.extend(....
To make it model specific:
App.FooAdapter = DS.RESTAdapter.extend(...
Then you will define the implementation you'd like to override. You always have the option to call this._super
and revert to the base implementation. e.g.
App.NotesAdapter = DS.RESTAdapter.extend({
find: function(store, type, id) {
id = "foo" + id;
return this._super(store, type, id);
}
});
Or you can completely override the implementation:
App.NotesAdapter = DS.RESTAdapter.extend({
find: function(store, type, id) {
// Do your thing here
return this.ajax(this.buildURL(type.typeKey, id), 'GET');
},
findAll: function(store, type, sinceToken) {
// Do your thing here
var query;
if (sinceToken) {
query = { since: sinceToken };
}
return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });
},
findQuery: function(store, type, query) {
// Do your thing here
return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });
},
findMany: function(store, type, ids, owner) {
return this.ajax(this.buildURL(type.typeKey), 'GET', { data: { ids: ids } });
},
.....
});
To see the complete api you can override see: http://emberjs.com/api/data/classes/DS.RESTAdapter.html
Serializer
Often more important will be rolling your own serializer for massaging the data to fit your rest endpoint. Here's some useful information from the transition document https://github.com/emberjs/data/blob/master/TRANSITION.md .
The short version is that once an Ajax request has completed, the resulting payload is sent through the following hooks:
- The payload is sent to extractSingle if the original request was for a single record (like find/save) or extractArray if the original request was for an Array of records (like findAll/findQuery)
- The default behavior of those methods is to pull apart the top-level of the payload into multiple smaller records.
- Each of those smaller records is sent to normalize, which can do normalization a record at a time.
- Finally, specific types of records can be specially normalized.
App.PostSerializer = DS.RESTSerializer.extend({
extractSingle: function(store, type, payload, id) {
// massage
this._super(store, type, payload, id);
},
extractArray: function(store, type, payload) {
// massage
this._super(store, type, payload);
},
normalize: function(type, hash, property) {
// massage
this._super(type, hash, property);
}
});
- use extractSingle and extractArray when the top-level of your payload is organized differently than Ember Data expects
- use normalize to normalize sub-hashes if all sub-hashes in the payload can be normalized in the same way.
- use normalizeHash to normalize specific sub-hashes.
- make sure to call super if you override extractSingle, extractArray or normalize so the rest of the chain will get called.
Rolling your own
App.FooAdapter = Ember.Object.extend({
find: function(id){
return $.getJSON('http://www.foolandia.com/foooo/' + id);
}
});
Then from your route, or wherever
App.FooRoute = Ember.Route.extend({
model: function(){
var adapter = App.FooAdapter.create();
return adapter.find(1);
}
});
Now personally I'd inject the adapter onto the routes just to make my life easier:
App.initializer({
name: "fooAdapter",
initialize: function (container, application) {
application.register("my:manager", application.FooAdapter);
application.inject("controller", "fooAdapter", "my:manager");
application.inject("route", "fooAdapter", "my:manager");
}
});
Then on the route you could be lazier and do:
App.FooRoute = Ember.Route.extend({
model: function(){
return this.fooAdapter.find(1);
}
});
Example: http://emberjs.jsbin.com/OxIDiVU/676/edit
You can read more about Ember without Ember Data: Ember without Ember Data