Подтвердить что ты не робот

Обработка ошибок с помощью адаптера (теперь по умолчанию) Ember Data JSON-API

Я использую Ember 1.13.7 и Ember Data 1.13.8, которые по умолчанию используют стандарт JSON-API для форматирования полезных нагрузок, отправленных и полученных от API.

Я хотел бы использовать встроенную обработку ошибок Ember Data для отображения красных полей формы "ошибка" для пользователя. Я отформатировал свои ответы об ошибках API в соответствии со стандартом JSON-API, например

{"errors":[
    {
        "title":"The included.1.attributes.street name field is required.", 
        "code":"API_ERR", 
        "status":"400", 
    }
]}

и когда я пытаюсь сохранить свою модель, обратный вызов ошибки выполняется правильно. Если я посмотрю внутри Ember Inspector, я вижу, что для значения модели isError установлено значение true, но я не вижу, как Ember Data должен знать, какое поле в модели является единицей в состоянии ошибки? Я вижу на официальных страницах JSON-API (http://jsonapi.org/format/#errors), что вы можете включить в исходный код объект в ответ на ошибку:

source: объект, содержащий ссылки на источник ошибки, необязательно включая любой из следующих элементов:

: указатель JSON [RFC6901] связанному объекту в документе запроса   [например. "/data" для первичного объекта данных или "/data/attributes/title"   для определенного атрибута].

     

: строка, указывающая, какой запрос   параметр вызвал ошибку.

но это то, что я должен делать, чтобы сообщить Ember Data, какие поля должны быть отмечены как находящиеся в состоянии ошибки?

Если кто-то может помочь пролить свет на это, я был бы благодарен.

Спасибо.

4b9b3361

Ответ 1

Примечание. Ответ ниже основан на следующих версиях:

DEBUG: -------------------------------
ember.debug.js:5442DEBUG: Ember                     : 1.13.8
ember.debug.js:5442DEBUG: Ember Data                : 1.13.9
ember.debug.js:5442DEBUG: jQuery                    : 1.11.3
DEBUG: -------------------------------

Документация по обработке ошибок, к сожалению, разбросана на данный момент, так как способ обработки ошибок для разных адаптеров (Active, REST, JSON) все немного отличается.

В вашем случае вы хотите обрабатывать ошибки проверки для своей формы, что, вероятно, означает ошибки проверки. Формат ошибок, указанных в JSON API, можно найти здесь: http://jsonapi.org/format/#error-objects

Вы заметите, что API только указывает, что ошибки возвращаются в массив верхнего уровня с ключом errors, а все другие атрибуты ошибок являются необязательными. Таким образом, похоже, что все, что требуется JSON API, следующее:

{
    "errors": [
     {}
    ]
}  

Конечно, на самом деле ничего не получится, поэтому для ошибок, возникающих из-за ошибок с Ember Data и JSONAPIAdapter, вам нужно будет включить как минимум атрибут detail и атрибут source/pointer. Атрибут detail - это то, что устанавливается как сообщение об ошибке, а атрибут source/pointer позволяет Ember Data определять, какой атрибут в модели вызывает проблему. Таким образом, действительный объект ошибки JSON API, как требуется Ember Data (если вы используете JSONAPI, который сейчас является значением по умолчанию), выглядит примерно так:

{
    "errors": [
     {
        "detail": "The attribute `is-admin` is required",
        "source": {
             "pointer": "data/attributes/is-admin"
         }
     }
    ]
}  

Обратите внимание, что detail не является множественным (общая ошибка для меня) и что значение для source/pointer не должно содержать ведущую косую черту и имя атрибута должно быть дешифровано.

Наконец, вы должны вернуть свою ошибку проверки с помощью HTTP-кода 422, что означает "Непроцессная сущность". Если вы не вернете код 422, то по умолчанию Ember Data вернет AdapterError и не будет устанавливать сообщения об ошибках в хеше модели errors. Это немного меня немного, потому что я использовал HTTP-код 400 (Bad Request), чтобы возвращать ошибки проверки клиенту.

Способ, которым данные ember различают два типа ошибок, заключается в том, что ошибка проверки возвращает объект InvalidError (http://emberjs.com/api/data/classes/DS.InvalidError.html). Это приведет к установке хеша errors для модели, но не будет устанавливать флаг isError в значение true (не уверен, почему это так, но оно описано здесь: http://emberjs.com/api/data/classes/DS.Model.html#property_isError). По умолчанию код ошибки HTTP, отличный от 422, приведет к возврату AdapterError, а флаг isError - к true. В обоих случаях будет вызываться обработчик отклонения обещаний.

model.save().then(function(){
    // yay! it worked
}, function(){
    // it failed for some reason possibly a Bad Request (400)
    // possibly a validation error (422)
}

По умолчанию, если возвращаемый HTTP-код является 422, и у вас есть правильный формат ошибок JSON API, вы можете получить доступ к сообщениям об ошибках, обратившись к хэш файлу ошибок модели, где хеш-ключи являются вашими именами атрибутов. Хэш вводится по имени атрибута в формате camelcase.

Например, в нашем примере примера ошибки json-api, если есть ошибка на is-admin, вы получите эту ошибку следующим образом:

model.get('errors.isAdmin');

Это приведет к возврату массива, содержащего объекты ошибки, где формат выглядит следующим образом:

[
   {
      "attribute": "isAdmin",
      "message": "The attribute `is-admin` is required"
    }
]

По существу detail отображается на message, а source/pointer отображается на attribute. Массив возвращается в случае, если у вас есть несколько ошибок проверки на один атрибут (JSON API позволяет вам возвращать несколько ошибок проверки, а не возвращать только первую проверку для отказа). Вы можете использовать значения ошибок непосредственно в шаблоне следующим образом:

{{#each model.errors.isAdmin as |error|}}
    <div class="error">
      {{error.message}}
    </div>
{{/each}}

Если ошибок нет, вышесказанное не будет отображать что-либо, чтобы оно хорошо работало для создания сообщений проверки формы.

Если API не использует код HTTP 422 для ошибок проверки (например, если он использует 400), вы можете изменить поведение по умолчанию JSONAPIAdapter, переопределив метод handleResponse в вашем пользовательском адаптере. Вот пример, который возвращает новый объект InvalidError для любого кода состояния ответа HTTP, который 400.

import DS from "ember-data";
import Ember from "ember";

export default DS.JSONAPIAdapter.extend({
  handleResponse: function(status, headers, payload){
    if(status === 400 && payload.errors){
      return new DS.InvalidError(payload.errors);
    }
    return this._super(...arguments);
  }
});

В приведенном выше примере я проверяю, есть ли статус HTTP 400 и убедитесь, что свойство errors существует. Если да, то создаю новый DS.InvalidError и вернем это. Это приведет к тому же поведению, что и поведение по умолчанию, которое ожидает код состояния 422 HTTP (т.е. Ваша ошибка JSON API будет обработана и сообщение помещено в хэш ошибок в модели).

Надеюсь, что это поможет!