trilingue políglota poliglota comprar complutense biblia bac amberes ember.js ember-data

ember.js - políglota - La propiedad de errores del modelo de datos de Ember(DS.Errors) no se completa



biblia políglota complutense polyglot (3)

Estoy usando Ember Data y parece que no puedo completar la propiedad de ''errores'' del modelo con los mensajes de error de mi API REST. Casi estoy siguiendo el ejemplo en esta guía:

http://emberjs.com/api/data/classes/DS.Errors.html

Mi aplicación se ve así:

window.App = Ember.Application.create(); App.User = DS.Model.extend({ username: DS.attr(''string''), email: DS.attr(''string'') }); App.ApplicationRoute = Ember.Route.extend({ model: function () { return this.store.createRecord(''user'', { username: ''mike'', email: ''invalidEmail'' }); }, actions: { save: function () { this.modelFor(this.routeName).save(); } } });

Y mi API devuelve esto:

HTTP/1.1 400 Bad Request Content-Type: application/json; charset=utf-8 Content-Length: 125 { "errors": { "username": ["Username is taken!"], "email": ["Email is invalid."] } }

Después de llamar a save () en el modelo, esto es lo que veo en el modelo de usuario:

user.get(''isError'') // true user.get(''errors.messages'') // []

Aunque el modelo está registrando correctamente la propiedad isError, parece que no puedo completar los mensajes de error. ¿Cómo puedo hacer que esto funcione? Estoy trabajando en la última versión beta de Ember Data versión 1.0.0-beta.8.2a68c63a


Tuve una experiencia larga y muy frustrante con la propiedad errors.messages de Ember Data, así que pensé en resumir todos mis hallazgos aquí en caso de que alguien más intente usar esta característica.

1) La documentación está desactualizada

Como @ kingpin2k mencionó en su respuesta, la documentación en http://emberjs.com/api/data/classes/DS.Errors.html está desactualizada. El ejemplo que proporcionan en esa página solo funciona si está utilizando DS.ActiveModelAdapter. Si está utilizando el DS.RESTAdapter predeterminado, entonces debe hacer algo como esto. Tenga en cuenta que prefiero este enfoque más simple en lugar de solo copiar la implementación ajaxError de ActiveModelAdapter:

App.ApplicationAdapter = DS.RESTAdapter.extend({ ajaxError: function (jqXHR) { this._super(jqXHR); var response = Ember.$.parseJSON(jqXHR.responseText); if (response.errors) return new DS.InvalidError(response.errors); else return new DS.InvalidError({ summary: ''Error connecting to the server.'' }); } });

2) Debe proporcionar una devolución de llamada rechazada

Esto es muy extraño, pero cuando llama a save () en su modelo, debe proporcionar una devolución de llamada rechazada, de lo contrario, obtendrá una excepción no capturada ''back-end rechazó la confirmación'' y JavaScript dejará de ejecutarse. No tengo idea de por qué este es el caso.

Ejemplo sin rechazar devolución de llamada. Esto dará como resultado una excepción:

user.save().then(function (model) { // do something });

Ejemplo con rechazo de devolución de llamada. Todo va a funcionar bien:

user.save().then(function (model) { // do something }, function (error) { // must supply reject callback, otherwise Ember will throw a ''backend rejected the commit'' error. });

3) De forma predeterminada, solo las propiedades de error que forman parte del modelo se registrarán en errors.messages. Por ejemplo, si este es tu modelo:

App.User = DS.Model.extend({ firstName: DS.attr(''string''), lastName: DS.attr(''string'') });

... y si esta es tu carga de error:

{ "errors": { "firstName":"is required", "summary":"something went wrong" } }

Entonces, el resumen no aparecerá en user.get (''errors.messages''). El origen de este problema se puede encontrar en el método adapterDidInvalidate de Ember Data. Utiliza this.eachAttribute y this.eachRelationship para restringir el registro de mensajes de error solo a aquellos que son parte del modelo.

adapterDidInvalidate: function(errors) { var recordErrors = get(this, ''errors''); function addError(name) { if (errors[name]) { recordErrors.add(name, errors[name]); } } this.eachAttribute(addError); this.eachRelationship(addError); }

Hay una discusión sobre este tema aquí: https://github.com/emberjs/data/issues/1877

Hasta que el equipo Ember solucione esto, puede solucionar este problema creando un modelo base personalizado que anule la implementación predeterminada de adapterDidInvalidate, y todos sus otros modelos heredarán de ella:

Modelo base:

App.Model = DS.Model.extend({ adapterDidInvalidate: function (errors) { var recordErrors = this.get(''errors''); Ember.keys(errors).forEach(function (key) { recordErrors.add(key, errors[key]); }); } });

Modelo de usuario:

App.User = App.Model.extend({ firstName: DS.attr(''string''), lastName: DS.attr(''string'') });

4) Si devuelve DS.InvalidError del adaptador ajaxError (el que anulamos anteriormente), su modelo quedará bloqueado en el estado ''isSaving'' y no podrá salir de él.

Este problema también es el caso si está utilizando DS.ActiveModelAdapter.

Por ejemplo:

user.deleteRecord(); user.save().then(function (model) { // do something }, function (error) { });

Cuando el servidor responde con un error, el estado de ahorro del modelo es verdadero y no puedo resolver reiniciarlo sin volver a cargar la página.

Actualización: 2014-10-30 Para cualquiera que esté luchando con DS.Errors, aquí hay una excelente publicación de blog que resume bien esto: http://alexspeller.com/server-side-validations-with-ember-data-and-ds- errores /


ACTUALIZACIÓN: Ember Data 2.x

La respuesta anterior sigue siendo algo relevante y, en general, bastante útil, pero ahora está desactualizada para Ember Data 2.x (v2.5.1 al momento de escribir esto). Aquí hay algunas cosas que debe tener en cuenta cuando trabaje con versiones más nuevas de Ember Data:

  • DS.RESTAdapter ya no tiene una función ajaxError en 2.x. Esto ahora lo maneja RESTAdapter.handleResponse() . Puede anular este método si se requiere un manejo especial o formateo de errores. Código fuente RESTAdapter.handleResponse
  • La documentación para DS.Errors y DS.Model.errors (que es una instancia de DS.Errors) es actualmente un poco engañosa. SÓLO funciona cuando los errores en la respuesta se adhieren a la especificación del objeto de error de la API JSON . Esto significa que no será del todo útil o utilizable si sus objetos de error de API siguen cualquier otro formato. Desafortunadamente, este comportamiento actualmente no se puede anular como muchas otras cosas en Ember Data, ya que este comportamiento se maneja en API privadas dentro de la clase InternalModel de Ember dentro de DS.Model.
  • DS.InvalidError solo se usará si el código de estado de la respuesta es 422 por defecto. Si su API utiliza un código de estado diferente para representar los errores de las solicitudes no válidas, puede anular RESTAdapter.isInvalid() para personalizar qué códigos de estado (u otra parte de una respuesta de error) comprobar que representan un InvalidError .
  • Como alternativa, puede anular isInvalid() para que siempre devuelva false, de modo que Ember Data siempre creará un DS.AdapterError más genérico en DS.AdapterError lugar . Este error se establece en DS.Model.adapterError y se puede aprovechar según sea necesario desde allí.
  • DS.AdapterError.errors contiene lo que se devolvió en la clave de errors de la respuesta de la API.

Los documentos definitivamente no existen en esta área, los errores no se completan a menos que esté utilizando el adaptador de modelo activo.

Aquí hay un ejemplo de que funciona, también echa un vistazo a Ember: error.messages no muestra errores del servidor en guardar donde digo lo mismo

http://jsbin.com/motuvaye/24/edit

Puede implementarlo fácilmente en el adaptador RESTA redefiniendo ajaxError y copiando cómo lo hace el adaptador de modelo activo.

App.ApplicationAdapter = DS.RESTAdapter.extend({ ajaxError: function(jqXHR) { var error = this._super(jqXHR); if (jqXHR && jqXHR.status === 422) { var response = Ember.$.parseJSON(jqXHR.responseText), errors = {}; if (response.errors !== undefined) { var jsonErrors = response.errors; Ember.EnumerableUtils.forEach(Ember.keys(jsonErrors), function(key) { errors[Ember.String.camelize(key)] = jsonErrors[key]; }); } return new DS.InvalidError(errors); } else { return error; } } });

http://jsbin.com/motuvaye/27/edit

https://github.com/emberjs/data/blob/v1.0.0-beta.8/packages/activemodel-adapter/lib/system/active_model_adapter.js#L102