有没有办法使用emberfire指定模型上的timestamp属性应该赋予Firebase.ServerValue.TIMESTAMP值?

时间:2014-10-11 14:01:26

标签: ember.js ember-data emberfire

我有一个带有timestamp属性的模型。当在服务器上创建记录时,我希望服务器而不是提供值的客户端使用值初始化此属性的值,以便这些时间戳在不同客户端之间保持一致。

如果我直接使用firebase API,那么我理解我可以使用特殊令牌Firebase.ServerValue.TIMESTAMP来实现这一点。但我无法通过ember-data和emberfire适配器来解决这个问题。

2 个答案:

答案 0 :(得分:8)

抱歉,我知道这已经很晚了,但我遇到了同样的问题。

您可以使用直接传递该值的DS.Transform定义自定义属性类型,就像序列化它一样。我只是命名我的时间戳。

// transforms/timestamp.js
/* global Firebase */
import DS from 'ember-data';

export default DS.DateTransform.extend({
    serialize: function(date) {
        if(date === Firebase.ServerValue.TIMESTAMP){
            return date;
        }
        return this._super(date);
    }
});

然后你可以按预期使用它:

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

export default DS.Model.extend({
    createdAt: DS.attr("timestamp")
});

然后在某些控制器或其他东西:

this.store.createRecord("somemodel", { createdAt: Firebase.ServerValue.TIMESTAMP });

保存时,它会在服务器副本上设置具有正确值的字段,但不会使用该值更新本地记录。我还在研究如何解决这个问题,但是一旦EmberFire更新,新的Ember Data Store.fetch()方法似乎是最糟糕的解决方案。

编辑:

进行了更多挖掘。一些说明:

  • 使用此方法创建记录并在其上调用save()时,DS.Store会调用didCreateRecord事件处理程序,该处理程序通常会反序列化服务器返回的记录(通常是您获取模型ID和内容的位置) ,但在这种情况下,它不会反序列化,因为FirebaseAdapter的create / updateRecord方法返回调用其解析处理程序而没有任何参数(https://github.com/firebase/emberfire/blob/v1.3.1/src/data.js#L492)的promise,因此Store方法未定义,而不是序列化记录。就铺设这个用例而言,理想情况下,这是我想要定位解决方案的地方。

  • 看起来服务器时间是作为估计生成的,无论如何通过在连接服务器websocket时设置的时间偏移量变量在客户端上同步生成。因此,当您使用Firebase.ServerValues.TIMESTAMP值保存/更新记录时,它将花费客户端时间,通过偏移修改它,并使用它创建更新数据。这看起来被修改为服务器上的实际值,并且修改最终将传播到客户端。 - 如果您确实需要立即获得该值,您可以再次保存您的记录,它将为您提供服务器生成的值。

答案 1 :(得分:3)

默认date转换正在将Firebase.ServerValue.TIMESTAMP转换为null,因为它不是日期对象(see the transform's check here)。

您可以创建自定义转换,也可以覆盖属性序列化代码,以便不加改变地传递Firebase常量。我更喜欢在序列化器中覆盖,因此不需要特殊的转换:

// app/serializers/application.js

import Firebase from 'firebase';
import FirebaseSerializer from 'emberfire/serializers/firebase';

export default FirebaseSerializer.extend({

  /**
   * Override the attribute serializer to pass through
   * Firebase.ServerValue.TIMESTAMP unaltered.
   *
   * @override
   */
  serializeAttribute(snapshot, json, key, attribute) {
    this._super(snapshot, json, key, attribute);

    var value = snapshot.attr(key);

    if (this._canSerialize(key)) {
      if (value === Firebase.ServerValue.TIMESTAMP) {
        var payloadKey = this._getMappedKey(key);
        if (payloadKey === key) {
          payloadKey = this.keyForAttribute(key, 'serialize');
        }

        // do not transform
        json[payloadKey] = value;
      }
    }
  }

});

我将把它集成到emberfire基本序列化器中。