How to deal with possible duplicates in an Ember store? - ember.js

My Ember apps retrieves model objects from an API that can contain duplicates on successive calls.
I want to store my objects like this:
myController.store.createRecord('myModel', myModelObject).save()
Unfortunately, when a duplicate occurs, I get the following error in the console:
Error: Assertion Failed: The id XXX has already been used with another record of type MyApp.MyModel.
(fonction anonyme)ember.js:3866
I couldn't figure a way to recover gracefully from that error. I tried:
myController.store.createRecord('myModel', myModelObject).save().catch(myFailureCallback)
but the failure callback doesn't get called and the error is the same.

You could check to see if the record is already loaded into the store
http://emberjs.com/api/data/classes/DS.Store.html#method_recordIsLoaded
store.recordIsLoaded('myModel', myModelObject.get('id'))

Related

What happens when ember's model hook's request fails

I have a typical scenario.
My model hook for Route-1 looks something like this.
model() {
return Ember.RSVP.hash({
posts: this.store.findAll('post'),
authors: this.store.findAll('author')
});
}
If I'm on Route-2 and navigate to Route-1 it will call the model hook.
And if I already have data on my store, both the findAll requests are resolved, triggering RSVP.hash to resolve.
But if the request fails, I'm getting undefined error in my console (chrome).(twice for each of findAll)
My error tracking system reports it as Unhandled promise error detected
the stack shows no relevant info either
defaultDispatch # ember.debug.js:18008
dispatchError # ember.debug.js:17987
onerrorDefault # ember.debug.js:31634
trigger # ember.debug.js:58713
(anonymous) # ember.debug.js:59614
invokeWithOnError # ember.debug.js:346
flush # ember.debug.js:405
flush # ember.debug.js:529
end # ember.debug.js:599
(anonymous) # ember.debug.js:1165
I am not able to figure out what is causing the error to be thrown because the promise findAll already got resolved. And ember tells me I have not handled the promise!
I tried putting catch/reject codes everywher but it never gets called. Because of course the promise was already resolved. So, it can not be rejected.
Then where is this error coming from!! I have no clue. There is no error till the adapter returns.
The only thing I could find was in my serializer normalizeFindAllResponse was not invoked whenever such failures happened.
Any help is greatly appreciated. Thanks!
I somehow solved this issue.
Before, in my adapter I was rejecting the promise with Promis' reason object.
Now, in case of error response, I am rather sending an object containing errors array, rather then failure reason object.
So, the object will get passed as payload to my normalizeFindAllResponse in serializer. There I check for existance of errors array in our payload parameter.
If there is such object then just return an empty object with data attribute set to empty array.
Note: Got the idea from here.

Getting error when trying to delete record from hasMany collection

ember-data#2.5.3
ember#2.4.3
I am getting the following error "Cannot set property 'jqXHR' of undefined" when attempting to delete a record. The item has already been deleted via model.deleteRecord, I am now trying to persist it to the server. I have tried this with both item.save() and item.destroyRecord() any ideas of what this message means? The request never actually reaches the server.
This is caused by a bug in v0.1.0 of the ember-data-has-many-query addon, which was fixed in v0.1.1. Updating to the latest version should fix it.

Ember.js 2.x: Handling "Could not find component..." error thrown by component helper

I have need in my Ember.js app to render a different component based on some piece of data. I've set this up via the component helper, like so:
<article class='awesome-article'>
{{component article-type}}
</article>
This works all fine and well, though naturally, if the article-type attribute doesn't match the name of any component in the application (which may happen due to fat-fingering), it gives us a nice, explicit error message:
Uncaught Error: Assertion Failed: HTMLBars error: Could not find component named "nonexistent-component" (no component or template with that name was found)
This is also great, but now I've got a smaller problem: I'd like to gracefully handle this error in the application, but I can't seem to figure out how to either catch or prevent this error. I've tried adding an error action to the parent component, but it skips right past it.
How can I go about handling this? This is probably one of those "missing something obvious" things, but my Google-fu has failed me this time.
You could create a handlebars helper that looks up if the component is registered in the container and based on this information you can display it or display some placeholder component.
If you are on at least Ember 2.3 you can use the public API they added: http://emberjs.com/api/classes/RegistryProxyMixin.html#method_hasRegistration

Getting "Error: Assertion Failed: calling set on destroyed object" when trying to rollback a deletion

I am looking into how to show proper deletion error message in ember when there is an error coming back from the server. I looked at this topic and followed its suggestion:
Ember Data delete fails, how to rollback
My code is just like it, I return a 400 and my catch fires and logs, but nothing happens, when I pause it in the debugger though and try to rollback, I get Error: Assertion Failed: calling set on destroyed object
So A) I cannot rollback B) the error is eaten normally.
Here is my code
visitor.destroyRecord().then(function() {
console.log('SUCCESS');
}).catch(function(response) {
console.log('failed to remove', response);
visitor.rollback();
});
In case it's relevant, my model does have multiple relationships. What am I doing wrong? Ember-data version is 1.0.0.8 beta (previous one from the release a few days ago).
Thanks in advance.
EDIT
I discovered now that the record actually is restored currently inside the cache according to ember inspector, but the object will not reappear in the rendering of the visitors. I need some way to force it to reload into the template...
After destroyRecord, the record is gone and the deletion cannot be rolled back. The catch clause will just catch a server error. If you want the record back, and think it's still on the server, you'll have to reload it.
See the following comment on deleteRecord from the Ember Data source:
Marks the record as deleted but does not save it. You must call
`save` afterwards if you want to persist it. You might use this
method if you want to allow the user to still `rollback()` a
delete after it was made.
This implies that a rollback after save is not possible. There is also no sign anywhere I can see in the Ember Data code for somehow reverting a record deletion when the DELETE request fails.
In theory you might be able to muck with the isDeleted flag, or override various internal hooks, but I'd recommend against that unless you really know how things work.
Try reloading the model after the rollback. It will reload from the server but it was the only way around this that I could find.
visitor.destroyRecord().then(function() {
console.log('SUCCESS');
}).catch(function(response) {
console.log('failed to remove', response);
visitor.rollback();
visitor.reload().then(function(vis)
{
console.log('visitor.reload :: ' + JSON.stringify(vis));
});
});
Hope that helps.

the persisting records instructions in the guide don't work for me

I'm trying to use the instructions find here:
http://emberjs.com/guides/models/persisting-records/
My server receives the json well and creates a record which it then returns properly, but my onSuccess function doesn't get anything usable as a response. It gets this strange object which if I try to pass onto the next route like the instructions say, it errors out saying this:
Uncaught Error: Assertion Failed: The value that #each loops over must be an Array. You passed '' (wrapped in (generated articles.view controller))
Here is my code:
https://github.com/mgenev/Full-Stack-JS-Boilerplate/blob/master/public/ember/controllers/articles_controller.js
I appreciate any help.
It looks like your transitionToArticle function requires an argument but you're not passing in anything when you're calling it:
article.save().then(transitionToArticle).catch(failure);