Forceing PUST vs. POST in form

I am experimenting with a combined form. I wish to force the HTTP verb for this form to PUT. However, it always uses POST when submitted and I cannot determine why.

The view template code is:

  <%=form_for( @user,       :html => {         :class => :edit_user_role,         :id => :edit_user_role_form,         :method => :put },       :url => user_roles_url( @user )

        ) do |f|-%>

The resulting html is:

<form accept-charset="UTF-8"   action="http://www.example.com/users/330/roles&quot;   class="edit_user_role"   id="edit_user_role_form" method="post">   <div style="margin:0;padding:0;display:inline">     <input name="utf8" type="hidden" value="&#x2713;" />     <input name="_method" type="hidden" value="put" />   </div>

This confuses me. The form method is not being set by the html attribute but a hidden field is being created instead. Since Rails considers only the HTTP verb for routing this simply will not work as I expect.

What is the problem with my approach? How does one set the form method?

James Byrne wrote in post #972875:

I am experimenting with a combined form. I wish to force the HTTP verb for this form to PUT. However, it always uses POST when submitted and I cannot determine why.

Because that's the way Rails works. Many browsers don't support PUT forms, so Rails leaves the method as POST and adds a hidden field to fake what the method "really" is. Rails does the processing of that hidden field transparently, so that a POST with method "_put" will appear to the framework exactly like a real PUT.

Best,

Marnen Laibow-Koser wrote in post #972876:

James Byrne wrote in post #972875:

I am experimenting with a combined form. I wish to force the HTTP verb for this form to PUT. However, it always uses POST when submitted and I cannot determine why.

Because that's the way Rails works. Many browsers don't support PUT forms, so Rails leaves the method as POST and adds a hidden field to fake what the method "really" is. Rails does the processing of that hidden field transparently, so that a POST with method "_put" will appear to the framework exactly like a real PUT.

Then does that mean one must always provide a route for the new method, even if it makes no sense to do so within a given context?

James Byrne wrote in post #972918:

Marnen Laibow-Koser wrote in post #972876:

James Byrne wrote in post #972875:

I am experimenting with a combined form. I wish to force the HTTP verb for this form to PUT. However, it always uses POST when submitted and I cannot determine why.

Because that's the way Rails works. Many browsers don't support PUT forms, so Rails leaves the method as POST and adds a hidden field to fake what the method "really" is. Rails does the processing of that hidden field transparently, so that a POST with method "_put" will appear to the framework exactly like a real PUT.

Then does that mean one must always provide a route for the new method, even if it makes no sense to do so within a given context?

I don't understand your question.

Best,

Marnen Laibow-Koser wrote in post #972921:

James Byrne wrote in post #972918:

Then does that mean one must always provide a route for the new method, even if it makes no sense to do so within a given context?

I don't understand your question.

I get this error when I submit the form.

no route exists for "/users/1/roles"

However, I get to the form via "/users/1/roles/new" called from "/users/1/role", which is where I want to return to after the update completes. At the moment I am perplexed by this, to me, mysterious behaviour and error message.

In other words, I can start by entering http://localhost:3000/users/1/roles

That URL displays all the roles associated with User.find(1)

From that page I follow a link to http://localhost:3000/users/1/roles/new which displays the input form. When I complete and submit the form I get this error:

No route matches "/users/1/roles"

which is the very URL I have just come from.

James Byrne wrote in post #972930:

Marnen Laibow-Koser wrote in post #972921:

James Byrne wrote in post #972918:

Then does that mean one must always provide a route for the new method, even if it makes no sense to do so within a given context?

I don't understand your question.

I get this error when I submit the form.

no route exists for "/users/1/roles"

Do you have a route defined with method PUT?

However, I get to the form via "/users/1/roles/new" called from "/users/1/role",

What do you mean by that? The previous page is irrelevant -- HTTP is stateless, remember?

So...describe exactly how you get here

which is where I want to return to after the update completes.

*Which* page is where you want to return to?

What does the controller action look like?

At the moment I am perplexed by this, to me, mysterious behaviour and error message.

In other words, I can start by entering http://localhost:3000/users/1/roles

That URL displays all the roles associated with User.find(1)

Right. Standard RESTful nested resources (on GET).

From that page I follow a link to http://localhost:3000/users/1/roles/new which displays the input form. When I complete and submit the form I get this error:

No route matches "/users/1/roles"

which is the very URL I have just come from.

But you came from it as GET, not PUT. Routes include method, not just URL.

What's your rake routes output like for these paths?

Best,

Marnen Laibow-Koser wrote in post #972933:

But you came from it as GET, not PUT. Routes include method, not just URL.

I knew that. Nonetheless that is the bit I had confused. I was trying to override the form method for the right reason but I fixed upon the wrong method, PUT, instead of GET.

Thank you for the help.

James Byrne wrote in post #972938:

Marnen Laibow-Koser wrote in post #972933:

But you came from it as GET, not PUT. Routes include method, not just URL.

I knew that. Nonetheless that is the bit I had confused. I was trying to override the form method for the right reason but I fixed upon the wrong method, PUT, instead of GET.

Thank you for the help.

You probably don't want the form submission to be GET.

Best,

Marnen Laibow-Koser wrote in post #972943:

You probably don't want the form submission to be GET.

You are probably right. But for now I am simply exploring how things work for a nested resource. I will rewire the controller when I figure how what I want each bit to do and how I want it to look.

James Byrne wrote in post #972946:

Marnen Laibow-Koser wrote in post #972943:

You probably don't want the form submission to be GET.

You are probably right. But for now I am simply exploring how things work for a nested resource. I will rewire the controller when I figure how what I want each bit to do and how I want it to look.

No! If you need to make the form submission GET, then something is *badly wrong*. Rails' resource mapping should make the PUT form work by default. If that isn't working, find out why. Perhaps we should take a look at your routes.

Best,

Marnen Laibow-Koser wrote in post #972947:

No! If you need to make the form submission GET, then something is *badly wrong*. Rails' resource mapping should make the PUT form work by default. If that isn't working, find out why. Perhaps we should take a look at your routes.

I believe that I know the source of the problem. I have deliberately created a merged edit/new form and forced the controller to map different methods to specific templates. I do not intend for this to remain. But I am interested in seeing what behaviour results.

James Byrne wrote in post #972959:

No! If you need to make the form submission GET, then something is *badly wrong*. Rails' resource mapping should make the PUT form work by default. If that isn't working, find out why. Perhaps we should take a look at your routes.

I believe that I know the source of the problem. I have deliberately created a merged edit/new form and forced the controller to map different methods to specific templates. I do not intend for this to remain. But I am interested in seeing what behaviour results.

It's common to "merge" the new and edit forms. The body of the form goes into a partial that the two views (new and edit) share. That's the cleanest and most direct way to accomplish what it sounds like you want.

Interestingly, w3.org indicates that there are only two valid HTTP verbs for the form and the submit elements. Those are GET and POST.

James Byrne wrote in post #972964:

Interestingly, w3.org indicates that there are only two valid HTTP verbs for the form and the submit elements. Those are GET and POST.

Exactly. Which is why Rails fakes PUT forms as I explained earlier. It's a POST as far as the browser is concerned, but a PUT as far as Rails is concerned.

Best,

Marnen Laibow-Koser wrote in post #972966:

James Byrne wrote in post #972964:

Interestingly, w3.org indicates that there are only two valid HTTP verbs for the form and the submit elements. Those are GET and POST.

Exactly. Which is why Rails fakes PUT forms as I explained earlier. It's a POST as far as the browser is concerned, but a PUT as far as Rails is concerned.

And, if you really, really want to know how and where that happens, that would be here:

http://guides.rubyonrails.org/v2.3.8/rails_on_rack.html#internal-middleware-stack

Notice: Rack:MethodOveride