保存到服务器之前更改Ember模型的值

时间:2019-08-26 01:24:30

标签: ember.js ember-data

我有一个Ember模型,它具有要显示和使用的字段,但是在我从服务器保存或检索它之前,我想将其乘以/除以1000。

这意味着UI应当始终使用较小的值,但应将较大的值保存到服务器。同样,它应从服务器检索较大的值,但在允许它被控制器,路由等使用之前将其减小。

// models/my_model.js
import DS from 'ember-data';

export default DS.Model.extend({
    name: DS.attr('string'),
    value: DS.attr('number')
});

本质上,我希望我的应用程序将这些字段显示为:

/* my webpage */
Please enter name: "foo"
Please enter value: 5

但是当我发送请求时,它应该以以下方式发送它们:

{
    "my_model": {
        "name": "foo",
        "value": 5000
    }
}

它也应该 以这种格式接收它们,然后用1000除以反序列化该值。

请注意,以1000乘除为例-我可能想追加,添加,添加,减去等


我尝试用一​​种不太优雅的方式做到这一点:

// Controller.js
actions: {
    save: function() {
        this.set('model.value', this.get('model.value') * 1000);
        this.get('model').save().then(
            /* stuff */
        );
        this.set('model.value', this.get('model.value') / 1000);
    }
}

但是我对此并不满意,它导致重复的代码难以维护且容易出错。

我有一个RESTSerializer,但是我不知道如何使用它来操作字段,并且在the documentation中找不到任何内容。也许我需要使用其他序列化器?到目前为止,我的基本上是空的。

// serializers/my_model.js
import DS from 'ember-data';

export default DS.RESTSerializer.extend({
    primaryKey: 'name',
});

2 个答案:

答案 0 :(得分:5)

对于该用例,我建议使用Ember Data transform。与重写Serializer的normalizeserialize方法相比,它更可重用,并且关注点分离更好。灰烬数据转换可以看作是属性特定的(反)序列化器。有一些内置的转换:stringnumberbooleandate。您已经在使用其中的一些。

您应该从默认蓝图开始编写一个自定义序列化程序:ember generate transform currency。这将生成文件app/transforms/currency.js和相关的单元测试。转换扩展了DS.Transform类,并且必须实现serializedeserialize方法。他们获得(反)序列化的值作为参数,并且应该返回相反的值。

重构此处给出的答案作为示例的示例看起来像这样:

// app/transforms/currency.js

import DS from 'ember-data';

export default DS.Transform.extend({
  deserialize(serialized) {
    return serialized / 1000;
  },

  serialize(deserialized) {
    return deserialized * 1000;
  }
});

它可以这样使用:

// models/my_model.js
import DS from 'ember-data';

export default DS.Model.extend({
  name: DS.attr('string'),
  value: DS.attr('currency')
});

最大的好处是,它可以根据需要在任意数量的模型中应用于任意数量的属性。它还可以进行单元测试以分离其他序列化问题,并且可以作为Ember Addon轻松在应用程序之间共享。

答案 1 :(得分:0)

我用自定义的serializenormalize(反序列化)方法解决了这个问题:

// serializers/my_model.js
import DS from 'ember-data';

export default DS.RESTSerializer.extend({
    normalizeResponse(store, primaryModelClass, payload) {
        payload.my_model.value /= 1000;
        return this._super(...arguments);
    },
    serialize() {
        let json = this._super(...arguments);
        json.value *= 1000;
        return json;
    }
});

这对我来说很好,并且非常灵活。