Search code examples
ruby-on-railsruby-on-rails-4actioncontroller

Is before_action/filter in application_controller.rb a bad practice?


Consider the following

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  before_filter :maintenance_mode

private

def maintenance_mode
      @settings = Setting.first
      if @settings.maintenance
        if logged_in?
          if !current_user.admin?
            redirect_to maintenance_url
          end
        else
          redirect_to maintenance_url
        end
      end

end

is there a performance issue or bad practice in general to use before_actions globally? So i created a maintenance mode, where if in the database there is a true value on the maintenance attribute(which will be checked on each request i assume), and its likely not the best way, so is there a workaround in that?

I can imagine of a cron job/rake task checking every minute in a background process but what i really want to know is before_action a bad thing in general?


Solution

  • You can skip unnecessary logic and queries by using your session and cache

    class ApplicationController < ActionController::Base
      # Prevent CSRF attacks by raising an exception.
      # For APIs, you may want to use :null_session instead.
      protect_from_forgery with: :exception
    
      before_filter :maintenance_mode
    
      private
      def maintenance_mode
        unless session[:maintainence_mode].present?
          @settings = Rails.cache.fetch { Setting.first }
          session[:maintainence_mode] = @settings.maintenance
        end
    
        if session[:maintainence_mode]
          if logged_in?
            if !current_user.admin?
              redirect_to maintenance_url
            end
          else
            redirect_to maintenance_url
          end
        end
      end
    end
    

    This way you can call before_filter than will most of the times check if the value in session[:maintanence_mode] is set or not instead of performing the query each time.

    You should also use Rails.cache or cookies

    Using rails cache to fetch or get the Setting model

    @settings = Rails.cache.fetch { Setting.first }
    

    or

    using cookies to store value instead of session which gives you support for expiry

    cookies[:_mmode] = { :value => @settings.maintanence,\
      :expires => 1.hour.from_now }