6

So, I have this form declaration:

<%= form_for 'students_list', {:url => update_students_list_stream_url(@stream), :method=>:patch}  do |students_list_form| %>

Just as described in API docs, but this leads me to error:

No route matches [POST] "/streams/26/edit-students-list"

So it still tries to post, even though my HTML input has:

<input type="hidden" name="_method" value="patch" />

From Rails guide:

Rails works around this issue by emulating other methods over POST with a hidden input named "_method", which is set to reflect the desired method:

I'm quite confused

Joe Half Face
  • 2,303
  • 1
  • 17
  • 45
  • If I get you right, you are trying to make an update to the student list stream, is this correct? – x6iae Dec 13 '15 at 02:40
  • Rails uses the [`Rack::MethodOverride` middleware](https://github.com/rack/rack/blob/857641dab255dbec490fead1d3a0f1ff999b2137/lib/rack/method_override.rb) which processes the request before it is passed to the routes. `Rack::MethodOverride` should be picking up on the `_method` param and i'm also a bit puzzled on why its not working. I would suggest trying to send the request with cURL or Postman to troubleshoot as you are eliminating any browser related bugs or anything related to the form. – max Dec 13 '15 at 05:16
  • Note that the Rails unobtrustive javascript driver also does some trickery to send native PATCH/PUT/DELETE requests and this could also be part of the problem. – max Dec 13 '15 at 05:18

3 Answers3

5

I was looking for an answer on why rails loaded method patch as post in the rendered form. If you ended up here looking for that like I did, this is the answer you are looking for:

https://stackoverflow.com/a/46699512/5750078

From https://guides.rubyonrails.org/form_helpers.html#how-do-forms-with-patch-put-or-delete-methods-work-questionmark:

enter image description here

Alvaro Rodriguez Scelza
  • 3,643
  • 2
  • 32
  • 47
3

Rails use Rack::MethodOverride middleware that tweaks the HTTP methods PUT/PATCH to POST for supporting old browsers.

This can happen on Rails API application to unload the middleware for performance. In some cases where you want to call a casual PUT/PATCH request using form_with tag in the views, simply add

# config/application.rb

config.middleware.insert_after Rack::Runtime, Rack::MethodOverride
Dat Le Tien
  • 1,880
  • 1
  • 9
  • 12
1

You'll be better doing this:

<%= form_for @stream do |student_form_list| %>

If you've set up your routes using the standard resources directive, you'll have the following routes:

enter image description here

Of these routes, the update path should just be students_list_stream_path -- not the update_students_list_stream_path you have now.

If you've set up the form_for to use the correct object, it will automatically set the path & method for update.

Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • 2
    I found out, that :method declaration for some reason doesn't work (except post and get), if you form builder have any hidden field. When I removed `students_list_form.hidden_field`, it started working and sends PATCH request. Not sure if it's some Rails bug or what to do if I need hidden field. – Joe Half Face Dec 13 '15 at 12:53