My back-end has two separate pages, one for handling the model save request and the other for model fetch.
What is the best approach for calling save() and fetch() to use different URLs? Thanks.
Edit: After studying the annotated source, I see that one can actually supply an options
hash to fetch and save
//taken from backbone source: save : function(attrs, options) { options || (options = {}); if (attrs && !this.set(attrs, options)) return false; var model = this; var success = options.success; options.success = function(resp, status, xhr) { if (!model.set(model.parse(resp, xhr), options)) return false; if (success) success(model, resp, xhr); }; options.error = wrapError(options.error, model, options); var method = this.isNew() ? 'create' : 'update'; return (this.sync || Backbone.sync).call(this, method, this, options); },
In the save, what purpose does the attrs
serve? I've just been calling myModel.save() without passing anything in and it's always been hashing my model's attributes correctly. But now that I want to supply a 'save url' and I'm tempted to call
myModel.save(undefined, { url: 'myPath' })
with the undefined required to 'skip' the first attrs
paramter.
If you're reading the source you probably already have a working solution. You essentially have two options (probably more)-
save() takes two parameters attr and options attr - is a hash of model attributes and is used to update the model before save. eg.
myModel.save(attrs)
is equivalent to
myModel.set(attrs) myModel.save()
The second parameter is an options hash, which is passed down to this.sync() (and then Backbone.sync and then $.ajax) - setting the url in this hash will work as expected. You can pass false, undefined, or {} as the first parameter to skip the update.
Rather than have url's scattered throughout your code every time you call save() or fetch() write your own sync function to compute the url for you, the delegate to the original Backbone.sync to do the heavy lifting
eg. (This sync function adds /save to the url on CREATE, UPDATE and DELETE actions)
function mySyncFunction(method, model, options){ if(method=='GET'){ options.url = model.url; }else{ options.url = model.url + '/save'; } return Backbone.sync(method, model, options); }
To use your custom sync method just declare it as part of your model
var myModel = Backbone.Model.extend({ ... "sync": mySyncFunction, ... });
Gingerhendrix's answer covers the bases, but I thought it was worth elaborating on the method for passing in an options value for save
/delete
/fetch
.
Instead of littering your code with urls every place you call one of those methods, you can also override the method on your model than then delegate back to the original Backbone.Model
method like this:
var MyModel = Backbone.Model.extend({ save: function(attributes, options) { options = _.defaults((options || {}), {url: "http://your.save.url.com/"}); return Backbone.Model.prototype.save.call(this, attributes, options); }, // same thing for fetch and delete to give them different urls... }
Then, you can call the method in your code without having to worry about remembering to set the url
in the options.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With