javascriptbackbone.jsbackbone-relational

'Backbone Relational' model relation adds an 'id' with a collection as a value, preventing PUT and DELETE


I successfully implemented loading and showing relations with 'Backbone Relational' from an API I created. I get how things work by trial and error. I do think the docs are lacking some clarity though since it took a lot of time to figure out how things work. Especially on how to map things to the API I think the docs are lacking a bit.

Problem
Adding a bookmark works, it's the editing and deletion that don't work. The PUT becomes a POST and the DELETE simply doesn't fire at all. When I set an id to the model hardcoded it does work. So the id is missing which makes sense for the PUT becoming a POST.

The problem seems to be that the id doesn't hold an actual id, but a collection. The view where the problem occurs does not requires the BookmarkBinding, it's used somewhere else. Simply the fact that it has Bookmark as a relation makes the DELETE and PUT break.

BookmarkBinding model:

App.Model.BookmarkBinding = Backbone.RelationalModel.extend({
    defaults: {
        set_id: null,
        bookmark_id: null
    },
    relations: [{
        type: Backbone.HasOne,
        key: 'bookmark',
        relatedModel: 'App.Model.Bookmark',
        reverseRelation: {
            type: Backbone.HasOne,
            key: 'id'
        }
    }],
    urlRoot: 'http://api.testapi.com/api/v1/bookmark-bindings'
});

Bookmark model:

App.Model.Bookmark = Backbone.RelationalModel.extend({
    defaults: {
        url: 'undefined',
        description: 'undefined',
        visits: 0,
    },
    relations: [{
        type: Backbone.HasMany,
        key: 'termbindings',
        relatedModel: 'App.Model.TermBinding',
        reverseRelation: {
            key: 'bookmark_id',
        }
    }],
    urlRoot: 'http://api.testapi.com/api/v1/bookmarks'
});

Solution

  • The problem was that on editing or deleting the bookmark model, the bookmark binding model wanted to do it's work too since it is related too the bookmark from it's side. I already tried to remove the reverse relation which didn't prove to be a solution since in the other part of my application where I used the bookmark bindings things wouldn't work anymore.

    Solution
    I did end up removing the reverse relation (@jarede +1 for that!), but the crux was how to implement the foreign key to fetch relations from the API without a reverse relation. I ended up adding the keySource and keyDestination which made everything work out.

    Sidenote
    Backbone Ralational cannot handle identical foreign keys either, this gave me some problems too. This will make the lastly declared foreign key overwrite all the previous ones. This can be quite impractical since within an API it's not uncommon that model's are related to a column named id. So the idAttribute can be set with idAttribute: '_id' for example, but the foreign key has to be unique across your application.

    BookmarkBinding model:

    App.Model.BookmarkBinding = Backbone.RelationalModel.extend({
        defaults: {
            set_id: null,
            bookmark_id: null
        },
        relations: [{
            type: Backbone.HasOne,
            key: 'bookmark',
            keySource: 'id',
            keyDestination: 'bookmark',
            relatedModel: 'App.Model.Bookmark'
        }],
        urlRoot: 'http://api.testapi.com/api/v1/bookmark-bindings'
    });