1. #1
    Sencha User
    Join Date
    Jan 2012
    Posts
    49
    Vote Rating
    0
    Answers
    6
    j.k is on a distinguished road

      0  

    Default Answered: belongsTo association in Beta2 not working

    Answered: belongsTo association in Beta2 not working


    I've got a couple of nested models with hasMany associations and one store to load my xml file into that model hierarchy. That is working just fine.
    All models (except for the root one) have a belongsTo association, so I can obtain the parent node of every sub-node:

    Code:
    		belongsTo: {
    			model: "MyApp.model.mymodule.ParentModelXYZ",
    			getterName: "getParentNode"
    		},
    When I call getParentNode() on the model instance I get the following error message:

    Code:
    Error: [ERROR][Anonymous] You are trying to load a model that doesn't have a Proxy specified
    That is correct, I don't have proxies specified in the models, my proxy is specified in my store. This used to work in PR2 but not in Beta2 anymore. Is this a bug or is there a workaround?

    The raw data in the model instance is correct and does contain the correct parentNode. I did not manually specify foreign keys or something.

    I tried to add a belongsTo association in the kitchen sink Nested Loading demo, too, but didn't get that to work either.

    Thanks again for your helpful responses,
    j.k

  2. Quote Originally Posted by mitchellsimoens View Post
    You will need to put a proxy on the model.
    No, that definitely can't be true, and it would be terrible if it would - think about it:
    for every item I have in my model, if I call getParentNode - and if you put that structure in a nestedlist you call that plenty of times - , the whole XML document is loaded from the web and parsed again, just to resolve the association to the parent node, that just doesn't make sense. And it worked in PR2 and before.

    After further investigation and debugging of the Beta 2 code, I found, that it is indeed a bug - or let's say an unwanted side effect of changes made to the code - that the parent nodes are not populated during the initial loading of the document.

    The relevant code resides in Ext.data.association.HasMany#read(), which contains the logic to populate a node's parentNode property if you have a hasMany - belongsTo relationship between 2 models:

    Code:
            //now that we've added the related records to the hasMany association, set the inverse belongsTo
            //association on each of them if it exists
            inverse = this.getAssociatedModel().associations.findBy(function(assoc) {
                return assoc.getType() === 'belongsTo' && assoc.getAssociatedName() === record.$className;
            });
           //if the inverse association was found, set it now on each record we've just created
    That code fails, hence inverse remains null, because in Beta 2 the associatedName attribute of every association is not the full class name of the model:

    Code:
        applyAssociatedName: function(associatedName) {
            if (!associatedName) {
                associatedName = this.getAssociatedModel().modelName;
            }
            associatedName = associatedName.slice(associatedName.lastIndexOf('.')+1);
            return associatedName;
        },
    overriding that method with the associatedName = associatedName.slice(...) line commented out fixes this issue and the belongsTo relationship is resolved once again automatically when loading the structure in a store.

    If other people happen to run into this problem, here's the code you need to override that behavior to the old one:

    Code:
    Ext.define("MyApp.overrides.Association", {
    	override: "Ext.data.association.Association",
    
    	applyAssociatedName: function (associatedName) {
    		if (!associatedName) {
    			associatedName = this.getAssociatedModel().modelName;
    		}
    	//	associatedName = associatedName.slice(associatedName.lastIndexOf('.') + 1);
    		return associatedName;
    	}
    });
    I hope this change makes it into the final version of ST2.

    Also let me just say that I love the ability to just override any method I want in the whole framework with Ext.define() and override, this makes the whole framework so much more flexible, it's fantastic.

    kind regards

  3. #2
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    37,547
    Vote Rating
    872
    Answers
    3566
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    Are you using TreeStore and NestedList?
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  4. #3
    Sencha User
    Join Date
    Jan 2012
    Posts
    49
    Vote Rating
    0
    Answers
    6
    j.k is on a distinguished road

      0  

    Default


    No I'm using a regular Store and a customized NestedList implementation, because for some reason I didn't get the NestedList to work as expected (maybe I'll try later again). but I doubt this matters, as the error seems to lie in the Ext.data.Model or BelongsTo implementation.

  5. #4
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    37,547
    Vote Rating
    872
    Answers
    3566
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    I spent a little bit of time to create a simple example of belongsTo:

    Code:
    Ext.define('Post', {
        extend : 'Ext.data.Model',
    
        config : {
            fields : ['id', 'user_id'],
            proxy  : {
                type   : 'ajax',
                url    : 'data/json.json',
                reader : 'json'
            }
        }
    });
    
    Ext.define('Comment', {
        extend : 'Ext.data.Model',
    
        config : {
            fields    : ['id', 'user_id', 'post_id'],
            belongsTo : 'Post'
        }
    });
    
    Ext.setup({
        onReady: function() {
    
            var comment = new Comment({
                id      : 1,
                user_id : 1,
                post_id : 1
            });
            
            comment.getPost({
                callback : function(post) {
                    console.log(post);
                }
            });
    
        }
    });
    This is what I have in my data/json.json

    Code:
    {
        "id" : 1,
        "user_id" : 1
    }
    This should then console.log out a valid Post model instance after it loaded
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  6. #5
    Sencha User
    Join Date
    Jan 2012
    Posts
    49
    Vote Rating
    0
    Answers
    6
    j.k is on a distinguished road

      0  

    Default


    Thanks, but this example isn't reflecting the problem I'm having in my app, because:
    I don't have a proxy set up in my model, I have a separate store, which loads all the data in my model hierarchy.
    If I were to add a proxy config to my root model, the system would reload the entire document, when I call getParentNode() (as in your example), which is unnecessary, because I already did load everything into my various models.

    As I said my code worked in PR2, so something must've changed in the way a belongsTo association is resolved.

    Let me know if you need more information on that.

  7. #6
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    37,547
    Vote Rating
    872
    Answers
    3566
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    You will need to put a proxy on the model.
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  8. #7
    Sencha User
    Join Date
    Jan 2012
    Posts
    49
    Vote Rating
    0
    Answers
    6
    j.k is on a distinguished road

      0  

    Default


    Quote Originally Posted by mitchellsimoens View Post
    You will need to put a proxy on the model.
    No, that definitely can't be true, and it would be terrible if it would - think about it:
    for every item I have in my model, if I call getParentNode - and if you put that structure in a nestedlist you call that plenty of times - , the whole XML document is loaded from the web and parsed again, just to resolve the association to the parent node, that just doesn't make sense. And it worked in PR2 and before.

    After further investigation and debugging of the Beta 2 code, I found, that it is indeed a bug - or let's say an unwanted side effect of changes made to the code - that the parent nodes are not populated during the initial loading of the document.

    The relevant code resides in Ext.data.association.HasMany#read(), which contains the logic to populate a node's parentNode property if you have a hasMany - belongsTo relationship between 2 models:

    Code:
            //now that we've added the related records to the hasMany association, set the inverse belongsTo
            //association on each of them if it exists
            inverse = this.getAssociatedModel().associations.findBy(function(assoc) {
                return assoc.getType() === 'belongsTo' && assoc.getAssociatedName() === record.$className;
            });
           //if the inverse association was found, set it now on each record we've just created
    That code fails, hence inverse remains null, because in Beta 2 the associatedName attribute of every association is not the full class name of the model:

    Code:
        applyAssociatedName: function(associatedName) {
            if (!associatedName) {
                associatedName = this.getAssociatedModel().modelName;
            }
            associatedName = associatedName.slice(associatedName.lastIndexOf('.')+1);
            return associatedName;
        },
    overriding that method with the associatedName = associatedName.slice(...) line commented out fixes this issue and the belongsTo relationship is resolved once again automatically when loading the structure in a store.

    If other people happen to run into this problem, here's the code you need to override that behavior to the old one:

    Code:
    Ext.define("MyApp.overrides.Association", {
    	override: "Ext.data.association.Association",
    
    	applyAssociatedName: function (associatedName) {
    		if (!associatedName) {
    			associatedName = this.getAssociatedModel().modelName;
    		}
    	//	associatedName = associatedName.slice(associatedName.lastIndexOf('.') + 1);
    		return associatedName;
    	}
    });
    I hope this change makes it into the final version of ST2.

    Also let me just say that I love the ability to just override any method I want in the whole framework with Ext.define() and override, this makes the whole framework so much more flexible, it's fantastic.

    kind regards

  9. #8
    Sencha User
    Join Date
    Jan 2012
    Posts
    49
    Vote Rating
    0
    Answers
    6
    j.k is on a distinguished road

      0  

    Default


    So, this was just fixed in Beta3, probably should've spent today working on another part of the app - case closed, thanks!

  10. #9
    Sencha User
    Join Date
    Jul 2009
    Posts
    55
    Vote Rating
    0
    jgadbois is on a distinguished road

      0  

    Default


    Was this reverted in the RC? I'm getting the proxy error now.

Thread Participants: 2