Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PUT or PATCH `_method` param not working or not being respected in rails-api

TLDR:

Using rails --api, expected rails to route as PUT method from POST and params[:_method]='put', but is routing as POST

Given:

  • rails 4.2.8
  • rails-api 0.4.1

Consider the following:

config/routes.rb:

resources :sessions, do
  put 'authenticate', on: :collection
end

some client HTML file:

<form action='http://localhost:3000/sessions/authenticate' method='post'>
  <input type='hidden' name='_method' value='put'>
  ...
</form>

...upon form submit:

rails server output:

Started POST "/sessions/authenticate" for ::1 at 2018-03-07 11:20:21 +0000
No route matches [POST] "/sessions/authenticate" excluded from capture: DSN not set

ActionController::RoutingError (No route matches [POST] "/sessions/authenticate"):
  actionpack (4.2.8) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
  actionpack (4.2.8) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
  ...

Inspecting Chrome -> Developer Tools -> Network tab -> [REQUEST], the payload is correct as shown below:

General
Request URL:http://localhost:3000/sessions/authenticate
...

FormData
_method:put
...

Troubleshooting

  • I tried copying the exact code in a new rails project, but this time not using the --api mode, and the request worked: that it recognised the _method='PUT' and route as a PUT properly. So, I have a feeling that this just got to do with some differences between normal rails and the api mode. Unfortunately, after several searches I couldn't find any solution.

Any help would be appreciated.

like image 876
Jay-Ar Polidario Avatar asked Sep 18 '25 11:09

Jay-Ar Polidario


1 Answers

Handling of _method hidden fields is done by a piece of rack middleware.

http://guides.rubyonrails.org/configuring.html#configuring-middleware

Rack::MethodOverride allows the method to be overridden if params[:_method] is set. This is the middleware which supports the PATCH, PUT, and DELETE HTTP method types.

I'm guessing you don't have that in api mode. Add it and the request should be routed correctly.

Bonus track

I didn't know this myself (or forgot a long time ago). Here's how I found out.

  1. Go to https://github.com/rails/rails and try to search that repo for :_method (as this is likely how rails would address the field). After two minutes realize that github doesn't search the exact term.
  2. Clone rails repo locally (5 mins)
  3. Grep the local codebase (0.5 seconds)

    sergio@soviet-russia ‹ master › : ~/projects/github/rails
    [0] % ag ":_method"
    guides/source/rails_on_rack.md
    238:* Allows the method to be overridden if `params[:_method]` is set. This is the middleware which supports the PUT and DELETE HTTP method types.
    
    guides/source/configuring.md
    235:* `Rack::MethodOverride` allows the method to be overridden if `params[:_method]` is set. This is the middleware which supports the PATCH, PUT, and DELETE HTTP method types.
    

Total time taken: ~7 minutes. Rails itself actually didn't contain actual relevant code, but it had the docs. I got lucky. :)

like image 83
Sergio Tulentsev Avatar answered Sep 20 '25 03:09

Sergio Tulentsev