Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

findRecord giving error "Cannot read property '_internalModel' of undefined" #136

Closed
swatijadhav opened this issue Oct 1, 2015 · 37 comments

Comments

@swatijadhav
Copy link

In our ember app, we are using following versions of ember-data and ember-data-factory-guy.

package.json

"ember-cli": "^1.13.8",
"ember-data": "1.13.9",
"ember-data-factory-guy": "1.13.10",

Note: we are using active-model adapter, not yet migrated to the json-api adapter.

import ActiveModelAdapter from 'active-model-adapter';
export default ActiveModelAdapter.extend({

Route: item.js

export default Ember.Route.extend(({
  model(params) {
    return this.store.findRecord('item', params.item_id);
  }
});

Its working fine in development mode, but while running test cases, am facing following issue:

Test Case for "display single item" fails with following error:

{
  "message": "Cannot read property '_internalModel' of undefined",
  "name": "TypeError"
}

ember-data/lib/system/stpre/finder.js, fails at return statement

  return promise.then(function (adapterPayload) {
    Ember.assert("You made a request for a " + typeClass.typeClassKey + " with id " + id + ", but the adapter's response did not have any data", adapterPayload);
    return store._adapterRun(function () {
      var requestType = get(serializer, 'isNewSerializerAPI') ? 'findRecord' : 'find';
      var payload = normalizeResponseHelper(serializer, store, typeClass, adapterPayload, id, requestType);
      //TODO Optimize
      var record = pushPayload(store, payload);
      return record._internalModel;
    });

(https://github.com/emberjs/data/blob/master/packages/ember-data/lib/system/store/finders.js#L32)

Are we missing anything here? Can anyone please help me to resolve this? I have tried by upgrading versions to latest, but still facing same issue.

@danielspaniel
Copy link
Collaborator

This issue is missing a few key details @swatijadhav.
Like:

  • What does your test look like? ( most important )
  • What does model and factory look like?

@swatijadhav
Copy link
Author

item model:

import Ember from 'ember';
import DS from 'ember-data';
var attr = DS.attr,
    belongsTo = DS.belongsTo;
export default DS.Model.extend({
  donorDescription:     attr('string'),
  state:                attr('string'),
  offer:                belongsTo('offer', { async: false })
})

item factory:

import FactoryGuy from 'ember-data-factory-guy';
import './offer';
FactoryGuy.define('item', {
  sequences: {
    id: function(num) {
      return num + 100;
    },
    description: function(num) {
      return 'Donor Description' + num;
    }
  },
  default: {
    id:               FactoryGuy.generate('id'),
    state:            'submitted',
    donorDescription: FactoryGuy.generate("description"),
  },
});
export default {};

test case:

import Ember from 'ember';
import startApp from '../helpers/start-app';
import syncDataStub from '../helpers/empty-sync-data-stub';
import FactoryGuy from 'ember-data-factory-guy';
import TestHelper from 'ember-data-factory-guy/factory-guy-test-helper';
var App, store, offer1, item1;
module('Donor: Display Item Status', {
  setup: function() {
    App = startApp();
    TestHelper.setup();
    store = TestHelper.getStore();
    syncDataStub(TestHelper);
    offer1 = FactoryGuy.make("offer", {state:"submitted"});
    item1 = FactoryGuy.make("item", {offer: offer1, state:"submitted"});
  },
  teardown: function() {
    Em.run(function() { TestHelper.teardown(); });
    Ember.run(App, 'destroy');
  }
});
test("Display item status for submitted item", function() {
  visit('/offers/' + offer1.id + "/items/"+ item1.id +"/messages");
  andThen(function() {
    equal(currentURL(), '/offers/' + offer1.id + "/items/"+ item1.id +"/messages");
    equal($.trim(find('.status-message').text()), "This item is awaiting review.");
  });
});

@swatijadhav
Copy link
Author

While inspecting further, came to know that in ember-data/lib/system/store/serializer-response.js file, inside function normalizeResponseHelper

get(serializer, 'isNewSerializerAPI')

this value is evaluated as false.

For the same function normalizeResponseHelper, it is given that

/**
  This is a helper method that always returns a JSON-API Document.
  If the current serializer has `isNewSerializerAPI` set to `true`
  this helper calls `normalizeResponse` instead of `extract`.
  All the built-in serializers get `isNewSerializerAPI` set to `true` automatically
  if the feature flag is enabled.

So I added it

export default ActiveModelAdapter.extend({
  isNewSerializerAPI: true,

But still facing same issue.

@danielspaniel
Copy link
Collaborator

do me a favour and do this:

import FactoryGuy from 'ember-data-factory-guy';
import './offer'; // why? maybe you don't need?

FactoryGuy.define('item', {
  sequences: {
    description: function(num) {
      return 'Donor Description' + num;
    }
  },
  default: {
    state:            'submitted',
    donorDescription: FactoryGuy.generate("description"),
  },
});
export default {};

for your test ( get rid of the id line ) ..

@swatijadhav
Copy link
Author

Thanks for the response @danielspaniel
Tried above suggestion, but it does not work. :(

@danielspaniel
Copy link
Collaborator

@swatijadhav ... can you send me your router code too .. curious

also curious to see what you get for:

export default Ember.Route.extend(({
  model(params) {
    console.log( this.store.peekAll('item').get('content').length)
    var item = this.store.findRecord('item', params.item_id);
    console.log(params, item);
    return item;
  }
});

like what the store is returning? check network. should not be doing network call .. should go to store and get the item ( assuming you have the right id .. which you should base on your test )
my guess is something in routes maybe?

@danielspaniel
Copy link
Collaborator

then right after your test code here:

test("Display item status for submitted item", function() {
  console.log(item1) // see if there is '_internalModel' property on item1
  visit('/offers/' + offer1.id + "/items/"+ item1.id +"/messages");

@swatijadhav
Copy link
Author

In router.js, I have following:

  this.resource('offers', function () {
    this.resource('offer', { path: '/:offer_id'}, function() {
      this.resource('item', {path: '/items/:item_id'}, function() {
        this.route('index', { path: '/'});
      });
    });
  });

@swatijadhav
Copy link
Author

yes, it gets 'item1._internalModel' value

  item1._internalModel
  InternalModel {id: "101", store: Class, container: Container, _data: Object, modelName: "item".....

@danielspaniel
Copy link
Collaborator

what about this one:

export default Ember.Route.extend(({
  model(params) {
    console.log( this.store.peekAll('item').get('content').length)
    var item = this.store.findRecord('item', params.item_id);
    console.log(params, item+'');
    return item;
  }
});

what do you get for those console statements

@swatijadhav
Copy link
Author

4
Object {item_id: "101"} "<DS.PromiseObject:ember765>"

@danielspaniel
Copy link
Collaborator

hmm .. 4 is odd .. should be 1, but the rest is good
how about: replace the first console with:
console.log( this.store.peekAll('item').get('content').mapBy('id') )

@swatijadhav
Copy link
Author

the count is 4 because we have created some more data for other test cases in same file.. so we can neglect that

- ["101", "102", "103", "104"]
0: "101"
1: "102"
2: "103"
3: "104"
length: 4__proto__: Array[0]
- Object {item_id: "101"} "<DS.PromiseObject:ember765>"

@danielspaniel
Copy link
Collaborator

ok .. so replace

console.log(params, item+'');

with

item.then(function(model) {
  console.log(model+'', model.get('offer')+'')
});

@danielspaniel
Copy link
Collaborator

though what is really troubling me is that there should not be a payload at all .. since it should be getting the item from the store and returning that one. so I am wondering if you get any network calls when you run this test ( developer tools on chrome .. network tab )

@danielspaniel
Copy link
Collaborator

because if there is an error here:

  return promise.then(function (adapterPayload) {
    Ember.assert("You made a request for a " + typeClass.typeClassKey + " with id " + id + ", but the adapter's response did not have any data", adapterPayload);
    return store._adapterRun(function () {
      var requestType = get(serializer, 'isNewSerializerAPI') ? 'findRecord' : 'find';
      var payload = normalizeResponseHelper(serializer, store, typeClass, adapterPayload, id, requestType);
      //TODO Optimize
      var record = pushPayload(store, payload);
      return record._internalModel;
    });

that means the store went and did an ajax find to get the json .. odd .. isn't it?
boy .. I am curious to see what you get if you put a console statement there
after
// TODO Optimize
console.log(payload) // what could that payload be I wonder?

@swatijadhav
Copy link
Author

> payload
Object {data: null}

@danielspaniel
Copy link
Collaborator

that is super interesting .. well .. is there a network call?

@swatijadhav
Copy link
Author

@swatijadhav
Copy link
Author

Check this issue emberjs/data#3757

@danielspaniel
Copy link
Collaborator

hmm .. fascinating .. that should not be happening .. and good find there from ember-data ticket

@swatijadhav
Copy link
Author

any workaround for this issue? any suggestions?
Reverting it back from findRecord to find, gives same issue..

@danielspaniel
Copy link
Collaborator

hmm .. I guess that concept of preloading the store might be unreliable.
I reckon, you could get around that ... but using the helpers
TestHelper.handleFind('item_with_offer')

module('Donor: Display Item Status', {
  setup: function() {
    App = startApp();
    TestHelper.setup();
    store = TestHelper.getStore();
    syncDataStub(TestHelper);
  },

  teardown: function() {
    Em.run(function() { 
     TestHelper.teardown(); 
     App.destroy() 
    });
  }
});

test("Display item status for submitted item", function() {
  var item = TestHelper.handleFind('item', 'is_submitted', 'has_submitted_offer');
  visit('/offers/' + 1 + "/items/"+ item1.id +"/messages");

  andThen(function() {
    equal(currentURL(), '/offers/1/items/"+ item1.id +"/messages");
    equal($.trim(find('.status-message').text()), "This item is awaiting review.");
  });
});

@danielspaniel
Copy link
Collaborator

 see better detail here
// using traits here to make a submitted item with a submitted offer
var itemId = TestHelper.handleFind('item', 'is_submitted', 'has_submitted_offer');
var offerId = 1; // assumes you let FactoryGuy make the offer
visit('/offers/' + offerId + "/items/"+ itemIid +"/messages");

@danielspaniel
Copy link
Collaborator

though your default is state ( submitted ) for offers and items .. so that might seem redundant .. but I think you know what I mean .. right?

@swatijadhav
Copy link
Author

yeah, got your point..
But here it will fix only one specific test..I have other many tests which failing due to findRecord
I will try out the above suggestion and will update it here..

@swatijadhav
Copy link
Author

Finally got the exact cause:

In my adapter/application.js

// Ember Data 2.0 Reload behavior
shouldReloadRecord: function() { return true; },
shouldReloadAll: function() { return true; },
shouldBackgroundReloadRecord: function() { return true; },
shouldBackgroundReloadAll: function() { return true; },

These lines I had added while fixing deprecation warnings, and because of this, it was causing records to be loaded always, although they were present in ember-data store. So now I just removed those.

Thank you very much for all the help.. 😄

@danielspaniel
Copy link
Collaborator

great news @swatijadhav .. really happy you are back in business, and I am glad you posted this to help others with similar problem

@swatijadhav
Copy link
Author

Thanks 👍

@neeraj-joshi01
Copy link

Getting this error "Cannot read property '_internalModel' of undefined" on this.store.find('user',1) or this.store.findRecord('user',1).
Here is my bower.json,
{
"name": "frontend",
"dependencies": {
"ember": "1.13.11",
"ember-cli-shims": "0.0.6",
"ember-cli-test-loader": "0.2.1",
"ember-data": "1.13.15",
"ember-load-initializers": "0.1.7",
"ember-qunit": "0.4.16",
"ember-qunit-notifications": "0.1.0",
"ember-resolver": "~0.1.20",
"jquery": "^1.11.3",
"loader.js": "ember-cli/loader.js#3.4.0",
"qunit": "~1.20.0",
"bootstrap": "~3.3.6"
}
}

@danielspaniel
Copy link
Collaborator

huh? .. what you talkin bout willis?

@neeraj-joshi01
Copy link

Here is my application adapter :
import ActiveModelAdapter from 'active-model-adapter'

export default ActiveModelAdapter.extend({})

Here is the application serializer:

import { ActiveModelSerializer } from 'active-model-adapter'

export default ActiveModelSerializer.extend()

Error stack trace:
TypeError: Cannot read property '_internalModel' of undefined
at http://localhost:3000/assets/vendor.js:78908:24
at Object.Backburner.run (http://localhost:3000/assets/vendor.js:10843:25)
at ember$data$lib$system$store$$Service.extend._adapterRun (http://localhost:3000/assets/vendor.js:84741:33)
at http://localhost:3000/assets/vendor.js:78903:22
at tryCatch (http://localhost:3000/assets/vendor.js:67710:14)
at invokeCallback (http://localhost:3000/assets/vendor.js:67725:15)
at publish (http://localhost:3000/assets/vendor.js:67693:9)
at http://localhost:3000/assets/vendor.js:44051:7
at Queue.invoke (http://localhost:3000/assets/vendor.js:11571:16)
at Object.Queue.flush (http://localhost:3000/assets/vendor.js:11635:11)

@danielspaniel
Copy link
Collaborator

sorry ... I have no idea what you are talking about .. too little info

@neeraj-joshi01
Copy link

what do you want me to give you? Here is the code snippet which throws this error
that.store.find('user',response.id).then(
(user)->
that.get('session').set('currentUser',user)
that.transitionToRoute('home')
)

@danielspaniel
Copy link
Collaborator

so .. pretend you were me and this is all you had to look at .. you tell me how you would fix it? cause if you could .. maybe you are some kind of genius and I will bow before you.

@neeraj-joshi01
Copy link

what more information you want me to give you ? can you specify that ?

@danielspaniel
Copy link
Collaborator

no .. I want you to figure it out alittle bit .. because you don't seem to be able to understand what it is like for me .. so think more about it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants