Kevin Pang
Kevin Pang

Reputation: 41442

How to handle multiple HTTP methods in the same Rails controller action

Let's say I want to support both GET and POST methods on the same URL. How would I go about handling that in a rails controller action?

Upvotes: 43

Views: 27991

Answers (6)

PedroProgrammer
PedroProgrammer

Reputation: 35

This works for me:

In routes.rb

Rails.application.routes.draw do
  post '/posts', to: 'posts#create'
  get '/posts', to: 'posts#list_all'
end

In posts_controller.rb

class PostsController < ApplicationController
    def create
        new_post = Post.create( content: params[:content], user_id: params[:user_id] )
        render json: { post: new_post }
    end

    def list_all
        request = Post.all
        render json: { all_posts: request }
    end
end

So each action is referred to a different function

Upvotes: 0

Ngoral
Ngoral

Reputation: 4814

I would say, the best way is to create separate actions in the controller and state them in routes.

# config/routes.rb
...
get '/my_action' => 'my#my_action_get'
post '/my_action' => 'my#my_action_post'
...

# app/controllers/my_controller.rb
...
def my_action_get
  # do stuff like listing smth
end

def my_action_post
  # do other stuff
end

In fact, the same logic is used by Rails by default: index and create actions are both called by requests sent to the same paths (e.g. /articles), however, they have different request methods: GET /articles request is redirected to the index action and lists all articles, and POST /articles is redirected to the create action and creates a new article.

Upvotes: 1

jamesdelacruz
jamesdelacruz

Reputation: 217

you can try this

match '/posts/multiple_action', to: 'posts#multiple_action', via: [:create, :patch, :get, :options]

Upvotes: 3

jacr1614
jacr1614

Reputation: 1310

Just need to use this, to use only get and post in the same route

resources :articles do
  member do
    match 'action_do-you_want', via: [:get, :post]
  end
end

Upvotes: 8

Dennis
Dennis

Reputation: 59529

Here's another way. I included example code for responding with 405 for unsupported methods and showing supported methods when the OPTIONS method is used on the URL.

In app/controllers/foo/bar_controller.rb

before_action :verify_request_type

def my_action
  case request.method_symbol
  when :get
    ...
  when :post
    ...
  when :patch
    ...
  when :options
    # Header will contain a comma-separated list of methods that are supported for the resource.
    headers['Access-Control-Allow-Methods'] = allowed_methods.map { |sym| sym.to_s.upcase }.join(', ')
    head :ok
  end
end

private

def verify_request_type
  unless allowed_methods.include?(request.method_symbol)
    head :method_not_allowed # 405
  end
end

def allowed_methods
  %i(get post patch options)
end

In config/routes.rb

match '/foo/bar', to: 'foo/bar#my_action', via: :all

Upvotes: 9

Jesse Wolgamott
Jesse Wolgamott

Reputation: 40277

You can check if it was a post using request.post?

if request.post?
  #handle posts
else
  #handle gets
end

To get your routes to work:

resources :photos do
  member do
    get 'preview'
    post 'preview'
  end
end

Upvotes: 74

Related Questions