In backbone.js I'm updating a category model:
@category.save {
name : category_name,
}
This saves fine and updates the collection properly in backbone. But on the rails serverside its not saving because of a routing error:
Started PUT "/categories" for 127.0.0.1 at 2011-05-24 11:18:16 -0400
ActionController::RoutingError (No route matches "/categories"):
The problem is that rails expects PUT/update to have a url including the id "/categories/:id", not just "/categories"
I tested this out by changing the model url from:
class Category extends Backbone.Model
name: 'category'
url: ->
host + '/categories'
to
class Category extends Backbone.Model
name: 'category'
url: ->
host + '/categories/2'
This works fine.
Started PUT "/categories/2" for 127.0.0.1 at 2011-05-24 11:44:08 -0400
Processing by CategoriesController#update as JSON
Parameters: {"category"=>{"created_at"=>2010-03-14 16:30:07 -0400, "id"=>2, "name"=>"Lunchr5", "updated_at"=>2010-03-14 16:30:07 -0400, "user_id"=>1}, "api_key"=>"s1boakDIav30V6DzOFsY", "id"=>"2"}
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`single_access_token` = 's1boakDIav30V6DzOFsY' LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
SQL (0.1ms) BEGIN
AREL (0.3ms) UPDATE `users` SET `visit_count` = 11, `perishable_token` = 'YG3s4yB01FxUMdMcK8m', `updated_at` = '2011-05-24 15:44:08' WHERE `users`.`id` = 1
SQL (0.3ms) COMMIT
Option Load (0.3ms) SELECT `options`.* FROM `options` WHERE (`options`.user_id = 1) LIMIT 1
Category Load (0.2ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = 2 LIMIT 1
SQL (0.1ms) BEGIN
Category Load (13.1ms) SELECT `categories`.`id` FROM `categories` WHERE `categories`.`user_id` = 1 AND (`categories`.`name` = BINARY 'Lunchr5') AND (`categories`.id <> 2) LIMIT 1
AREL (0.3ms) UPDATE `categories` SET `name` = 'Lunchr5', `updated_at` = '2011-05-24 15:44:09' WHERE `categories`.`id` = 2
SQL (0.3ms) COMMIT
Redirected to http://localhost:3000/categories
Completed 302 Found in 179ms
Do I have to hack backbone to add the :id to the url or am I missing something?
Backbone will determine the url to use from the result of Model.url(). So if you have
class Category extends Backbone.Model
name: 'category'
url: ->
host + '/categories'
The url backbone's save method will try on the server will be: host+'/categories'
If you do not define a url function, the default behaviour for the url function will delegate to the collection that it is in. So if you have a collection
class Categories extends Backbone.Collection
model:Category
url: ->
host + '/categories'
class Category extends Backbone.Model
name: 'category'
and instance of Category that belongs to a Categories collection will automatically get use the url host+'/categories'+'/'+category.id to save to the server.
Now if your model is not part of a collection, then you can't do this. You have to override the url function in your model so something like this
class Category extends Backbone.Model
name: 'category'
url: ->
u = "#{host}/categories/"
u = "#{u}#{this.id}" if this.id
u
Note that this is not hacking. This is using backbone correctly. In fact in future editions of backbone, I believe there will be no default behaviour of the url function, and the url function will have to be written for all Models.
When using a model outside of a collection, provide a url root:
class Category extends Backbone.Model
urlRoot: '/categories'
http://backbonejs.org/#Model-urlRoot
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