Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

fetchRelated fails to correctly load nested relations with loading a set #455

Closed
eriks5 opened this Issue · 2 comments

3 participants

@eriks5

I have some code that loads nested relations using fetchRelated.

With backbone-relational 0.8.8 (and master) this fails (some relations are not fetched) if the object on which fetchRelated is called was itself loaded as a HasMany relation on another object, and the Collection.url method is overridden to load a single set of objects instead of each object separately (eg. when using backbone-tastypie).

In our real-life application, everythings works as it should when Collection.url just returns Collection.urlRoot (but, as expected, each fetch of a collection generates a request for each object, including all objects in nested relations), and things break when Collection.url from backbone-tastypie is used (and we have one request for each collection, but none for nested relations). The latter has worked perfectly on backbone-relational 0.8.6.

I've managed to isolate the issue as two test cases that can be dropped into tests.js.

Both test cases are nearly identical, except for the way the url is created and the server reponse. The first test case (using default Collection.url) passes, the second one (using custom Collection.url to load all models as a set like backbone-tastypie uses) fails.

They use 3 models: a Top, Middle and Leaf model. Top has a HasMany relation to Middle, which has a HasOne relation to Leaf. The second test case fails to load the content for Leaf, no requests are generated.

test( "Nested relations with HasMany", function() {
    var LeafModel = Backbone.RelationalModel.extend({
            idAttribute: 'resource_uri'
        }),
        MiddleModel = Backbone.RelationalModel.extend({
            idAttribute: 'resource_uri',
            relations: [
                {
                    type: Backbone.HasOne,
                    key: 'leaf',
                    relatedModel: LeafModel,
                    includeInJSON: 'resource_uri'
                }
            ]
        }),
        MiddleCollection = Backbone.Collection.extend({
            model: MiddleModel
        }),
        TopModel = Backbone.RelationalModel.extend({
            idAttribute: 'resource_uri',
            relations: [
                {
                    type: Backbone.HasMany,
                    key: 'middle',
                    relatedModel: MiddleModel,
                    includeInJSON: 'resource_uri',
                    collectionType: MiddleCollection
                }
            ]
        });

    var top = TopModel.build({
            resource_uri: 'top/1',
            middle: ['middle/1'],
            label: 'top object'
        });

    equal( top.get('label'), 'top object', "Top object is initialized" );

    var requests = top.fetchRelated('middle', {
            response: {
                status: 200,
                responseText: {
                    resource_uri: 'middle/1',
                    label: 'middle object',
                    leaf: 'leaf/1'
                }
            }
        });

    equal( requests.length, 1, "A request has been made" );

    var middle_coll = top.get('middle'),
        middle = middle_coll.get('middle/1');

    equal( middle.get('label'), "middle object", "Middle object was initialized" );

    requests = middle.fetchRelated('leaf', {
        response: {
            status: 200,
            responseText: {
                resource_uri: 'leaf/1',
                label: 'leaf object'
            }
        }
    });

    equal( requests.length, 1, "A request has been made" );

    equal( middle.get('leaf').get('label'), "leaf object", "Leaf object was initialized" );
});

test( "Nested relations with HasMany and set url", function() {
    var LeafModel = Backbone.RelationalModel.extend({
            idAttribute: 'resource_uri'
        }),
        MiddleModel = Backbone.RelationalModel.extend({
            idAttribute: 'resource_uri',
            relations: [
                {
                    type: Backbone.HasOne,
                    key: 'leaf',
                    relatedModel: LeafModel,
                    includeInJSON: 'resource_uri'
                }
            ]
        }),
        MiddleCollection = Backbone.Collection.extend({
            model: MiddleModel,
            url: function(models) { return models && '/middle/set/'; }
        }),
        TopModel = Backbone.RelationalModel.extend({
            idAttribute: 'resource_uri',
            relations: [
                {
                    type: Backbone.HasMany,
                    key: 'middle',
                    relatedModel: MiddleModel,
                    includeInJSON: 'resource_uri',
                    collectionType: MiddleCollection
                }
            ]
        });

    var top = TopModel.build({
            resource_uri: 'top/1',
            middle: ['middle/1'],
            label: 'top object'
        });

    equal( top.get('label'), 'top object', "Top object was initialized" );

    var requests = top.fetchRelated('middle', {
            response: {
                status: 200,
                responseText: [{
                    resource_uri: 'middle/1',
                    label: 'middle object',
                    leaf: 'leaf/1'
                }]
            }
    });

    equal( requests.length, 1, "A request has been made" );

    var middle_coll = top.get('middle'),
        middle = middle_coll.get('middle/1');

    equal( middle.get('label'), "middle object", "Middle object was initialized" );

    requests = middle.fetchRelated('leaf', {
        response: {
            status: 200,
            responseText: {
                resource_uri: 'leaf/1',
                label: 'leaf object'
            }
        }
    });

    // The following two assertions fail, as `leaf` was not fetched (requests is empty)
    equal( requests.length, 1, "A request has been made" );

    equal( middle.get('leaf').get('label'), "leaf object", "Leaf object was initialized" );
});
@Boogydown

I endorse this fix! ...for what it's worth :)

@PaulUithol
Owner

Fixed by 30b0abb

@PaulUithol PaulUithol closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.