How Model.typeKey is computed?


#1

Hi all,

I encountered a strange issue with the ember-data framework today. My application namespace is METAMORE, I defined a Model called ‘Strata’. I override the function extractSingle in the ApplicatoinSerializer. The error below happened when the extractSingle was called.

strata.index No model was found for ‘stratum’ Error: No model was found for ‘stratum

It is because the framework try to find the model type with the typekey of the my model METAMORE.Strata. However, the METAMORE.Strata.typeKey returns ‘stratum’.

My ember-data version is 1.0.0-beta.9, My Model is defined as follows:

METAMORE.Model = METAMORE.OrganizationIdModel.extend({
    createdOn: DS.attr('string'),
    lastUpdatedOn:  DS.attr('string'),
    //isChecked is used only by the client side for checkboxes, server can never see it.
    isChecked:false
});

METAMORE.Strata = METAMORE.Model.extend({
    endpoint : DS.attr('string'),
    username: DS.attr('string'),
    password: DS.attr('string'),
    daysToLoad: DS.attr('string'),
    defaultDuration: DS.attr('string')
});

It had been working fine before I upgraded the ember-data to 0.9. It was 0.7 before.

Does anyone know what might be the cause? How the typeKey of a model type is computed? Why ‘a’ becomes ‘um’? Thanks.


#2

Ember data uses something called Ember Inflector for pluralizing and singularizing keys. I’m going to make an assumption that there was an update in Ember Inflector that caused the change. If you look here you’ll see the rule that singularizes a word ending in “ta” to “tum”.

This Stack Overflow question answers how you can override the pluralization of certain words, if need be. (Make sure to see the answer on the bottom as the original answer applies to the pre-1.0 beta version).


#3

It’s strange that your typeKey is pluralized. In normal case Ember generates camelCased and singularized typeKey.

Ember sets typeKey for model class in store.modelFor, and it uses _normalizeTypeKey method to calculate typeKey. The logic is simple:

_normalizeTypeKey: function(key) {
  return camelize(singularize(key));
}

I don’t know how to solve your problem. But by reading the source I think there is a workaround to solve your issue. You can manually set typeKey for your model class and Ember will respect that.

METAMORE.Strata.typeKey = 'strata';

But for long term it’s necessary to figure out the reason so your other models won’t have same issue.

Wish it helps.


#4

You should absolutely not be setting the typeKey of a class. Leave it to modelFor.

This sounds like maybe you are referencing the class directly instead of via the container and modelFor, with MODEL_FACTORY_INJECTIONS enabled.

More information or a JSBin would maybe help resolve this.


#5

Thanks Spencer. Your answer is the right one I am looking for. Adding the following lines resolved my issue.

Ember.Inflector.inflector.uncountable('Strata');
Ember.Inflector.inflector.uncountable('Terms');

The second line is for another model which doesn’t work with beta.9 either. It works fine with beta.7 with the following function overriding.

METAMORE.AssetContainerSerializer = METAMORE.ApplicationSerializer.extend({
    typeForRoot: function(root){
        if(root === 'Terms')
            return "Terms";
        else
            return this._super(root);
    }
});

Where Terms is a child model ‘belongsTo’ of the AssetContainer model.