简体   繁体   中英

Ember destroyRecord (or deleteRecord then save) using ember-cli-mirage failing

What I'm trying to do is integrate ember-cli-mirage into this todo app, https://github.com/ember-cli/ember-cli-todos . This app uses Ember 2.0 or greater. The setup:

  1. Clone the todo app, then cd into the app directory.
  2. shell> npm install
  3. shell> bower install
  4. shell> ember serve

I verified that the app is working as advertised (except for one minor thing that is not relevant here). I can create, update and delete a todo item. The todo app uses ember-data-fixture-adapter/FIXTURES to seed the app with data.

The steps I did to integrate ember-cli-mirage are:

  1. Comment out the Todo.reopenClass block in app/models/todo.js (the code that creates the FIXTURES/seed data).
  2. Removed the app/adapters directory (which only contains one file, application.js (which only contains one line, "export { default } from 'ember-data-fixture-adapter';")). I'm fairly certain this whole directory is only of use to the FIXTURES setup.
  3. shell> ember install ember-cli-mirage
  4. Setup the ember-cli-mirage parts (app/mirage/{config.js,factories/post.js,scenarios/default.js}) per instructions here http://www.ember-cli-mirage.com/docs/v0.1.x/working-with-json-api/ .

I'll post the code for app/mirage/{config.js,factories/post.js,scenarios/default.js} if anybody needs to see it but it's basically just a copy of the instructions in the ember-cli-mirage page (with the "user" model name replaced with "post").

I restarted the ember server. Everything works fine except for the removal of a todo item. Record removal is done by pressing the "x" button that will appear when you move your pointer to the right of a todo item. I found out that it fails in the save() part of the record removal. The code for the record removal (using the "x" button interface) resides in app/components/todo-item/component.js and it looks like this:

removeTodo() {
  var todo = this.get('todo');

  todo.deleteRecord();
  todo.save();
}

When I try to delete a todo item, the browser console prints "Successful request: DELETE /todos/n" ("n" being the todo id), then it prints a cryptic error message along with the stack trace.

I commented out the "todo.save();" line above. When I removed a todo item, removal still fails but on the console, there's no error message anymore after the "Successful request: DELETE /todos/n" message.

So I changed the removeTodo code above in an attempt to make the error messages clearer. I changed it to this:

todo.save().then(function() {
    console.log('Save OK.');
  }).catch((err) => {
    console.log('Save failed.');
    console.log(err.message);
});

I've tried various changes to things here and there but the error message that consistently appears is:

Assertion Failed: An adapter cannot assign a new id to a record that already has an id. had id: 3 and you tried to update it with undefined. This likely happened because your server returned data in response to a find or update that had a different id than the one you sent.

I saw an error message that had something like "normalizeserializer..." text on it but I forgot to copy the whole message.

I added an adapter:

shell> ember g adapter application

// app/adapters/application.js
import DS from 'ember-data';

export default DS.JSONAPIAdapter.extend({
});

But this didn't fix it.

BTW, a todo item creation, which also calls save on a todo item, works. The code resides in app/components/todos-route/component.js:

createTodo() {
  const store = this.get('store');

  // Get the todo title set by the "New Todo" text field
  var title = this.get('newTitle');

  if (title && !title.trim()) {
    this.set('newTitle', '');
    return;
  }

  // Create the new Todo model
  var todo = store.createRecord('todo', {
    title: title
  });

  // Clear the "New Todo" text field
  this.set('newTitle', '');

  // Save the new model
  todo.save();
}

What does your Mirage mock for DELETE to /todos/:id look like? It looks like you're responding to the DELETE request with a JSON payload that contains an id , which is causing problems.

Instead you could try something that returns an empty response body, like

this.del('/todos/:id', (db, request) => {
  let id = request.params.id;
  db.todos.remove(id);

  return new Mirage.Response(204, {}, {});
});

(This code is untested but hopefully you get the idea).

Another small point, there's a destroyRecord method on models which essentially does deleteRecord and save all at once.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM