I have a model with a timestamp attribute. When records are created on the server I would like the value of this attribute to be initialized with a value by the server rather than the client providing the value, so that these timestamps are consistent between different clients.
If I was using the firebase API directly then I understand that I could use the special token Firebase.ServerValue.TIMESTAMP to achieve this. But I can't work out how to do this with ember-data and the emberfire adapter.
Sorry, I know this is late, but I ran into the same problem.
You can define a custom attribute type with a DS.Transform that just passes that value through, as is, when you serialize it. I just named mine timestamp.
// 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);
}
});
Then you can use it about as expected:
// models/somemodel.js
import DS from 'ember-data';
export default DS.Model.extend({
createdAt: DS.attr("timestamp")
});
And then in some controller or something:
this.store.createRecord("somemodel", { createdAt: Firebase.ServerValue.TIMESTAMP });
When you save it, it'll set the field with the right value on the server's copy, but the local record won't be updated with that value. I'm still working out how to approach fixing this, but the new Ember Data Store.fetch() method seems like a worst case solution once EmberFire is brought up to date.
edit:
Did some more digging. Some notes:
When you create a record with this method, and call save() on it, DS.Store calls a didCreateRecord event handler that normally deserializes the server returned record (which is where you normally get model IDs and stuff), but in this case, it doesn't deserialize, because FirebaseAdapter's create/updateRecord methods return promises that call their resolve handlers without any arguments (https://github.com/firebase/emberfire/blob/v1.3.1/src/data.js#L492), so the Store method gets undefined, instead of a serialized record. In terms of paving this use case, this is where I'd want to target a solution, ideally.
It looks like the server time is generated as an estimate, synchronously on the client anyway via a time offset variable that gets set when you connect the server websocket. So when you go to save/update a record with the Firebase.ServerValues.TIMESTAMP value, it takes the client time, modifies it by the offset, and creates the update data with it. This looks to get modified to the actual value on the server, and the modification will eventually propagate to the client. -- If you really need the value immediately, you can save your record a second time, and it will give you the server generated value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With