vendredi 29 mai 2015

EmberData Setting value prevents future autoloads of data after model save

In EmberData calling model.save() causes the model to be persisted via whatever adapter is in place. If the adapter returns some data (such as JSON from an API) the model is updated with that data.

I have stumbled upon a sequence where this is not true.

In a voucher system for a checkout process a voucherCode is entered on an order model. When an 'Apply' button is pressed the order is saved via order.save() and the voucher is thus submitted to the server.

If the voucher code is valid a voucherValue field is populated with a number. If the voucher code is invalid a 422 error is returned with a standard errors object as per http://ift.tt/1kd5W52

Now, here is where things go awry. If a code is entered that returns a voucherValue of 300 a controller property calculates the discount.

discount: function () {
  var discount = this.get('model.voucherValue');
  // some calculation
  return discount;
}.property('model.voucherValue')

If, for whatever reason, the user then enters an invalid code we return an error as described above. The server removes the discount and sets the voucherValue to 0

As the error response does not contain the updated data in the catch of the save we manually update it.

order.save().then(function () {

}).catch(function (error) {

  order.set('voucherValue', 0);
});

The discount computed property is updated as expected on setting the voucherValue. However, inspecting the order model shows that order._data.voucherValue is still the original 300 value from the first valid voucher code - as EmberData does not know this value is persisted on the server.

If we then enter a valid voucher code that returns a voucherValue of 300 (the same as it was originally) the discount computed property is not recalculated.

It appears Ember is checking the returned data values against order._data and as there is no difference is not triggering any property recalculations.

I've tried different workarounds but have been unable to find something that works reliably.

Frustratingly there does not seem to be a reliable way to access the returned data and manually set the voucherValue from the returned data. Even if the returned data sets a value for voucherValue the following is true:

order.save().then(function (savedOrder) {

  savedOrder.get('voucherValue') === 0; //true

}).catch(function (error) {
  order.set('voucherValue', 0);
});

However, if a different voucher is entered after an invalid voucher and the voucherValue is different (say 450) everything works as expected.

Is this a bug in EmberData? Is there a know workaround. I'm open to suggestions and willing to try anything before I try and reengineer how this entire system is implemented.




Aucun commentaire:

Enregistrer un commentaire