【问题标题】:Is there a way in Rails to skip a before_filter if the request is xhr?如果请求是 xhr,Rails 中有没有办法跳过 before_filter?
【发布时间】:2011-02-25 07:01:31
【问题描述】:

使用以下代码:

class TestsController < ApplicationController
  skip_before_filter :load_something,      # how to skip these only 
                     :load_something_else  # if the request is xhr ?

  def index
    respond_to do |format|
      format.html
      format.js
    end
  end

end

有没有办法在不改变:load_something:load_something_else方法的情况下根据请求是否是javascript调用跳过过滤器?

谢谢!

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    试试这一行来跳过条件过滤:

    skip_before_filter :load_something, :load_something_else,
       :if => proc { request.xhr? }
    

    对于,您还可以使用 lambdas(在参数传递方面具有严格性):

    skip_before_filter :load_something, :load_something_else,
       if: -> { request.xhr? }
    

    或带参数:

    skip_before_filter :load_something, :load_something_else,
       if: ->(arg) { request.xhr? && arg }
    

    【讨论】:

      【解决方案2】:

      过去没有干净的解决方案。假设您无法控制before_filters(或不想更改它们),我会留下skip_before_filter 并添加一个额外的before_filter,如果它是xhr 方法,它只会执行所需的方法。

      类似

      skip_before_filter :load_something,      # how to skip these only 
                         :load_something_else  # if the request is xhr ?
      before_filter :do_loads_if_xhr
      
      def do_loads_if_xhr
        if request.xhr?
          load_something
          load_something_else
        end
      end
      

      here 中描述的方法之所以有效,是因为条件对于应用程序是全局的:条件仅在创建类时才被评估。不是每个请求。

      [更新] 但是,有一种更简洁的方法可以使 skip_before_filter 成为条件。像这样写:

      skip_before_filter :load_something, :load_something_else, :if => proc {|c| request.xhr?}
      

      还请注意,虽然 skip_before_filter 仍然完全受支持,并且没有被弃用,但由于 rails 4 文档似乎更喜欢(相同的)skip_before_action。此外,文档对此完全不清楚,必须在代码中进行验证。

      【讨论】:

        【解决方案3】:

        在我看来,所有这些答案都采取了错误的方法。使用带有条件的skip_before_action 是倒退,并不像将条件添加到before_action 本身那样明确和清晰;所以这是我的建议:

        before_action :require_password_change, unless: -> { request.xhr? }
        

        这样,阅读您的代码的人可以立即清楚此 before_action 在什么条件下运行或不运行,而不必依赖它们在控制器层次结构中某处的此 skip_before_action 中发生。

        【讨论】:

        • 这是我见过的最好的方法
        • 这似乎没有真正记录在案,但这实际上来自 ActiveSupport::Callbacks 类。
        【解决方案4】:

        使用alias_method_chain装饰过滤器,如果请求是xhr,则不会执行。

        def load_something_with_noxhr(*args)
          load_something_without_noxhr(*args) unless request.xhr?
        end
        
        alias_method_chain :load_something, :noxhr
        

        (将load_something 更改为所需的任何内容,_with__without_ 是文字,并且后缀noxhr 必须与您在alias_method_chain 调用中作为第二个参数传递的相同。)

        【讨论】:

        • 看起来alias_method_chain 可能已被弃用/不推荐stackoverflow.com/questions/3689736/…
        • 不是不推荐,但是现在(Ruby 2.1)有 marvellos prepend MyModule 它将您的模块 放在调用链的前面,所以函数在模块实际上可以调用super并调用“包含”类中的同名函数。
        【解决方案5】:

        您编写了过滤器的代码?在这种情况下,您可以在其中编写 if 子句而不使用 skip_before_filter

        def load_something
          unless request.xhr?
            #Code
          end
        end
        

        另一方面,您可以制作自己的过滤器和委托:

        before_filter :my_own_filter
        
        def my_own_filter
          unless request.xhr?
            load_something
            load_something_else
          end
        end
        

        我认为这应该可行。

        【讨论】:

        • 不应该将这些方法 &&'d 放在一起,这样如果前一个返回 false 则其他方法将不会运行并且过滤器链将停止?
        猜你喜欢
        • 1970-01-01
        • 2011-01-24
        • 1970-01-01
        • 2021-06-07
        • 1970-01-01
        • 2011-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多