我有一个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',
});
答案 0 :(得分:5)
对于该用例,我建议使用Ember Data transform。与重写Serializer的normalize
和serialize
方法相比,它更可重用,并且关注点分离更好。灰烬数据转换可以看作是属性特定的(反)序列化器。有一些内置的转换:string
,number
,boolean
和date
。您已经在使用其中的一些。
您应该从默认蓝图开始编写一个自定义序列化程序:ember generate transform currency
。这将生成文件app/transforms/currency.js
和相关的单元测试。转换扩展了DS.Transform
类,并且必须实现serialize
和deserialize
方法。他们获得(反)序列化的值作为参数,并且应该返回相反的值。
重构此处给出的答案作为示例的示例看起来像这样:
// 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)
我用自定义的serialize
和normalize
(反序列化)方法解决了这个问题:
// 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;
}
});
这对我来说很好,并且非常灵活。