-
-
Save trydionel/719080 to your computer and use it in GitHub Desktop.
// | |
// 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); | |
} | |
}); |
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
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
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!