12

有谁知道为 Ember 指定model不持久属性的方法?

基本上,我们正在加载一些与每个模型相关的元数据,并通过模型内部将这些数据发送到 Ember RESTAdapter。此元数据可以在我们的应用程序中更改,但通过使用 AJAX 调用来完成。一旦调用成功,我希望能够在模型中更新此值,而 Ember 通过将模型更改为并在幕后uncommitted执行它所做的任何事情,从而不会在此业务中插手。transactions

我还有一个问题,即这个元数据(不是来自model的数据库记录的数据)被传RESTAdapter回服务器,而服务器并不期望这些值。我正在使用 RoR 后端,因此服务器在尝试批量分配根本不应该成为属性的受保护属性时出错。我知道我可以清理服务器上接收到的数据,但我希望客户端能够区分持久数据和辅助数据。

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

4

4 回答 4

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})
});

这些属性在保存记录时不会发送到服务器。

于 2013-10-17T12:43:04.913 回答
6

当这个PR得到合并时,可以将属性标记为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设置了标志的属性时,它会跳过该属性。

我希望这种机制适用于您的用例。

于 2013-05-16T14:02:15.303 回答
6

按照这个答案,为防止字段被序列化,请覆盖模型的默认序列化程序:

app/serializers/person.js

export default DS.JSONSerializer.extend({
  attrs: {
    admin: { serialize: false }
  }
});

有关源 PR,请参见此处。此解决方案适用于 Ember Data 2,也应该适用于旧版本。

于 2014-08-26T19:56:03.810 回答
1

更新

此答案很可能与当前版本的 Ember Data 已过时。我不会在我的答案中使用任何东西。


我正在回答这个问题以供参考,因为您的评论表明记录仍然存在isDirty,但这是我对read-onlynon-persistentnon-dirty属性的解决方案。

覆盖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

这个设置对我有用。

于 2013-06-26T18:08:39.647 回答