Ember.js: depending on "model.constructor.modelName" sets model.constructor to undefined

Created on 3 Aug 2016  路  13Comments  路  Source: emberjs/ember.js

In my app I use an computed property to state how many steps are left to do for creating the models. This depends on how many steps are already done and which kind of model it is currently creating. (We create different kind of coworkers)

In Ember 2.5 it did work. After upgrading or slightly after (not quite sure) it stopped working.

this is my cp

numberOfSubSteps: Ember.computed('model.constructor.modelName', function() {
    let valueBasedOnModel = 4;
    switch(this.get('model.constructor.modelName')) {
      case 'kurzfristig':
        valueBasedOnModel = 5;
        break;
      case 'geringfugig':
        valueBasedOnModel = 6;
        break;
...
    }
    return valueBasedOnModel;
  }),

I found the exact line where it changes the constructor. (It defines a new property which somehow is then returning undefined.)
https://github.com/emberjs/ember.js/blob/master/packages/ember-metal/lib/watch_key.js#L81

This is the callstack when it happens
screenshot 2016-08-03 um 17 05 44

might be somewhat related to #9387

Bug Has Reproduction Inactive Needs Submitter Response

Most helpful comment

This works:

import DS from 'ember-data';
import Ember from 'ember';

export default {
  name: 'model-Name',
  initialize() {
    DS.Model.reopen({
      modelName: Ember.computed(function() {
        return this.get('constructor.modelName');
      })
    });
  }
};

Is this a proper workaround?

All 13 comments

Hello, @spruce.

Can you please reproduce the problem in an ember-twiddle, please?

I tried but couldn't.

Thank you!

I finally got two different reproductions. The first one by @cibernox can be found here and it raises the error as soon as the application renders.

The other example is a bit more convoluted but shows that a computed property can work if the model does not change. Instructions are found in the twiddle itself.

To clarify, the application fails as soon as the app renders because I'm passing the post model after it has been destroyed by observing his constructor to a component, and components perform an assertion to deperecate didInitAttrs that calls .toString() on that property.

The default toString attempts to call this.constructor.super, which now raises an error.

Another note. I understand that observing the constructor does seem like a weird pattern, given that the constructor can't change, so I'd accept as reasonable bugfix to add an assertion in development to instruct users to not do that.

Also have problem with this.constructor undefined in didInitAttrs depreaction check

but in my case i only pass model.constructor.modelName as argument to component

@Sinled Using that in a template is implicitly creating an observer to watch for changes, so it's the same issue.

I've recreated this too in a current project that upgraded, and it was the same cause. I amended the computed property to use the modelName, but not actually listen for the property (as, as you said, it doesn't actually change) and this seems to resolve it for me.

This just happened to me after upgrading to ember 2.10.0

replaced:

computed.oneWay('owner.constructor.modelName')

by:

computed('owner', function() {
  return this.get('owner.constructor.modelName');
})

and it's working now, thanks for the tips @cibernox

how did u resolve it @Sinled ? I have the exact same issue

So modelName being written (or having been written in the past) to the constructor is polluting a global (the class, which may have more then one name...). This ends up being at odds with several performance efforts, such as: https://github.com/emberjs/ember.js/pull/14360

Maybe an alternative API can be provided?

This works:

import DS from 'ember-data';
import Ember from 'ember';

export default {
  name: 'model-Name',
  initialize() {
    DS.Model.reopen({
      modelName: Ember.computed(function() {
        return this.get('constructor.modelName');
      })
    });
  }
};

Is this a proper workaround?

@PowerP I think that is a sufficient workaround.

@stefanpenner @cibernox is this still an issue, perhaps we should close; what do you think?

Per our triage policy I'll close this out for now, feel free to reopen if the issue persists on the current release.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dfreeman picture dfreeman  路  4Comments

MichalBryxi picture MichalBryxi  路  3Comments

nathanpalmer picture nathanpalmer  路  3Comments

ggayowsky picture ggayowsky  路  3Comments

escobera picture escobera  路  3Comments