frodo2975
frodo2975

Reputation: 11725

Backbone Relational: Model with 2 collections of the same type

I'm trying to create a backbone relational model with 2 "hasMany" relations of the same type, but I'm getting the error: "Cannot create relation=child on "(myReverseRelationName)" for model=child: already taken by relation=child". Is this something that is supposed to be allowed, or am I doing it wrong? Thanks.

I've created a jsFiddle so you guys can take a look for yourselves: http://jsfiddle.net/Mu68f/5/

And here's the code:

Animal = Backbone.RelationalModel.extend({
    urlRoot: '/animal/',
});

AnimalCollection = Backbone.Collection.extend({
    model: Animal
});

Zoo = Backbone.RelationalModel.extend({    
    relations: [
        {
            type: Backbone.HasMany,
            key: 'largeAnimals',
            relatedModel: Animal,
            collectionType: AnimalCollection,
            reverseRelation: {
                key: 'livesIn',
                includeInJSON: false
            }
        },
        {
            type: Backbone.HasMany,
            key: 'smallAnimals',
            relatedModel: Animal,
            collectionType: AnimalCollection,
            reverseRelation: {
                key: 'livesIn',
                includeInJSON: false
            }
        },
    ]
});

// initialize our zoo
var zoo = new Zoo({
    largeAnimals: [{name: "Big Bill"}],
    smallAnimals: [{name: "Pee Wee"}]
});
console.log(zoo);

Upvotes: 3

Views: 1524

Answers (1)

Ricky Zein
Ricky Zein

Reputation: 557

The problem is that both largeAnimals and smallAnimals are within the "Animal" model class, but don't have distinct references to the Zoo.

In terms of associations, if a model (i.e. Animals) belongs to another model (Zoo) in two distinct ways (small and large), then it should have two distinct types of "foreign keys" that refer to the associated model in two different ways.

In terms of simplicity, I would go the route of adding "large" or "small" as attributes to the Animal class instead of trying to associate it with the the Zoo in two different ways.

BUT, if you would like to associate the Animals with the Zoo that way, here's how you can do it:

Animal = Backbone.RelationalModel.extend({
    urlRoot: '/animal/',
});

AnimalCollection = Backbone.Collection.extend({
    model: Animal
});

Zoo = Backbone.RelationalModel.extend({    
    relations: [
        {
            type: Backbone.HasMany,
            key: 'largeAnimals',
            relatedModel: Animal,
            collectionType: AnimalCollection,
            reverseRelation: {
                key: 'livesIn',
                includeInJSON: false
            }
        },
        {
            type: Backbone.HasMany,
            key: 'smallAnimals',
            relatedModel: Animal,
            collectionType: AnimalCollection,
            reverseRelation: {
                key: 'residesIn', // different key to refer to Zoo
                includeInJSON: false
            }
        },
    ]
});

As you can see, I gave the smallAnimal a different type of key to refer to the Zoo. this also means that when you fetch smallAnimals from the server, smallAnimal objects should have an attribute that points to the Zoo as residesIn.

Upvotes: 2

Related Questions