PDA

View Full Version : [FIXED]Model getBelongsToClass() not working



sg707
1 Mar 2011, 8:10 AM
I have the following



Ext.regModel('User', {
fields : [
{
name : 'id',
type : 'int'
}, {
name : 'name',
type : 'string'
}
],
hasMany : 'Post',
proxy : {
type : 'rest',
url : 'users',
format : 'json',
reader : {
type : 'json',
root : 'users'
}
}

});

Ext.regModel('Post', {
fields : [
{
name : 'title',
type : 'string'
}
],
belongsTo : 'User'
}



I noticed the following methods were created

User -> posts()
Post -> getUser()

posts() works great! but for getUser() I'm getting undefined. It does print the "user_id" correctly though from Post

<post record>.get('user_id')

sg707
1 Mar 2011, 11:21 AM
also, shouldn't "posts()" be "getPosts()". This seems to be more aligned w/ the method "getUser()"

icflorescu
1 Mar 2011, 5:21 PM
When you call getUser() I think you must supply a callback function as argument; getUser() will trigger a server request to fetch the user object (although in this case the user is already loaded).
Then your callback method will receive the loaded user as the first argument...

sg707
2 Mar 2011, 7:18 AM
That worked!!! How did you find out that it was taking a "callback function"? I need better ExtJS debugging skills.

Also, why is it a call back??

Let say my Post model belongsTo multiple Model. Say "User" and "Group". Then, I have a business logic where I need to invoke AJAX call that requires some value from it's own, "User", and "Group". Then, how do I gather all that info to make a AJAX call?

I really don't understand how User can invoke posts() syncronously and not the other way? :-/

Condor
2 Mar 2011, 7:57 AM
Your server already returns the posts of a user, but it doesn't return the user of a post, so it needs another server request to get the user.

sg707
2 Mar 2011, 8:41 AM
If you take a look at below code



User.load('1', {
success : function(record, operations) {

record.posts().each(function(post) {
console.log(post);
});

record.posts().load( {
callback : function(records, operations, success) {
console.log(records);

records[0].getUser(function() {
console.log(arguments);
})
}
});

}
});
It makes AJAX call to retrieve the User. This would make sense if I'm calling Post.load then it makes sense to make AJAX call to retrieve the associated User but... from above code I'm using User.load... Shouldn't it be default that Post knows the relationship to the User?

icflorescu
2 Mar 2011, 9:17 AM
You can read about the callback function here (http://dev.sencha.com/deploy/ext-4.0-pr2/docs/api/Ext.data.BelongsToAssociation.html). There are still some fuzzy things in the examples on that page, but you'll get the idea. I do agree there might be an unnecessary proxy call, though...

I haven't tested how/if the generated setter (setUser() in your case) works. If you do, please share your results here, others might be interested too :)

Also, there's one more thing you should be aware of: if you're defining your models using namespaces (i.e. 'App.models.User') no getter/setter will be generated for many->one navigation. It's a known bug, I've filed a report about it a couple of days ago.

sg707
2 Mar 2011, 11:02 AM
Tried the setUser method. Doesn't seem like it's assigning user_id.

This is what gets sent to the server (POST method)



{"records":[{"title":"New Post","id":0,"user_id":null}]}




User.load('1', {
success : function(user, operations) {

var newPost = Ext.ModelMgr.create( {
title: 'New Post'
}, 'Post');

console.log(user.get("id"));
newPost.setUser(user);
newPost.save();
}
}

kveeiv
10 Mar 2011, 8:15 AM
This would make sense if I'm calling Post.load then it makes sense to make AJAX call to retrieve the associated User but... from above code I'm using User.load... Shouldn't it be default that Post knows the relationship to the User?

This appears to be a bug in the Ext.data.Reader process. In the readAssociated function, there is an attempt to do just what you describe:


//now that we've added the related records to the hasMany association, set the inverse belongsTo
//association on each of them if it exists
inverseAssociation = associatedModel.prototype.associations.findBy(function(assoc) {
return assoc.type == 'belongsTo' && assoc.associatedName == record.constructor.modelName;
});

However, "record.constructor.modelName" is undefined. I am not sure where the official place to get that modelName is, but I found it available as "record.$className". Changing that check results in the inverse association properly being set. You are then able to call post.getUser() as you expected to be able to in the original post.

evant
14 Mar 2011, 3:19 AM
@kveeiv is correct, it was looking at the wrong property. I've fixed this up.