miragejs/ember-cli-mirage

Change ember data model attributes & relationships to camel case in Mirage models

cristinawithout opened this issue · 4 comments

I'm looking for a solution to be able to add mirage to an existing application that has dozens of Ember Data models. It works perfectly fine on GET requests, but for POST & PATCH requests, it returns a 500 error when there is a relationship because the models have snake_cased_relationships.

Additional details are on the miragejs issue miragejs/miragejs#890

The short version is that miragejs forces camelize on the relationshipName but the Mirage model has snake cased name.
Code that does that is here:
https://github.com/miragejs/miragejs/blob/b965b8a058523dac0d6ab4792826887154e25368/lib/route-handlers/base.js#L76

Everything about Ember Data and Mirage works just fine with snake case except for this.

Since Mirage expects camel case, is there a way to have ember-cli-mirage create Mirage models with camel cased relationships/attributes when the Ember Data models are not camel case? Or a way I can override the modelClass.associationFor() method?

Adding this to scenarios/default.js makes it work, but it's really ugly. I'd greatly prefer a cleaner solution that also doesn't involve redefining over 2 dozen Ember Data models as Mirage models.

 Object.keys(server.schema).forEach(key => {
    let modelName = server.schema[key].camelizedModelName;
    if (modelName) {
      let model = server.schema.modelClassFor(modelName);
      if (model) {
        model.associationFor = function(key) {
          let association = this.associations[key];
          if (!association) {
            key = underscore(key);
            association = this.associations[key];
          }
          return association;
        };
      }
    }
  });

I found the server configuration docs. https://www.ember-cli-mirage.com/docs/advanced/server-configuration

If I copy discoverEmberDataModels from add/ember-data.js and change lines 79 & 81 to use attr[camelize(name)], it all works.

attrs[name] = belongsTo(r.type, r.options);

attrs[name] = hasMany(r.type, r.options);

I'd rather not have to copy & modify code from the addon, but this looks like the best option I have unless ember-cli-mirage can add camelize() to the Mirage model attributes.

import { createServer, Model, belongsTo, hasMany } from 'ember-cli-mirage';
import { getDsModels } from 'ember-cli-mirage/ember-data';
import { camelize } from '@ember/string';

function customDiscoverEmberDataModels() {
  let emberDataModels = getDsModels();
  let Models = {};

  Object.keys(emberDataModels).forEach(modelName => {
    let model = emberDataModels[modelName];
    let attrs = {};

    model.eachRelationship((name, r) => {
      if (r.kind === 'belongsTo') {
        attrs[camelize(name)] = belongsTo(r.type, r.options);
      } else if (r.kind === 'hasMany') {
        attrs[camelize(name)] = hasMany(r.type, r.options);
      }
    });

    Models[modelName] = Model.extend(attrs);
  });

  return Models;
}

export function makeServer(config) {
  let finalConfig = {
    ...config,
    models: { ...customDiscoverEmberDataModels(), ...config.models },
    routes,
  };

  return createServer(finalConfig);
}


function routes() {
...
}

If changing those two lines fixes the problem, please submit a PR with that change.Possibly create another model in the dummy app to test with that has the snake case demonstrating that it works

Thanks. I likely won't have the bandwidth to do a PR for quite awhile, but if anyone else has similar needs and would like to, feel free.