-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Saving a new record that returns a existing record now fails. #4972
Comments
I am thinking this being an edge case I will just break into a custom ajax request. |
Similar problem here, we were having this trouble too, in our case our ember application has a bank account model and the user was able to add and delete accounts, but in our API if an account was deleted by the user the backend handled to only deactivate the record in the database. Later if the user creates again the same account, the API activates the record in the database and returns it with 201 status code and we're getting the same error, then we solved it, unloading the record from the store inside the destroyRecord function. It's worth mentioning that we haven't this problem with ember data 2.8.1 and it starts to fail when we did upgrade to 2.13.1 Here a chunk of our controller code
For us the trick was to unload the duplicated record that was already loaded into the store. |
I'm reopening this because I think it should be discussed more |
I'm seeing this With our app the server will send push updates to the client. I suspect I'm seeing this when the pushed version of the data gets sent back before the |
If anyone is interested here is my workaround. The adapter and serializer api are quite well thought out. 👍 |
@arenoir Why is the |
Didn't work without it. Moving the promise to the next run loop ensures all the removal promises finish before loading the payload. |
@rondale-sc ideally |
@arenoir Ah, well this appears to have resolved my issue. Seems a little janky, but feels like as good a place as any. Thank you for working on this and sharing back your solution! 🍻 I think this exposes (in my app anyway) some weird bugs that were previously invisible. Good, but a bit frustrating. |
@arenoir Which ember-data version your fix works on - I am on 2.13.2 and even after unloading I still get the same error. |
Seems like in e-d@2.13 store.unloadRecord does not remove id from internal-model-map
|
I am not sure if this is relevant. But I suspect the jQuery version might be the culprit. The same piece of code did not work for me. But it worked for my friend. Here are my versions:
And here is my friend's version:
As you can see for yourself, only the jQuery version is different. |
I have the same problem here! I had to use the fix from @xomaczar. Will there be a fix in ember-data or is it an issue with our code? |
I've just started learning Ember. This question may sound unprofessional so bear with me. |
@akajulie I believe its existing model object. If I am not wrong 😛 |
@dhilipsiva It worked :) |
#5126 merged, and I back-ported to beta/release .. I'll release by tomorrow. Sorry for the delay. |
Can this be closed then? |
Closing since this seems resolved. Please reopen if this is still an issue. |
I have same issue and fix with Do you have any forecast to correct this error? Has anyone ever debugged to find the bug? |
We are having a similar issue here. In the past |
After upgrading to 2.16 I stumbled upon this in slightly different use case where a websocket notification with payload comes in quicker then response for model.save(). EDIT: My error is
I guess it's something different? |
Just ran into this scenario. I chose to export default JSONSerializer.extend({
normalizeCreateRecordResponse(store, primaryModelClass, payload, id, requestType) {
let { modelName } = primaryModelClass;
id = this.extractId(primaryModelClass, payload);
if (store.hasRecordForId(modelName, id)) {
let record = store.peekRecord(modelName, id);
store.unloadRecord(record);
}
return this._super(store, primaryModelClass, payload, id, requestType);
}
}); |
We are seeing a similar issue in our application. We are using the latest stable ember-data (2.17.0). I am going to follow up in the ember data slack to determine how we can collaborate getting this fixed as it breaks many things in our app. |
@efx did you get any feedback from the folks in the ember data channel? |
@jamesdixon I did not ( original question ). I have searched through the repo and found many different |
fyi I have this same issue that breaks after |
@bmac @hjdivad the solution from @villander resolved the issue but seems like a hack, any feedback on this?
the block of code:
|
I'm seeing this on 2.18.0 in development but not production build.
|
fyi it did work prior to 2.12.X but for now this line let us move along |
@runspired can you elaborate? First time hearing about client-id solution, why wouldn't ember-data be handling this as it did pre 2.13.X
|
@erichonkanen this didn’t work pre 2.13 either, we simply didn’t assert it. The result was that you’d end up with two separate records in separate states. #1829 has details of how to solve this issue long term. It can be fully implemented in userland, and primarily has not been implemented in ED because the answer is API specific. |
@runspired something happened in 2.13.X then, maybe it was creating duplicate records but functionally still working? when we were on 2.12.X our app worked fine but once we moved past it I had to implement that _internalRecord hack otherwise it doesn't work.. have talked to other ppl that had same issue at emberconf and consensus was "something broke after 2.12" I'll take a look at how to implement the client-id in the mean time thanks! |
I like @skaterdav85 suggestion with serializer, but it has an issue: unloadRecord is async and returns promise so in case server returns the same ID you have to wait for unloadRecord finished export default JSONSerializer.extend({
normalizeCreateRecordResponse(store, primaryModelClass, payload, id, requestType) {
let { modelName } = primaryModelClass;
id = this.extractId(primaryModelClass, payload);
if (store.hasRecordForId(modelName, id)) {
let record = store.peekRecord(modelName, id);
store.unloadRecord(record).then(() => {
return this._super(store, primaryModelClass, payload, id, requestType);
});
} else {
return this._super(store, primaryModelClass, payload, id, requestType);
}
}
}); |
@iriand, AFAIK, you can't run super asynchronously. |
@lolmaus I have found both codes not working properly. Found that ID is not extracted, so the record wasn't unloaded right. Also, after a deeper review found that unoadRecord doesn't return promise. |
@skaterdav85 looking to use a solution like you posted above, using the serializer to unload the local model from the store if the id already exists, however this doesn't seem to work in a situation where the response for //POST /foo
{
"foo": {
"id": 999,
"name": "..."
},
"bar": {
"id": 123,
"name": "...",
"foos": [
{"id": 777, "name": "..."},
{"id": 888, "name": "..."},
{"id": 999, "name": "..."}
]
}
} (where Here, it appears that the Any ideas where to override/extend ember-data's logic so this type of response can be allowed, or at least silently swallow the "XXX id is already used" exception and treat it as a successful request? |
@billdami I am having the same issue as you, but with JSONAPI. Given a request to create a "child" record. the response is like.
notice that the child is in the included records, and also in data. in older ember-data versions the record ends up in the store twice, in newer versions it raises an error. |
I just wrestled with a similar issue on Ember Data 3.17 with the new identifiers API @runspired landed above. On 3.17 it seems like if you create a record through However, if to create records, you do something like below, this does not work so well.
I set out to make it so when a record is deleted, it's as though it never existed and here is what I came up with. model.destroyRecord().then(() => {
model._internalModel.dematerializeRecord();
model._internalModel.destroySync();
// something happens in the runloop after this which will revive the identifier in the identifierCache if you don't wait for the next loop
Ember.run.next(() => {
model.get('store').identifierCache.forgetRecordIdentifier(model._internalModel.identifier);
}); This seems to make things work as expected. Very early stages of figuring this out so there may be more problems lurking but thought I'd post it up here to see if anyone has done anything similar or whether this approach creates any major problems I haven't discovered yet. |
@g-cassie feel free to reach out on discord, I suspect the issue is much simpler to resolve than this and can be resolved without using any of these private APIs. Also I think you are hitting the issue where |
Just a quick update for anyone who stumbles across this. There is a known issue where
In our particular case, we hit on an unrelated bug where due to our model having two async relationships, unloadRecord does not successfully remove the record from ember-data. This causes an error when we create a new record with the same ID. Once this bug is fixed, the destroy/unload combo should do the trick. Until then, my hack above does seem to work. Big thanks to @runspired for helping get to the bottom of this. |
@g-cassie is this bug fixed and in what version? |
@g-cassie running unloadRecord() did help prevent an issue where recreating a record using same natural key would throw upon record.destroyRecord() with "in state root.deleted.saved" Still seeing a different issue where recreating a record that exists in AnotherRecord.hasMany() will duplicate and result in two of the same record appearing (one being stale/old?) ember-data 3.20.5 For now I'm just adding filtering when I display that hasMany in a template |
So this is certainly an edge case but in the past was a nice feature.
I have a model
address
quite simple 4 attributeslineOne
,city
,state
andzip
. When creating a new address the server checks to see if a duplicate exists and if so returns the duplicate with the 201 created http code.This all works fine unless the duplicate is already loaded. If it is loaded I get the following error.
In versions of ember data 2.11 and prior this worked without issue.
The text was updated successfully, but these errors were encountered: