user938363
user938363

Reputation: 10360

Rails - do action and http verb have to match?

A custom action export_file is defined in routes.rb:

   resource :payment_requests do
      collection do
        get :export_file
      end
   end

In a form_tag, can we use method: put for export_file even though the export_file is a get?

<%= form_tag export_file_payment_requests_path(format: 'csv'), method: :put do %>
   ......
  <%= submit_tag 'CSV' %>
<% end %>

It seems OK to use put method for get action according to http document.

Upvotes: 1

Views: 607

Answers (1)

Jon
Jon

Reputation: 10898

Essentially, yes that's fine - you absolutely can send a PUT request from a form in Rails.

However, if you specify a route in your routes.rb file as being a get request, it will only ever match it using the HTTP GET verb.

Take a look at the output from rake routes:

               Prefix Verb     URI Pattern                                                                  Controller#Action
 api_v1_search_simple GET      /api/v1/search/simple(.:format)                                              api/v1/search#simple
     new_user_session GET      /auth/login(.:format)                                                        devise/sessions#new
         user_session POST     /auth/login(.:format)                                                        devise/sessions#create
 destroy_user_session DELETE   /auth/logout(.:format)                                                       devise/sessions#destroy
        user_password POST     /auth/password(.:format)                                                     devise/passwords#create
    new_user_password GET      /auth/password/new(.:format)                                                 devise/passwords#new
   edit_user_password GET      /auth/password/edit(.:format)                                                devise/passwords#edit
                      PATCH    /auth/password(.:format)                                                     devise/passwords#update
                      PUT      /auth/password(.:format)                                                     devise/passwords#update
    user_confirmation POST     /auth/confirmation(.:format)                                                 devise/confirmations#create
new_user_confirmation GET      /auth/confirmation/new(.:format)                                             devise/confirmations#new
                      GET      /auth/confirmation(.:format)                                                 devise/confirmations#show
                 root GET      /                                                                            dashboards#show

You see how it lists the Verb it will match against?

If you want to send a PUT request and have rails match it against a particular controller and action, then you should specify it as a put request in your routes.rb file.

You do have the option of using the match wildcard to define a route, but that is generally considered a bad thing to do, since it opens up your application for misuse.

This guide is really useful: http://guides.rubyonrails.org/routing.html

If you read section 3.7, you'll see that you can use the match keyword along with the via attribute to restrict what verbs your route should match against. Such as this:

match 'photos', to: 'photos#show', via: [:get, :post]

You could use a route like that to match against both GET and PUT if you need it.

Upvotes: 1

Related Questions