getoutreach / epf

A framework for keeping your Ember.js apps in sync.
http://epf.io
MIT License
369 stars 33 forks source link

Error querying single model - type seems undefined #53

Closed ericeslinger closed 10 years ago

ericeslinger commented 11 years ago

I'm working on a pretty minimal EPF implementation to see if I want to use it for persisting collaborated-on objects in a highly-customized CMS sorta thing. Right now, I'm just tracking user state - users logged in at the admin level can see /api/users, and all users can see /api/users/:user_id, for their own userid.

I'm getting the error listed at the bottom of this post in my code as part of my initial setup. Here's the profile route:

Social.ProfileRoute = Ember.Route.extend
  model: ->
    console.log 'getting usercontroller'
    ret = @session.load 'user', 1
    console.log ret
    console.log 'got it'
    ret

and the user object:

Social.User = Ep.Model.extend
  # type: 'Social.User'
  name: Ep.attr('string')
  email: Ep.attr('string')

This is just a test, with a super-simple user object. I've tried renaming name to uname (in case I was conflicting with an internal) and (as you can see) manually setting type on the object itself, but neither of these approaches works.

If I instead do the model as a list (everything in /api/users), I can see that the correct number of items works {{model.length}} renders as 3, but any attempt to individually address User objects fails with the same error below, either by getting them manually out of the list or by getting them singly as a load 1 instead of a query.

I feel like I'm overlooking something super-simple here - the foo/bar sample EPF app runs fine on my system, and I really can't tell what I'm not doing right here.

Uncaught TypeError: Cannot call method 'toString' of undefined epf.js?body=1:2765 Ep.Adapter.Ember.Object.extend._typeToString epf.js?body=1:2765 Ep.Adapter.Ember.Object.extend._generateClientId epf.js?body=1:2762 Ep.Adapter.Ember.Object.extend.reifyClientId epf.js?body=1:2750 Ep.Session.Ember.Object.extend.reifyClientId epf.js?body=1:3322 Ep.Session.reopen.merge epf.js?body=1:2980 (anonymous function) epf.js?body=1:3251 invokeCallback ember.js?body=1:7252 (anonymous function) ember.js?body=1:7302 EventTarget.trigger ember.js?body=1:7075 (anonymous function) ember.js?body=1:7365 DeferredActionQueues.flush ember.js?body=1:4727 Backburner.end ember.js?body=1:4813 (anonymous function)

ericeslinger commented 11 years ago

Quick follow-up on this. After tracing with the debugger, it seems clear that there's a call to reifyClientId on Social.User which processes through properly (with model being in scope on 2750), but there's a second call to reifyClientId where things don't work, and the model variable is null on line 2750. I'm probably doing something incorrect in my routing, which died quietly under ember-model but not so under epf.

dogawaf commented 11 years ago

32 is about about reserved words.

denisnazarov commented 11 years ago

Is your server returning the proper JSON with the id field populated?

ericeslinger commented 11 years ago

Yeah, as far as I can tell there's some sort of error involved in pulling single values out of the REST adapter (and it could easily be an error on my part, because this seems like reasonably-common behavior). I'm easily able to pull everything in /api/nouns and do an {{#each noun}}{{name}}{{/each}} construct, but if I do a /api/nouns/1 by calling @session.find 'noun', 1 instead of @session.query 'noun', I end up with the error in creating client_id strings.

Rather than pursue this bug at this time, I've reverted back to ember-data for now.

denisnazarov commented 11 years ago

From the docs, loading an individual model is done as follows:

App.PostRoute = Ember.Route.extend({

  model: function(params) {
    return App.Post.find(params.post_id);
  }

});

App.PostRoute = Ember.Route.extend({

  model: function(params) {
    return this.session.load('post', params.post_id);
  }

});
ericeslinger commented 11 years ago

yeah, that's what I'm doing - @session.load 'user' 1 is equivalent to the return this.session.load('post', params.post_id); in your response.

I'm pretty sure my server is returning reasonable JSON - it's formatted using activemodelserializers, and can be digested in list-form by EPF and in singular form by ember-data and ember-model. I also experimented with pushing client_id as a property (by defining it on the serializer and verifying it changed in the API). I can clearly see the query going to rails, but for some reason things fail when establishing a client_id on a new object. Go figure.

ericeslinger commented 11 years ago

Aha, I figured it out - there was a combination of errors that looked similar, so I was conflating them.

First of all, if the serialized JSON object doesn't have an id field named id, it breaks. This is reasonable, and was the root cause of most of my errors - I couldn't deserialize the object because it was looking for a non-existant id.

The other problem is more serious, and maybe I'll open a new issue to document it, and it has to do with non-numeric routing IDs.

I am routing /api/users/:user_id with server logic so that /api/users/NUMBER shows a record, which is pretty standard, but also routing /api/users/current to the current user (as determined by the session cookie). This throws the same to_string error on client id as before, and I imagine it has something to do with the non-numeric value being passed to the query string.

ghempton commented 11 years ago

hmm I am very interested in getting to the bottom of your second issue. I think the issue with /api/users/current is that it thinks current is the ID which in fact is not.

ghempton commented 10 years ago

Is this still an issue? Lots has changed, I will reopen if this has not been fixed.