有没有人知道如何为Ember model
指定一个不持久的属性?
基本上,我们正在加载与每个模型相关的一些元数据,并通过模型中的RESTAdapter
将数据发送到Ember。这个元数据可以在我们的应用程序中更改,但可以通过使用AJAX调用来完成。一旦调用成功,我希望能够在模型中更新此值,而不会让Ember在此业务中坚持不懈,方法是将模型更改为uncommitted
,并在幕后使用transactions
执行任何操作
我还遇到这样的问题:这个元数据(不是model
的数据库记录中的数据)被RESTAdapter
传递回服务器,服务器不期望这些值。我正在使用RoR后端,因此服务器错误地尝试大量分配受保护的属性,这些属性根本不属于属性。我知道我可以擦除服务器上收到的数据,但我希望客户端能够区分持久数据和辅助数据。
那么,对于最初的问题:是否有任何替代Ember-Data的DS.attr('...')
将指定非持久属性?
答案 0 :(得分:13)
此问题的其他答案适用于最高0.13的Ember数据版本,并且不再有效。 对于 Ember数据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})
});
保存记录时,这些属性不会发送到服务器。
答案 1 :(得分:6)
遵循此answer,为防止字段序列化,请覆盖模型的默认序列化程序:
在app/serializers/person.js
:
export default DS.JSONSerializer.extend({
attrs: {
admin: { serialize: false }
}
});
See here来源PR。此解决方案适用于Ember Data 2,也适用于旧版本。
答案 2 :(得分:5)
当合并PR get时,可以将属性标记为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
标志的属性时,它会跳过该属性。
我希望这种机制适用于您的用例。
答案 3 :(得分:1)
此答案很可能与当前版本的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
此设置对我有用。