Nimo
Nimo

Reputation: 8294

Multiple before_action's in Rails controller?

I have two methods that I wish to run in several controller actions.

  def get_offer
    @offer = Offer.find_by :uuid => params[:offer_id]
    if @offer.blank?
      error_response = ErrorResponse.new("Offer not found")
      render json: error_response, :status => :not_found and return
    end
  end

  def validate_api_v2
    api_version = params[:api_version]
    if api_version != api_version_to_validate
      error_response = ErrorResponse.new("API version not supported")
      render json: error_response, :status => :bad_request and return
    end
  end

How can I run both of them in actions action_a, action_b , only one in action_c and action_d, and none of them in action_e?

Upvotes: 4

Views: 7221

Answers (5)

IngoAlbers
IngoAlbers

Reputation: 5802

You could probably do it like this:

before_action :get_offer, only: [:action_a, :action_b, :action_c]
before_action :validate_api_v2, only: [:action_a, :action_b, :action_d]

Edit: colons were missing for the second line only and action_id

Upvotes: 4

sufinsha
sufinsha

Reputation: 765

write the methods in a controller concern. For example:

# app/controllers/concerns/example_concern.rb
module ExampleConcern
 extend ActiveSupport::Concern

 protected
 def get_offer
   @offer = Offer.find_by :uuid => params[:offer_id]
   if @offer.blank?
     error_response = ErrorResponse.new("Offer not found")
     render json: error_response, :status => :not_found and return
   end
 end

 def validate_api_v2
   api_version = params[:api_version]
   if api_version != api_version_to_validate
     error_response = ErrorResponse.new("API version not supported")
     render json: error_response, :status => :bad_request and return
   end
 end
end

Now in the controller, include the module in the concern and call the methods using before_action as required. For example:

# app/controllers/examples_controller.rb
class ExamplesController < ApplicationController
  include ExampleConcern

  before_action :get_offer, only: [:action_a, :action_b, :action_c]
  before_action :validate_api_v2, only: [:action_a, :action_b, :action_d]

  def action_a
  end
  def action_b
  end
  def action_c
  end
  def action_d
  end
  def action_e
  end
end

Upvotes: 1

Prashant4224
Prashant4224

Reputation: 1601

Try this one

 before_filter :action_a, :action_b, only: [:action_c, :action_d]

Upvotes: 3

webster
webster

Reputation: 4032

except comes in handy for some cases:

before_action :get_offer, only: [:action_a, :action_b, :action_c]
before_action :validate_api_v2, except: [:action_e, :action_c] 

Upvotes: 0

Surya
Surya

Reputation: 16002

Move get_offer and validate_api_v2 to ApplicationController and then in rest of your controllers, for example you can do:

class SomeController < ApplicationController
  before_filter :get_offer, :validate_api_v2, :only => [:action_a, :action_b]
end

and:

class SomeOtherController < ApplicationController
  before_filter :get_offer, :only => [:action_c, :action_d, :action_e]
  before_filter ::validate_api_v2, :only => [:action_c, :action_d]
end

I hope you get the point.

Upvotes: 1

Related Questions