Add paramRoot support for your Rails Backbone app
Out of the box, Backbone doesn't include a param root by default when sending requests off to your rails app.
There are gems like backbone-rails that offer some syntactic sugar with a paramRoot feature.
var User = Backbone.Model.extend({
paramRoot: 'user'
});
Which lets you do
User.new(params[:user])
in your controllers.
But here's a lighter way to add paramRoot sugar support:
Backbone.sync calls toJSON() when it sends data off to your app. The method is pretty bare, but it gets passed an options object. So well just make it a little smarter and pass it a indicator if it wants to wrap everything in a param root:
_.extend(Backbone.Model.prototype, {
//override backbone json
toJSON: function(options) {
var data = {},
attrs = _.clone(this.attributes);
//if the model has a paramRoot attribute, use it as the root element
if(options && options.includeParamRoot && this.paramRoot) {
data[this.paramRoot] = attrs;
} else {
data = attrs;
}
return data;
}
});
Additionally, we'll override Backbone.sync so it'll automatically pass an includeParamRoot indicator to toJSON() on create, update, and patch:
//store the old sync, this is to make testing easier.
Backbone.oldSync = Backbone.sync;
//replace backbone sync with our own version.
Backbone.sync = function( method, model, options ) {
//pass in a includeParamRoot = true to the options
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
options.includeParamRoot = true;
}
return Backbone.oldSync.apply(this, [method, model, options]);
};
Here's the finished product:
//Smarter JSON, we overwrite sync to keep rails convention of having a root
//to requests.
!function(Backbone){
//store the old sync, this is to make testing easier.
Backbone.oldSync = Backbone.sync;
//replace backbone sync with our own version.
Backbone.sync = function( method, model, options ) {
//pass in a includeParamRoot = true to the options
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
options.includeParamRoot = true;
}
return Backbone.oldSync.apply(this, [method, model, options]);
};
_.extend(Backbone.Model.prototype, {
//override backbone json
toJSON: function(options) {
var data = {},
attrs = _.clone(this.attributes);
//if the model has a paramRoot attribute, use it as the root element
if(options && options.includeParamRoot && this.paramRoot) {
data[this.paramRoot] = attrs;
} else {
data = attrs;
}
return data;
}
});
}(Backbone);Written by Johny Ho
Related protips
Have a fresh tip? Share with Coderwall community!
JavaScript on a page runs with the privileges of that origin. One altered library, tag manager, or snippet can read inputs, change what people see, and call your APIs as the user.
Security insights from Cside