miragejs / discuss

Ask questions, get help, and share what you've built with Mirage
MIT License
2 stars 0 forks source link

server.create() fails for models which are named as a plural #17

Open lougreenwood opened 5 years ago

lougreenwood commented 5 years ago

Boilerplate example: https://github.com/lougreenwood/ember-cli-mirage-boilerplate

When an ember-data model is named as plural, for example settings, calling server.create('settings') or server.createList('settings') fails with the error:

Promise rejected during "server.create singular model fails": Mirage: You called server.create('settings') but no model or factory was found. Make sure you're passing in the singularized version of the model or factory name.

Instead, if we use server.create('setting'), this works, but this is not the actual model name.

Examples can be seen here: Model: https://github.com/lougreenwood/ember-cli-mirage-boilerplate/blob/master/app/models/settings.js

Mirage Factory: https://github.com/lougreenwood/ember-cli-mirage-boilerplate/blob/master/mirage/factories/settings.js

Example failure test: https://github.com/lougreenwood/ember-cli-mirage-boilerplate/blob/master/tests/integration/components/settings-test.js

Expected behaviour

Even if a model name is actually plural, server.create() should not require an incorrect, singularized version of the model name to be passed to it.

samselikoff commented 5 years ago

Have you seen the guide on customizing the inflector? https://www.ember-cli-mirage.com/docs/advanced/customizing-the-inflector

I believe all you'd need to do in your case is something like

// app/initializers/custom-inflector-rules.js
import Inflector from 'ember-inflector';

export function initialize(/* application */) {
  const inflector = Inflector.inflector;

  // Tell the inflector that the plural of "settings" is "settings"
  inflector.uncountable('settings');
}

export default {
  name: 'custom-inflector-rules',
  initialize
};
lougreenwood commented 5 years ago

Thanks @samselikoff I'll take a look at this, however, I have a few questions about this:

samselikoff commented 5 years ago

Yep, I'd definitely agree it's heavy-handed if it were just us recommending it but it's part of the Ember Data docs: https://guides.emberjs.com/release/models/customizing-adapters/#toc_pluralization-customization

Basically the idea is, Ember Data relies on the inflector as part of its conventions, and Ember Data expects singular model names. A post.js model will generate URLs like GET /posts, POST /posts, GET /posts/1 and so on. And customizing the inflector is the way to do this.

I can help you find an alternative solution but first question would be, why not follow the docs on inflector customization? I would suggest doing this unless there's a good reason not to, if only because you will eventually run into surprising behavior within Ember Data's APIs if you don't.

samselikoff commented 4 years ago

FYI: Transferred this to our Discuss repo, our new home for more open-ended conversations about Mirage!

If things become more concrete + actionable we can create a tracking issue in the main repo.

kboucher commented 3 years ago

Um, so maybe a silly question, but how should we handle this for an integration test? The issue we are having is that the custom-inflector-rules.js initializer does not run during an integration test. Are we making a fundamental mistake by interacting with the Mirage server in integration tests?

samselikoff commented 3 years ago

There's some info in the docs about integration tests: https://www.ember-cli-mirage.com/docs/testing/integration-and-unit-tests

You can absolutely use Mirage there. In this case, you could just import and run your initializer alongside setupMirage. I might make a separate function that does both (setupMirageForIntegration or something like that) just so you don't forget!