What is the purpose of using :method => delete in button_to?

Viewed 1108

It is my understanding that the HTTP verb 'DELETE' is not supported in HTML, and as such a different route is required when making delete forms.

If this is the case, why does this code works fine,

<%=button_to 'Delete', {:controller => :users, :action => 'destroy', :id => user.id}, :method => :delete%>

but, following code doesn't work

<%=button_to 'Delete', {:controller => :users, :action => 'destroy', :id => user.id}%>

and it gives the error: 'No route matches [POST] "users/1/"'

shouldn't the url this resolves to be users/destroy/1 ?

4 Answers

The older versions of HTML supports only GET and POST. The newer version includes PUT, PATCH, and DELETE which are treated as XHR(XMLHttpRequest) requests or simply AJAX requests by all major web browsers.

When the requests for PUT or PATCH or DELETE are made, Rails under the hood, with the help of Javascript processes these requests as XHR requests to the client. When the Javascript in your application is not working or disabled, these requests will fall back to GET

Now coming back to your code snippet which is not working. You have the below

<%= button_to 'Delete', {:controller => :users, :action => 'destroy', :id => user.id}%>

button_to by default creates a form and sends the request as POST, unless if you are explicitly overriding it, as you are doing in the first case with :method => :delete. So the above code snippet generates a url like users/1/, but as a POST which eventually fails as you don't have any such route defined in the routes.rb

Shouldn't the url this resolves to be users/destroy/1 ?

No, when you use :method => :delete in your code, the url that is generated will be users/1 but the request is sent as DELETE, which eventually works as it is a valid request according to your routes that are defined in routes.rb

It is rails convention to mention the method (HTTP verb) with the link, so that Rails knows which controller method to call, because without the HTTP verb 3 actions show, update and destroy, all of these 3 generate the same url path that is "/users/:id" (if controller is "UsersController"). For further reading, I suggest to have a look at:

https://guides.rubyonrails.org/routing.html#crud-verbs-and-actions

EDIT:

As you can see in the screenshot, if you set the HTTP Verb to DELETE, Rails will automatically know that it has to run the destroy action, otherwise, the path for show,update and destroy is same.

enter image description here

Putting :method=>:delete signals Rails to create the form with hidden values that it will then use to emulate the function of a form with

method="delete"

If anyone would be able to explain why removing :action => :destroy causes :id => user.id to be treated as a key and value in the url (i.e. users?id=1 instead of users/1 ) I'd be grateful.

Related