A value of EmberData prevents future startups of data after saving the model

In EmberData, calling model.save() forces the model to persist through any adapter. If the adapter returns some data (for example, JSON from the API), the model is updated with this data.

I stumbled upon a sequence where this is not true.

In the voucher system, the order voucherCode is introduced for the voucherCode process. When the "Apply" button is clicked, the order is saved via order.save() , and the voucher is thus sent to the server.

If the voucher code is valid, the voucherValue field voucherValue filled with a number. If the voucher code is not valid, an error 422 returned with the standard errors object, according to http://emberjs.com/api/data/classes/DS.Errors.html

Now, this is where it all went wrong. If you enter code that returns voucherValue of 300 , the controller property calculates the discount.

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

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

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

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

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

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

It seems that Ember checks the returned data values ​​on order._data , and since there is no difference, this does not cause any recalculation of the properties.

I tried different workarounds but couldn't find something that works reliably.

Unsurprisingly, there is no reliable way to access the returned data and manually set voucherValue from the returned data. Even if the returned data sets a value for voucherValue , this is true:

 order.save().then(function (savedOrder) { savedOrder.get('voucherValue') === 0; //true }).catch(function (error) { order.set('voucherValue', 0); }); 

However, if another voucher is entered after an invalid voucher, and voucherValue is different (for example, 450 ), everything works as expected.

Is this a bug in EmberData? Is there a way around knowledge. I am open to suggestions and am ready to try something before I try and reengineer how this whole system will be implemented.

+6
source share
2 answers

This bit of your code seems to be a problem:

 order.save().then(function (savedOrder) { savedOrder.get('voucherValue') === 0; //true }).catch(function (error) { order.set('voucherValue', 0); }); 

The catch function is a proxy for promise. However, promises usually expect the second parameter to be passed to the then function, for example:

 order.save().then(function (savedOrder) { savedOrder.get('voucherValue') === 0; //true }, function (error) { order.set('voucherValue', 0); }); 

This second function represents the reject path of the resolve/reject pair used by Promise . See: http://emberjs.com/api/data/classes/DS.Model.html#method_save

0
source

If the server should install model.voucherValue , then you need to stop installing it on the client. Installing it on the client may interfere with the recording state, while Ember Data tries to materialize it in the adapter.

I think this can be solved by slightly changing the property definition:

 discount: function () { if (this.get('model.errors.length') > 0) { return 0; } var discount = this.get('model.voucherValue'); // some calculation return discount; }.property('model.voucherValue', 'model.errors.length') 

Or something similar, depending on your use case.

0
source

Source: https://habr.com/ru/post/988190/


All Articles