javascript - ¿Cómo se crea un adaptador personalizado para ember.js?
ajax rest (3)
Estoy planeando usar ember.js, sin embargo mi API REST no se alinea exactamente con el adaptador REST empaquetado. Me gustaría "anular" encontrar y ser capaz de poner mi propio AJAX en él. No me gusta cómo una brasa findAll recupera todos mis documentos sin opciones de paginación, por lo que junto con otros parámetros de consulta sería útil, y es por eso que quiero escribir mi propio ajax. No he podido encontrar ninguna documentación sobre cómo iba a hacer esto.
Para Ember Data
Esto está actualizado a partir de Ember Data 1.0 beta 9.
Extienda uno de los adaptadores de datos Ember. Para hacerlo extensivo a todo el sitio:
App.ApplicationAdapter = DS.RESTAdapter.extend(....
Para que sea modelo específico:
App.FooAdapter = DS.RESTAdapter.extend(...
Luego, definirá la implementación que desea anular. Siempre tiene la opción de llamar a this._super
y volver a la implementación base. p.ej
App.NotesAdapter = DS.RESTAdapter.extend({
find: function(store, type, id) {
id = "foo" + id;
return this._super(store, type, id);
}
});
O puede anular completamente la implementación:
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 } });
},
.....
});
Para ver la API completa que puede anular ver: http://emberjs.com/api/data/classes/DS.RESTAdapter.html
Serializador
A menudo, lo más importante será desplegar su propio serializador para masajear los datos para que se adapten a su punto final de reposo. Aquí hay información útil del documento de transición https://github.com/emberjs/data/blob/master/TRANSITION.md .
La versión corta es que una vez que se completa una solicitud de Ajax, la carga útil resultante se envía a través de los siguientes enlaces:
- La carga útil se envía a extractSingle si la solicitud original era para un solo registro (como find / save) o extractArray si la solicitud original era para una matriz de registros (como findAll / findQuery)
- El comportamiento predeterminado de esos métodos es separar el nivel superior de la carga en múltiples registros más pequeños.
- Cada uno de esos registros más pequeños se envía a normalizar, lo que puede hacer la normalización un registro a la vez.
- Finalmente, los tipos específicos de registros pueden ser especialmente normalizados.
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); } });
- utilice extractSingle y extractArray cuando el nivel superior de su carga útil esté organizado de forma diferente de lo que Ember Data espera
- use normalize para normalizar sub hashes si todos los sub hashes en la carga útil se pueden normalizar de la misma manera.
- use normalizeHash para normalizar sub hashes específicos.
- asegúrese de llamar a super si anula extractSingle, extractArray o normalize para que se llame al resto de la cadena.
Rolando tu propio
App.FooAdapter = Ember.Object.extend({
find: function(id){
return $.getJSON(''http://www.foolandia.com/foooo/'' + id);
}
});
Luego de tu ruta, o donde sea
App.FooRoute = Ember.Route.extend({
model: function(){
var adapter = App.FooAdapter.create();
return adapter.find(1);
}
});
Ahora personalmente, inyectaría el adaptador en las rutas solo para hacer mi vida más fácil:
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");
}
});
Luego, en la ruta, podrías ser más holgazán y hacer:
App.FooRoute = Ember.Route.extend({
model: function(){
return this.fooAdapter.find(1);
}
});
Ejemplo: http://emberjs.jsbin.com/OxIDiVU/676/edit
Puede leer más sobre Ember sin Ember Data: Ember sin Ember Data
Para aquellos que codifican el adaptador ellos mismos, si necesita devolver un valor de su adaptador (por ejemplo, userId), puede devolver json o prometer. Aquí hay un ejemplo de promesa de regreso:
App.RequestAdapter = Ember.Object.extend({
newRequest: function (data) {
return new Ember.RSVP.Promise(function (resolve, reject) {
Ember.$.ajax({
type: ''POST'', // method post
url: ''/Request/Create'', //target url
data: JSON.stringify(data), //the JSON.stringify converts data to JSON
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (response) {
resolve(response);
},
error: function (reason) {
reject(reason);
}
});
});
}
});
//use this adapter in your controller
var adapter = App.RequestAdapter.create();
adapter.newRequest(data).then(function (response) { //newRequest is method of our adapter
console.log(response.userId); //specify response data
}, function(error){
//handle error
});
Puede obtener más información sobre las promesas de Ember aquí: https://hackhands.com/3-ways-ember-js-leverages-promises/ o aquí http://emberjs.com/api/classes/RSVP.Promise.html
Yo tuve el mismo problema. Yo también quería usar un formato ligeramente diferente con mi backend (cakePHP) y no pude encontrar la manera de hacerlo. Las respuestas anteriores son geniales, pero es posible que no necesite redefinir todos los métodos, sino simplemente cambiar el formato de la URL anulando el buildURL en RESTAdapter.
Por ejemplo, quiero usar la extensión de CakePHP y quiero que mis URL se vean así, a nivel de toda la aplicación:
- /users.json (findAll)
- /users/view/1.json (buscar)
- /users/delete/1.json
- /users/edit.json (POST)
- /users/add.json (POST)
Después de mucho esfuerzo y de darme cuenta de que los datos de Ember son esenciales, utilicé el siguiente código:
App.ApplicationAdapter = DS.RESTAdapter.extend({
buildURL: function(type, id) {
var url = ''/'' + this.pluralize(type.typeKey);
if (id) {
url += ''/'' + id;
}
url += ''.json'';
return url;
}
});
Los documentos de Ember son buenos, pero la mayoría de sus ejemplos usan datos de FIXTURE. Me gustaría que tuvieran un ejemplo simple de cómo escribir diferentes tipos de adaptadores para diferentes situaciones.