EmberJS中的非持久属性

时间:2013-05-16 13:05:37

标签: ember.js

有没有人知道如何为Ember model指定一个不持久的属性?

基本上,我们正在加载与每个模型相关的一些元数据,并通过模型中的RESTAdapter将数据发送到Ember。这个元数据可以在我们的应用程序中更改,但可以通过使用AJAX调用来完成。一旦调用成功,我希望能够在模型中更新此值,而不会让Ember在此业务中坚持不懈,方法是将模型更改为uncommitted,并在幕后使用transactions执行任何操作

我还遇到这样的问题:这个元数据(不是model的数据库记录中的数据)被RESTAdapter传递回服务器,服务器不期望这些值。我正在使用RoR后端,因此服务器错误地尝试大量分配受保护的属性,这些属性根本不属于属性。我知道我可以擦除服务器上收到的数据,但我希望客户端能够区分持久数据和辅助数据。

那么,对于最初的问题:是否有任何替代Ember-Data的DS.attr('...')将指定非持久属性?

4 个答案:

答案 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

此设置对我有用。