views:

63

answers:

2

Rails is supposed to magically see that a request is a "DELETE" versus "GET" request, right?

I can hit http://localhost/controller/destroy/1 and it'll delete the record. How do developers typically prevent such silly deleting?

+3  A: 

There's a bit of an underlying problem here.

The HTML specification provides no way for to spawn a PUT or DELETE request. In Rails and most other RESTful web applications, PUT and DELETE requests are forged via a Javascript onclick property. So it's useful to have around to handle destroy requests from browsers without Javascript enabled. The forgery happens by submitting a hidden form on the DELETE method to the resource. This form contains the authenticity token for your application.

Secondly, I believe that this behaviour is coming from the default routes. Using RESTful resources in rails with map.resource(s) in your routes.rb file. should not generate that route. You may notice that /controller/destroy/:id is not listed by rake routes, but it does fit the :controller/:action/:id form of the default route. You'll find that commenting out the default routes will block your undesired behaviour. If you're taking care to define all the resources and routes that will be used this shouldn't be a problem.

If you don't want to remove the default route entirely, you can add a requirement to the so that destroy or any other harmful action are not matched.

map.connect ':controller/:action/:id', 
  :requirements => {:action => /^(?!destroy$)/}
map.connect ':controller/:action/:id.format',
  :requirements => {:action => /^(?!destroy$)/} 
EmFi
+7  A: 

It's good practice to remove the following generated routes from the bottom of your routes file:

map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'

As these can leave doors open to guessable, destructive actions like destroy. I try to be explicit about which routes are allowed by using named routes and map.resources

Andrew Nesbitt