application_controller.rb中的before_action / filter是一个不好的做法吗?

时间:2015-12-07 17:26:49

标签: ruby-on-rails ruby-on-rails-4 actioncontroller

考虑以下

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

在全球范围内使用before_actions是否存在性能问题或不良做法?所以我创建了一个维护模式,如果在数据库中有一个维护属性的真值(将在我假设的每个请求上检查),并且它可能不是最好的方法,那么是否有解决方法呢? / p>

我可以想象一个cron job / rake任务在后台进程中检查每一分钟,但我真正想知道的是before_action一般是坏事吗?

2 个答案:

答案 0 :(得分:2)

我不会认为before_action比其他任何事情更糟糕。您可能需要在某些路由上的其他控制器中实现skip_before_action,并且使用控制器帮助程序进行一些重构可能会避免额外的数据库查找。总的来说,在行动是轨道的主要用途之前,并不是出于性能原因而值得避免的事情。

答案 1 :(得分:1)

您可以使用会话和缓存

跳过不必要的逻辑和查询
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

通过这种方式,您可以拨打before_filter,而不是大部分时间都会检查session[:maintanence_mode]中的值是否设置,而不是每次都执行查询。

您还应该使用Rails.cachecookies

使用rails cache获取或获取Setting模型

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

使用cookies存储值而非session,这样可以支持到期

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