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"
  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