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

Add*_*son 2 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')
});
Run Code Online (Sandbox Code Playgroud)

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

/* my webpage */
Please enter name: "foo"
Please enter value: 5
Run Code Online (Sandbox Code Playgroud)

但是当我发送请求时,它应该将它们发送为:

{
    "my_model": {
        "name": "foo",
        "value": 5000
    }
}
Run Code Online (Sandbox Code Playgroud)

它应该收到他们以这种格式,但随后由1000除以deserialise值。

请注意,乘以/除以 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

export default DS.RESTSerializer.extend({
    primaryKey: 'name',
});
Run Code Online (Sandbox Code Playgroud)

jel*_*han 5

我建议为该用例使用Ember 数据转换。与覆盖 Serializernormalizeserialize方法相比,它更可重用且更好地分离关注点。Ember 数据转换可以被视为特定于属性的(反)序列化器。有一些内置的转换: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;
  }
});
Run Code Online (Sandbox Code Playgroud)

它可以像这样使用:

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

export default DS.Model.extend({
  name: DS.attr('string'),
  value: DS.attr('currency')
});
Run Code Online (Sandbox Code Playgroud)

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