Skip to content
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

How to re-create a deleted record (same ID) #5014

Closed
imhuytq opened this issue Jun 17, 2017 · 22 comments
Closed

How to re-create a deleted record (same ID) #5014

imhuytq opened this issue Jun 17, 2017 · 22 comments

Comments

@imhuytq
Copy link

imhuytq commented Jun 17, 2017

I have a record with ID is sample_account. I have deleted it by using this code:

record.destroyRecord();

But when I re-create a new record with the same ID (sample_account), I received this error:

Assertion Failed: The id sample_account has already been used with another record for modelClass 'account'.

How can I re-create a deleted record with the same ID?

@olivierchatry
Copy link

I got the same issue while working on my undo - redo stack. The only way I found was :

this.store._removeFromIdMap(this.model._internalModel)

Note that you need to do that after destroyRecord. Also, it uses _ function, which means that it might not work from one version to the other.

I also think destroyed record should be removed from this map automatically.

@sly7-7
Copy link
Contributor

sly7-7 commented Jun 26, 2017

I wonder if calling unloadRecord() would do the job here.

@imhuytq
Copy link
Author

imhuytq commented Jun 26, 2017

Thank @sly7-7 , use record.unloadRecord(); and it worked.
@olivierchatry I recommend you to use record.unloadRecord();.

@imhuytq imhuytq closed this as completed Jun 26, 2017
@olivierchatry
Copy link

olivierchatry commented Jun 26, 2017 via email

@anlumo
Copy link

anlumo commented Jan 7, 2018

unloadRecord doesn't trigger deleteRecord in the adapter and you can't both delete and unload the same record. Thus, I wouldn't consider this fixed, since the only solution is to access a private function and a private property.

@anlumo
Copy link

anlumo commented Jan 9, 2018

I also noticed just now that ember-data wreaks havoc with relationships in this situation, because there's a cache deep down in store.recordArrayManager._relationshipsPayloads._cache that is not cleaned up when a record is deleted. This causes some relationships to be formed automatically that are not in the model (and it even ignores inverse relationships at that).

EDIT: just found the function store._internalModelDestroyed that does clean up the relationships as well. This is supposed to be called from internalmodel.destroy, apparently ember-data never destroys the internal models?

@mrloop
Copy link
Contributor

mrloop commented Jun 5, 2018

This is working for me

myRecord.destroyRecord().then( rec => rec.unloadRecord());

@JCBarry
Copy link

JCBarry commented Jun 26, 2018

I am running into this as well. Creating a new record with a specific ID (using createRecord) before saving, calling deleteRecord removes the record from the store. However, if I try to re-create the record (createRecord) using the same ID -- I will receive this exception.

Since the record isn't saved at the data source, I don't think destroyRecord makes sense -- any reason that deleteRecord doesn't release the ID constraint from the data store?

@dennismende
Copy link

Hi, could some open the ticket again please?

I have the same problem with deleteRecord together with the id exception.

@anlumo
Copy link

anlumo commented Nov 7, 2018

It would be great to have this fixed. The workaround I posted above doesn't work with 3.5 any more, I'm currently looking for a new one.

I wonder how many projects are constantly leaking internalModels without realizing it.

EDIT: Apparently this issue is tracked in #5006.

@olivierchatry
Copy link

Same here, seems like since 3.5, my undo redo stack is broken. ( deleteRecord / createRecord with same id give me an error message about using the same id ).

@andrewcallahan
Copy link

I'm on Ember 3.8 and this is still an issue, and this is still the only way that works:

I got the same issue while working on my undo - redo stack. The only way I found was :

this.store._removeFromIdMap(this.model._internalModel)

Note that you need to do that after destroyRecord. Also, it uses ___ function, which means that it might not work from one version to the other.

I also think destroyed record should be removed from this map automatically.

@olivierchatry
Copy link

I think this needs to be re-open, as it is still not working.

@olivierchatry
Copy link

Still not working as 3.9.2

@runspired
Copy link
Contributor

You have to unload the record after persisting the deletion

@olivierchatry
Copy link

Yes, that is what I'm doing.

        return model.save().then(
          () => model.unloadRecord()
        )

@runspired
Copy link
Contributor

@olivierchatry with the delete call?

record.deleteRecord();
record.save().then(_ => record.unloadRecord());

@olivierchatry
Copy link

olivierchatry commented May 8, 2019

This is an "undo" action. The delete is done before saving. So yes, it is done.

In this code, undo / redo are called, then save. So deleteRecord() is called ( also the whole code is working as expected on 3.4.x, started to fails in 3.5.x

  redo() {
    this._createData()
  },
  undo() {
    const model = this.getModel()
    this._saveData()
    this.onDestroyModel(model)
    model.deleteRecord()
  },
  save() {
    const model = this._modelId ? this.getModel() : this.model
    if (model) {
      if (model.get('isDeleted')) {
        return model.save().then(
          () => model.unloadRecord()
        )
      } else if (model.get('isDestroyed') === false ) {
        return model.save().then(
          () => this._modelId = model.get('id')
        )
      }
    }
  }

@validkeys
Copy link

Can confirm this is also an issue on ember-data 3.10.0

@anlumo
Copy link

anlumo commented Jun 20, 2019

Well, there's an undocumented requirement that causes this issue. Whether it's an actual code bug or a documentation issue is up for interpretation.

You have to actively push all changes you get in an adapter back into the store from that adapter, otherwise the relationships of a changed record (unlike the attributes) will be in an unsaved state. This causes leaked objects all over the place, including the ids of deleted records.

@olivierchatry
Copy link

olivierchatry commented Jul 4, 2019

So being looking at the code, and from what I can see, it seems destroy is never called.
The function unloadRecord schedule a call on the destroy loop :

      if (this._scheduledDestroy === null) {
        this._scheduledDestroy = Ember.run.backburner.schedule('destroy', this, '_checkForOrphanedInternalModels');
      }

_scheduledDestroy is used to test if someone directly call createRecord with the same id right after, and if user do that, emberdata call destroySync, which actually destroy and remove the model from the internal model cache.

If not, then _checkForOrphanedInternalModels is called, which only does :

      this._isDematerializing = false;
      this._scheduledDestroy = null;

      if (this.isDestroyed) {
        return;
      }

My guess is that normally destroy should be called right after _checkForOrphanedInternalModels

Was wondering if maybe somethiing was missing after the

      if (this.isDestroyed) {
        return;
      }

like maybe a call to destroy?

@erichaus
Copy link

erichaus commented Jul 16, 2021

did anyone find a working solution for this? In ember-data 3.20.X there is no store._removeFromIdMap

I'm having the exact same problem where I cannot seem to properly remove a record that was previously created/destroyed with same id.

The record is created/deleted through a websocket update, and the addition seems to work fine using store.pushPayload(), but calling record.deleteRecord() does not remove it from relationship arrays, and leads to error on next create. Additionally if I call record.unloadRecord() after the deleteRecord(), I get a strange fastboot error

Failed to execute 'querySelector' on 'Document': '#shoebox-model-test3::test1' is not a valid selector.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests