skip before action in child controller - ruby-on-rails

I have an application controller where I'm handling some authentication
class ApplicationController < ActionController::Base
before_action :prep_data
def prep_data
# code...
# authenticate
end
end
and I have a controller that inherits from this one
class OtherController < ApplicationController
def custom_action_method
end
end
can I skip the before_action hook for the OtherController for a custom action method custom_action_method

I found the answer, this is the syntax
class OtherController < ApplicationController
skip_before_action :prep_data, only: [:custom_action_method]
def custom_action_method
end
end

Related

Use the same `before_action` filter in multiple controllers

In a Rails app, I have a before_action filter that sends a webhook message. Since I have a few controllers that I want the before_action to act on, is there a good way to make it a module and prepend it?
My current logic is:
# first_controller.rb:
before_action :do_something
def do_something
#same logic
end
# second_controller.rb:
before_action :do_something
def do_something
#same logic
end
# third_controller.rb:
before_action :do_something
def do_something
#same logic
end
If your controllers inherit from ApplicationController, You can do the following:
class ApplicationController < ActionController::Base
def do_something
#same logic
end
end
class FirstController < ApplicationController
before_action :do_something
end
class SecondController < ApplicationController
before_action :do_something
end
class ThirdController < ApplicationController
before_action :do_something
end
Or you can make your own parent controller, eg. DoSomethingController
class DoSomethingController < ApplicationController
before_action do_something
def do_something
#same logic
end
end
class FirstController < DoSomethingController
end
class SecondController < DoSomethingController
end
class ThirdController < DoSomethingController
end
Or you can use #code_aks's answer https://stackoverflow.com/a/59846330/8554172 to make a module and include it.
Yes, it is good to use DRY here. If your controllers do have same parent class you can place that method in there. If not it is good practice to move this method to the module and include it with reusing.
You can try below code write the methods in a controller concern. For example:
# app/controllers/concerns/example_concern.rb
module ExampleConcern
extend ActiveSupport::Concern
protected
def before_filter_1
puts "from first before_filter_method"
end
def before_filter_2
puts "from second before_filter_method"
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 :before_filter_1, only: [:action_a, :action_b, :action_c]
before_action :before_filter_2, only: [:action_d, :action_e]
def action_a
end
def action_b
end
def action_c
end
def action_d
end
def action_e
end
end
Hope this will help you. :)

Share some before_filters between controllers

I have two parent controllers, one for an API, one for normal html pages.
class ApplicationController < ActionController::Base
...
end
class ApiController < ActionController::Metal
include AbstractController::Callbacks
...
end
I want to share some before_filter on both controllers. I tried something like this:
class ApplicationController < ActionController::Base
include MyFilters
end
class ApiController < ActionController::Metal
include MyFilters
end
module MyFilters
before_filter :filter1
before_filter :filter2
def filter1
end
def filter2
end
...
end
And also this:
module MyFilters
def self.included(klass)
klass.before_filter :filter1
klass.before_filter :filter2
end
def filter1
end
def filter2
end
...
end
But in both cases I receive:
undefined method `before_filter' for MyFilters:Module
What is the correct way to implement this?
You could use a concern for that:
# app/controllers/concerns/my_filters.rb
module MyFilters
extend ActiveSupport::Concern
included do
before_filter :filter1
before_filter :filter2
end
def filter1
end
def filter1
end
end
Use them through a standard include in your controllers:
class ApplicationController < ActionController::Base
include MyFilters
end
class ApiController < ActionController::Metal
include MyFilters
end

before_action for specific controller

class ApplicationController < ActionController::Base
before_action :test, only: [:index]
def test
ap 'test'
end
end
The above is run before every single index action, be it dogs#index or cats#index or rabbits#index. How should I get it to execute just before cats#index and rabbits#index?
I want to test to be exectuted before actions in many controllers.
You can skip this method:
class ApplicationController < ActionController::Base
before_action :test, only: [:index]
def test
p 'test'
end
end
class DogsController < ApplicationController
skip_before_action :test
end
Just move your call into the controller you want it to run in.
class ApplicationController < ActionController::Base
# nothing here!
def test
# ...
end
end
class CatsController < ApplicationController
before_action :test, only: [:index]
end
class RabbitsController < ApplicationController
before_action :test, only: [:index]
end
It is pretty simple actually
Create before_action in application_controller and check if: that incoming request is for concerned_controller.
class ApplicationController < ActionController::Base
before_create :assign_setting, only: :create, if: :registration_controller?
def registration_controller?
params["controller"] == "registrations"
end
def assign_settings
# your code
puts "settings applied"
end
end

Controller not inheriting before_filter

So I have ApplicationController.rb:
class ApplicationController < ActionController::Base
protect_from_forgery
def decode_email
params[:email] = URI::decode(params[:email])
end
end
and then UsersController.rb:
class UsersController < ApplicationController
before_filter :decode_email, only: [:show]
def show
#blah blah
end
end
Now hitting the show action results in:
undefined local variable or method 'decode_email' for #<UsersController:0x007fb5f216a710>
Why isn't that method being inherited so it can be properly used as a before_filter?
class ApplicationController < ActionController::Base
protect_from_forgery
private
def decode_email
params[:email] = URI::decode(params[:email])
end
end
is working for me

add before_filter method to the end of the list in rails 3

I have before_filter :method in my application_controller and I want this method to run after the before_filter methods in inherit class.
how can I do it?
example
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :run_second
end
class SessionsController < ApplicationController
before_filter :run_first
end
I think the most Rails-friendly way of doing this would be to use prepend_before_filter in your SessionsController:
class SessionsController < ApplicationController
prepend_before_filter :run_first
end

Resources