Непостоянные атрибуты в EmberJS

Кто-нибудь знает способ указать для Ember model атрибут, который не сохранился?

По сути, мы загружаем некоторые метаданные, относящиеся к каждой модели, и отправляем эти данные в Ember через RESTAdapter в модели. Эти метаданные можно изменить в нашем приложении, но это делается с помощью вызова AJAX. Как только вызов завершится успешно, я хочу иметь возможность обновить это значение в модели, при этом Эмбер не сует свой нос в этом деле, изменив модель на uncommitted и делать то, что он делает с transactions за кулисами.

У меня также есть проблема, что это метаданные, которые не являются данными из modelзапись в базе данных, переданная RESTAdapter обратно на сервер, который не ожидает этих значений. Я использую бэкэнд RoR, поэтому сервер выдает ошибку при попытке массово назначить защищенные атрибуты, которые вообще не должны быть атрибутами. Я знаю, что могу очистить данные, полученные на сервере, но я бы предпочел, чтобы клиент мог различать постоянные данные и вспомогательные данные.

Итак, к первоначальному вопросу: есть ли альтернатива Ember-Data? DS.attr('...') который будет указывать непостоянный атрибут?

4 ответа

Решение

После слияния этого PR можно пометить свойства как readOnly, Но до этого есть некоторые обходные пути, например, переопределение вашего addAttributes метод в адаптере и разобраться с вашими специальными свойствами, вот пример, как это может выглядеть:

Определите свою модель, добавив новую опцию readOnly:

App.MyModel = DS.Model.extend({
  myMetaProperty: DS.attr('metaProperty', {readOnly: true})
});

а затем на адаптере:

App.Serializer = DS.RESTSerializer.extend({
   addAttributes: function(data, record) {
     record.eachAttribute(function(name, attribute) {
       if (!attribute.options.readOnly) {
         this._addAttribute(data, record, name, attribute.type);
       }
     }, this);
   }
 });

то, что это делает, это перебирать атрибуты вашей модели, и когда он находит атрибут с readOnly установленный флаг пропускает свойство.

Я надеюсь, что этот механизм работает для вашего случая использования.

Другие ответы на этот вопрос работают с версиями данных Ember до 0.13 и больше не работают. Для Ember data 1.0 beta 3 вы можете сделать:

App.ApplicationSerializer = DS.RESTSerializer.extend({
  serializeAttribute: function(record, json, key, attribute) {
    if (attribute.options.transient) {
      return;
    }
    return this._super(record, json, key, attribute);
  }
});

Теперь вы можете использовать временные атрибуты:

App.User = DS.Model.extend({
  name: DS.attr('string', {transient: true})
});

Эти атрибуты не будут отправлены на сервер при сохранении записей.

После этого ответа, чтобы предотвратить сериализацию поля, переопределите сериализатор по умолчанию для вашей модели:

В app/serializers/person.js:

export default DS.JSONSerializer.extend({
  attrs: {
    admin: { serialize: false }
  }
});

Смотрите здесь для источника PR. Это решение работает в Ember Data 2 и должно работать в более старых версиях.

Обновить

Этот ответ, скорее всего, устарел с текущими выпусками Ember Data. Я не буду ничего использовать в своем ответе.


Я отвечаю на этот вопрос для справки, и потому что ваш комментарий указал, что запись остается isDirty, но здесь мое решение для непостоянных, не грязных атрибутов только для чтения.

Переопределение addAtributes метод в вашем сериализаторе мешает readOnly атрибуты от отправки на сервер, что, вероятно, именно то, что вы хотите, но вы должны расширить (или reopen) ваш адаптер для переопределения dirtyRecordsForAttributeChange чтобы предотвратить загрязнение записи:

App.CustomAdapter = DS.RESTAdapter.extend({
  dirtyRecordsForAttributeChange: function(dirtySet, record, attrName, newValue, oldValue) {
    meta = record.constructor.metaForProperty(attrName);
    if (meta && meta.options.readOnly) { return; }
    this._super.apply(this, arguments);
  };
});

Тогда вы можете использовать readOnly атрибуты вроде так:

App.User = DS.Model.extend({
  name: DS.attr('string', {readOnly: true})
});

user = App.User.find(1);      # => {id: 1, name: 'John Doe'}
user.set('name', 'Jane Doe'); #
user.get('isDirty')           # => false

Эта настройка работает для меня.

Другие вопросы по тегам