09Nov

Making Backbone-Relational work with deep namespaces

Posted by Elf Sternberg as javascript

It’s no secret that I’m a Backbone.js fan, along with everything else. One of my other preferences is for Backbone-Relational, a nifty hack on top of Backbone that allows you to create, manage, and maintain simple relationships between objects. If you have a CouchDB or other JSON-oriented database, and you want to manipulate a record with Backbone on the client and then write it back, Backbone-Relational will let you define how child records get encoded into JSON, and when you write the parent object the backbone toJSON() call will automatically encapsulate your record in a DB-ready format. Very good.

I’m also fond of namespaces, and have started using the easy modules hack to manage namespaces with Coffeescript. It’s just a layer of abstraction on top of simply allocating yourself a namespace hanging off the root (in the client case, the traditional DOM window object). But it’s a nice, clear, self-documenting abstraction.

I discovered, however, that Backbone-Relational doesn’t like this idea. Since it’s an ORM, it needs to keep references to the models used for relationships, and it stores these as strings. The introspection layer is fairly dumb and not sure where to stop, so it assumes all of the names hang off the root namespace.

Bad idea. The following will not work:

@module "MyModule", ->
    class @AClass
        relations: [
            type: Backbone.HasMany
            key: 'children'
            relatedModel: @TheOtherClass
            includeInJSON: false
            reverseRelation:
                type: Backbone.HasOne
                key: 'parent'
        ]

However, because Backbone-Relational is working off string namespaces, specifying the relationships a  string works wonders:

@module "MyModule", ->
    MyModule = @
    class MyModule.AClass
        relations: [
            type: Backbone.HasMany
            key: 'children'
            relatedModel: "MyModule.TheOtherClass"
            includeInJSON: false
            reverseRelation:
                type: Backbone.HasOne
                key: 'parent'
        ]

In some respects, this is fairly ugly. You’re losing some of the shorthand advantages of using the Module hack by repetitiously (if you’re using the namespace in more than one file) re-assigning the module’s this object to a local name.  In other respects, it’s self-documenting, allows Backbone-Relational to work well, and is well-behaved.

Comment Form

Recent Comments