Instantly share code, notes, and snippets.

Embed
What would you like to do?
Makes Backbone.js play nicely with default Rails setup
//
// Backbone.Rails.js
//
// Makes Backbone.js play nicely with the default Rails setup, i.e.,
// no need to set
// ActiveRecord::Base.include_root_in_json = false
// and build all of your models directly from `params` rather than
// `params[:model]`.
//
// Load this file after backbone.js and before your application JS.
//
Backbone.RailsJSON = {
// In order to properly wrap/unwrap Rails JSON data, we need to specify
// what key the object will be wrapped with.
_name : function() {
if (!this.name) throw new Error("A 'name' property must be specified");
return this.name;
},
// A test to indicate whether the given object is wrapped.
isWrapped : function(object) {
return (object.hasOwnProperty(this._name()) &&
(typeof(object[this._name()]) == "object"));
},
// Extracts the object's wrapped attributes.
unwrappedAttributes : function(object) {
return object[this._name()];
},
// Wraps the model's attributes under the supplied key.
wrappedAttributes : function() {
var object = new Object;
object[this._name()] = _.clone(this.attributes);
return object;
},
// Sets up the new model's internal state so that it matches the
// expected format. Should be called early in the model's constructor.
maybeUnwrap : function(args) {
if (this.isWrapped(args)) {
this.set(this.unwrappedAttributes(args), { silent: true });
this.unset(this._name(), { silent: true });
this._previousAttributes = _.clone(this.attributes);
}
}
};
_.extend(Backbone.Model.prototype, Backbone.RailsJSON, {
// This is called on all models coming in from a remote server.
// Unwraps the given response from the default Rails format.
parse : function(resp) {
return this.unwrappedAttributes(resp);
},
// This is called just before a model is persisted to a remote server.
// Wraps the model's attributes into a Rails-friendly format.
toJSON : function() {
return this.wrappedAttributes();
},
// A new default initializer which handles data directly from Rails as
// well as unnested data.
initialize : function(args) {
this.maybeUnwrap(args);
}
});
@bernat

This comment has been minimized.

bernat commented Feb 23, 2011

Hello, I'm always getting the error "A name must be specified".
Is there any place where you wrote the documentation for this code? I'm trying to find the best way to use backbone with a rails app. Could you give me any advice? Thanks!

@trydionel

This comment has been minimized.

Owner

trydionel commented Feb 23, 2011

Hey bernat,

No, there's not a bit of documentation for this -- it's just a snippet I hacked together one weekend. It sounds like you just need to add a name attribute (which should be the key the JSON will be nested under) to your model:
var Widget = Backbone.Model.extend({
name: 'widget'
});

One thing to watch out for: since Backbone.js doesn't provide a create callback, I've had to add a default initializer which actually unwraps the JSON. If you override initialize in your model, you'll need to call this.maybeUnwrap(args) early in the new method.

Jeff

@panupan

This comment has been minimized.

panupan commented Mar 16, 2011

Thanks, just what I needed!

@slash7

This comment has been minimized.

slash7 commented Mar 20, 2011

Thanks!

@dmix

This comment has been minimized.

dmix commented Mar 24, 2011

thanks worked great

@dmix

This comment has been minimized.

dmix commented Mar 24, 2011

this should be moved to a repo so it can be searched/contributed to.

@drewda

This comment has been minimized.

drewda commented Mar 26, 2012

I just tried upgrading to Backbone 0.9.2 and now I'm getting this error: Uncaught TypeError: Cannot call method 'hasOwnProperty' of undefined. Anyone have a fix to suggest?

@thenickcox

This comment has been minimized.

thenickcox commented Feb 27, 2013

@drewda, your comment was 11 months ago, but I ran into this, too. My fix was to give it an || {} when it was asking for args in case args was undefined. Hope that helps anyone who gets here from Google.

@macool

This comment has been minimized.

macool commented Jun 3, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment