I wanted to write a quick post regarding these 2 libraries. Any large & complex web-app utilizing Backbone.js (or Knockback in my own case) has need for some type of relationship mapping across models. I’ll be comparing the 2 biggest players, looking at Backbone Relational vs Backbone Associations.
What do you need out of your relational library
The most basic need in a relational library is simply the association of models – for several purposes:
- Encapsulation of data/behavior into sub models
- The ability to bootstrap json and have it automatically loaded into the relevant models.
Take for example the below setup (written in Backbone Associations):
var Order = new Backbone.AssociatedModel({
relations: [{
key: “items”,
collectionType: OrderItems,
type: Backbone.Many
}]
});
I’m specifying a relationship between an Order model and its associated Items – pretty common to almost every eCommerce store out there. I expect that a javascript array I load into an Order be translated into a collection of items:
var order = new Order({
order_num: "CL-0001",
items: [{qty: 5, price: 50.00}, {qty: 1, price: 100}], //I expect this to become a collection of type OrderItems with 2 models
total: 350.00
});
And then I expect for the order items to be serialized into json when I’m using Backbone to persist my model to the server:
Order.toJSON();
//Should output {order_num:"CL-0001",total:350.00,items:[{qty:5,price:50},{qty:1,price:100.00}]
Those are the basic requirements. Both libraries provide this functionality.
I prefer Backbone Associations
Everytime I’ve needed a relational library the above scenario is all I require. Therefore I prefer Backbone Associations. Why?
- Backbone Associations is much faster (click here for the whitepaper).
- Backbone Associations does not put a limit on the number of Models with the same id that can be instantiated (more about this below).
- Backbone Associations is easy to pick up and to modify.
The second reason I listed above is by far the biggest constraint I face when using Backbone Relational. You may have seen the infamous:
Error: Cannot instantiate more than one Backbone.RelationalModel with the same id per type!
This was a design decision made by Backbone Relational’s author – and on some level it makes sense. If you’re using a model with the same id in multiple parts of your code, there should really only be one reference to it in memory. (Read more here about the decision), however the truth is that at some point you’re going to end up instantiating the same model twice, which isn’t inherently a bad thing. In my case, I actually bootstrap the REST endpoint for all my models, but use the same model class, making Backbone Relational a definite no for me:
CadenceModel = Backbone.Model.extend({
initialize:function(attributes,opts) {
Backbone.AssociatedModel.prototype.initialize.apply(this,attributes,opts);
var _crud_url = this.get(“_crud_url”);
if (_crud_url && typeof(this.urlRoot) === “undefined”) {
this.urlRoot =_crud_url;
}
},
});
var order = new CadenceModel({
_crud_url = “/order”
});
order.save();
//Saves to /order with a POST
var product = new CadenceModel({
_crud_url = “/product”,
id: 3
});
product.save();
//Saves to /product/3 with a PUT
You can see this setup lets us reuse a general model for all different endpoints; we need only make a separate model if we actually have separate functionality. So, for that reason, I simply can’t use Backbone Relational.
When to use Backbone Relational
Backbone Relational has more power than Backbone Associations. Take a look at some of the extra features it has:
- Full specifications for reverse lookups. Backbone Relational will allow you to specify a key in a child relation to “point back” to the parent. You can also specify how the parent is serialized in JSON when the child is saved to the server – Backbone Associations simply provides a “parents” array with all the possible parents of a model.
- Support for submodel type comparisons. Backbone Relational allows you to specify the Constructor type in a friendly way which lets you use instanceof to test a SubModel’s type – Backbone Associations has no support for this.
- Based on github pulse, Backbone Relational is more active (larger user base).
These are the 3 biggest reasons to use Backbone Relational in my personal opinion. That being said, I rarely find myself needing to specify a reverse relationship any more specific than the one Backbone Associations allows.
Conclusion
At the end of the day, if you need the power Backbone Relational offers you don’t really have another choice currently. However, if you can stick to Backbone Associations I recommend it for the flexibility and speed!
Hey Alan,
stumbled across this article and found it quite useful so wanted to give you a shout out for that. I have developed couple of complex web apps usign Backbone.js and Backbone elational. Have found it to be really powerful. But I have also stumbled on the “Error: Cannot instantiate more than one Backbone.RelationalModel with the same id per type!” issue multiple times and had to resort to using the findOrCreate() method to work around it.
I didn’t know about backbone-associations until now. Will definitely check it and out for future projects.
Thanks!