Backbone-relational icon indicating copy to clipboard operation
Backbone-relational copied to clipboard

reverseRelation Collection is always instanceof Backbone.Collection

Open mauron85 opened this issue 9 years ago • 6 comments

Description: reverseRelation Collection is always instanceof Backbone.Collection

Expected: reverseRelation Collection is instanceof Routes Actual: reverseRelation Collection is instanceof Backbone.Collection only

How to reproduce:

jsFiddle example: http://jsfiddle.net/mauron85/8uhvyq9L/

var User = Backbone.RelationalModel.extend({
        defaults: {
            routes: []
        }
});

var Route = Backbone.RelationalModel.extend({
    relations:[{
            type: Backbone.HasOne,
            key: 'user',
            relatedModel: User,
            includeInJSON: 'id', //serialize only id not a full object
            reverseRelation: {
                key: 'routes',
                includeInJSON: 'id'
            }        
    }]
});

var Users = Backbone.Collection.extend({
    model: User,
  url: '/users'
});

var Routes = Backbone.Collection.extend({
    model: Route,
    url: '/routes',
    someMethod: function () {
        console.log('you just called some method');
    }
});

var userJSON = [{
    id: 'john'
},{
    id: 'pete'
}];

var routesJSON = [{
    id: 'first',
    user: 'pete'
},{
    id: 'second',
    user: 'john'
}];

var users = new Users(userJSON);
var routes = new Routes(routesJSON);

var johnRoutes = users.at(0).get('routes')
console.log(johnRoutes.at(0).get('id') === 'second'); // TRUE
console.log(johnRoutes instanceof Backbone.Collection); // TRUE,
console.log(johnRoutes instanceof Routes); // FALSE, we cannot call Routes methods!!!

johnRoutes.someMethod(); // Uncaught TypeError: johnRoutes.someMethod is not a function

~~Modified version with model collection as constructor option throws:~~ ~~Uncaught TypeError: collection.on is not a function~~ ~~jsFiddle: http://jsfiddle.net/mauron85/8uhvyq9L/4/~~

mauron85 avatar Jul 14 '15 17:07 mauron85

The problem seems to be hardcoded collectionType: Backbone.Collection

Backbone.HasMany = Backbone.Relation.extend({
    collectionType: null,

    options: {
        reverseRelation: { type: 'HasOne' },
        collectionType: Backbone.Collection, // HARDCODED
        collectionKey: true,
        collectionOptions: {}
    },
...

mauron85 avatar Jul 15 '15 12:07 mauron85

Adding test scenario into Backbone-relational test suite:

https://rawgit.com/mauron85/Backbone-relational/issue-536/test/index.html

mauron85 avatar Jul 15 '15 12:07 mauron85

do this:

    relations:[{
            type: Backbone.HasOne,
            key: 'user',
            relatedModel: User,
            includeInJSON: 'id', //serialize only id not a full object
            reverseRelation: {
                key: 'routes',
                includeInJSON: 'id',
                **type: Backbone.HasOne** <-----
            }        
    }]

If the relation should be bidirectional, specify the details for the reverse relation here. It's only mandatory to supply a key; relatedModel is automatically set. The default type for a reverseRelation is HasMany for a HasOne relation (which can be overridden to HasOne in order to create a one-to-one relation), and HasOne for a HasMany relation.

ambischof avatar Jul 30 '15 20:07 ambischof

Thank you. But my reverseRelation is HasMany. Or in words User can have many Routes.

mauron85 avatar Jul 30 '15 20:07 mauron85

Ah sorry, seemed I misunderstood the problem.

Why haven't you used the option collectionType? (http://backbonerelational.org/#relations-collectionType)

ambischof avatar Jul 31 '15 15:07 ambischof

Thank you. That solved my problem.

Actually I thought I have tried to use collectionType some time before. Apparently I did some mistakes, because this example works:

http://jsfiddle.net/mauron85/8uhvyq9L/12/

I'll leave this issue open. Because i think, following notice should be mentioned in the docs somewhere:

_"Reverse relation collection DOES NOT inherit it's collection type from relation it is reverse to. If you use reverseRelation, please make sure, you also specify collectionType. If you don't provide it, reverse collection type will be Backbone.Collection"_

And also my examples, might be helpful: http://jsfiddle.net/mauron85/8uhvyq9L/ http://jsfiddle.net/mauron85/8uhvyq9L/12/

mauron85 avatar Aug 02 '15 09:08 mauron85