Created
November 28, 2010 16:47
-
-
Save trydionel/719080 to your computer and use it in GitHub Desktop.
Makes Backbone.js play nicely with default Rails setup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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); | |
} | |
}); |
Thanks, just what I needed!
Thanks!
thanks worked great
this should be moved to a repo so it can be searched/contributed to.
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?
@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.
Check this one: https://gist.github.com/jumski/1128000
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 overrideinitialize
in your model, you'll need to callthis.maybeUnwrap(args)
early in the new method.Jeff