【问题标题】:Rails and before_action with different conditionals具有不同条件的 Rails 和 before_action
【发布时间】:2021-05-26 17:01:26
【问题描述】:

我在控制器中设置了这些before_actions:

before_action :require_user, unless: :public?, only: [:show]
before_action :require_user, only: [:index, :edit, :update]

基本上我只是在public? 为假时尝试在show 操作中执行过滤器required_front_user

对于其余的操作,我希望始终执行过滤器。

看起来第一个 before_action 设置被忽略并完全被第二个设置覆盖。

是否可以使用before_action 语句组合这两种组合,还是我必须在过滤器中实现这个逻辑?

更新

这也行不通:

before_action :require_user, if: :public?, only: [:index, :edit, :update]
before_action :require_user, unless: :public?, only: [:show, :index, :edit, :update]

我想如果public? 返回true 将加载第一个设置,如果false 将加载第二个设置。碰巧只加载了第二个设置,如果public? == true 永远不会触发before_action

更新 2

这是我发现它的工作原理:

before_action :require_user_when_public, if: :public?, only: [:index, :edit, :update]
before_action :require_user_when_no_public, unless: :public?, only: [:show, :index, :edit, :update]

protected

def require_user_when_public
  require_user
end

def require_user_when_no_public
  require_user
end

这很丑:/

【问题讨论】:

    标签: ruby controller ruby-on-rails-6


    【解决方案1】:
    before_action :require_user, only: require_user_before_actions
    
    private
    
    def require_user_before_actions
     actions = [:index, :edit, :update]
     actions << :show unless public?
     actions
    end
    

    【讨论】:

    • 好主意,我试过了,但我得到了这个错误 undefined local variable or method require_user_before_actions'. It has sense du the before_action is called in class loading time and the method has to be defined as instance class. I tried variants: only: -> { require_user_before_actions }` 或 only: :require_user_before_actions 但方法 require_user_before_actions 从未被调用,@ 987654326@从未被执行
    【解决方案2】:

    我发现的最干净的方法是:

    before_action :require_user, only: [:index, :edit, :update]
    before_action :require_user_when_no_public, unless: :public?, only: [:show]
    
    protected 
    
    def require_user_when_no_public
      require_user
    end
    

    【讨论】:

    • (第 1 部分)我认为这个答案可能存在问题。您可以有一个回调,您希望每个请求只运行一次;例如,检查登录方法可能会在多次登录尝试失败后锁定用户帐户;如果登录方法由于某种原因运行了两次,那么用户的尝试可能会有效地减半。
    • (第 2 部分)如果上述是一个真正的问题,那么任何时候您将回调添加到队列中不止一次,您需要确保回调的每个条件都是互斥的,否则您可能有一些难以检测和调试的问题。
    • (第 3 部分)这对我来说似乎是一个很大的维护负担,让我想知道在 Rails 中无法两次添加相同的回调是否是预期行为。
    • @BenStephens 您的所有顾虑都可能是对的,但在我看来,这是一种更具可读性、可维护性和可调试性的解决方案,所以我接受这个作为答案,直到我看不到那里是在其他答案中有一些赞成票还是出现了一个新答案
    【解决方案3】:

    我只测试了一点点,所以不确定它是否会起作用,但可能是这样的:

    before_action :require_user, if: ->(c) {
      [:index, :edit, :update, !public? && :show].include?(c.action_name.to_sym)
    }
    

    作为一个可能愚蠢/损坏的(据我所知,这似乎对我来说在基本测试中起作用)替代方案,可能类似于:

    class <<self
      alias_method :old_before_action, :before_action
    end
    
    def self.before_action(*callbacks)
      options = callbacks.extract_options!
      if options[:only] && options[:only].is_a?(Proc)
        only_proc = options.delete(:only)
        if_proc = ->(c) { Array(only_proc.(c)).reject(&:blank?).map(&:to_s).to_set.include? c.action_name }
        options[:if] = Array(options[:if]).unshift(if_proc)
      end
      old_before_action(*callbacks, options)
    end
    
    before_action :require_user, only: ->(c) { [:index, :edit, :update, !public? && :show] }
    

    【讨论】:

      猜你喜欢
      • 2018-01-28
      • 1970-01-01
      • 1970-01-01
      • 2016-02-04
      • 1970-01-01
      • 1970-01-01
      • 2013-05-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多