我有一个带有时间戳属性的模型。在服务器上创建记录时,我希望该属性的值由服务器而不是客户端提供值初始化,以便这些时间戳在不同客户端之间保持一致。
如果我直接使用 firebase API,那么我知道我可以使用特殊令牌 Firebase.ServerValue.TIMESTAMP 来实现这一点。但我不知道如何使用 ember-data 和 emberfire 适配器来做到这一点。
我有一个带有时间戳属性的模型。在服务器上创建记录时,我希望该属性的值由服务器而不是客户端提供值初始化,以便这些时间戳在不同客户端之间保持一致。
如果我直接使用 firebase API,那么我知道我可以使用特殊令牌 Firebase.ServerValue.TIMESTAMP 来实现这一点。但我不知道如何使用 ember-data 和 emberfire 适配器来做到这一点。
抱歉,我知道这已经晚了,但我遇到了同样的问题。
您可以使用 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),因此 Store 方法未定义,而不是序列化记录。就铺平这个用例而言,理想情况下,这是我想要定位解决方案的地方。
看起来服务器时间是作为估计生成的,无论如何通过连接服务器 websocket 时设置的时间偏移变量在客户端上同步生成。因此,当您使用 Firebase.ServerValues.TIMESTAMP 值保存/更新记录时,它会占用客户端时间,通过偏移量对其进行修改,并使用它创建更新数据。这看起来会被修改为服务器上的实际值,并且修改最终会传播到客户端。-- 如果你真的需要立即的值,你可以第二次保存你的记录,它会给你服务器生成的值。
默认date
转换将转换为Firebase.ServerValue.TIMESTAMP
,null
因为它不是Date对象(请参阅转换的检查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 基本序列化程序中。