Rails 4:带参数

时间:2016-01-22 15:08:42

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

为了大幅减少代码重复,我想用一种通用的方法来编写一个关注点来向控制器添加一个特殊的around_action。它基本上应该捕获任何异常,呈现正确的模板并将异常添加为通知。但是,它必须适用于不同的操作,并根据操作显示不同的模板。我的目标基本上是能够做到这一点:

protect_from_exception_with 'index', only: [ :update ]

为了达到这个目的,我尝试写下这样的问题(使用Rails 4.1):

module CatchException
  extend ActiveSupport::Concern

  module ClassMethods
    def protect_from_exception_with(failure_template, params)
      around_action -> { catch_exception_with(failure_template) }, params
    end
  end

  private

  def log_error(e)
    # Many things happen here
  end

  def catch_exception_with(failure_template)
    yield
  rescue => e
    log_error(e)
    render failure_template
  end
end

但是,这会导致错误:

LocalJumpError: no block given (yield)

我尝试使用参数查找around_actionaround_filter的示例,但只能为before_action找到它们。

我希望我想要实现的目标是可能的,否则我需要在每个控制器中为我实现此目的所需的每个动作编写一个新方法。

1 个答案:

答案 0 :(得分:3)

有一些线索:

  1. around_action收到callbackblock作为参数,如果我们发送function作为第一个参数,则function不得有任何参数!
  2. 我们可以发送一个块(就像你做的那样),但我们必须将当前给定的块传递给该块,你的代码会错过传递块,这就是引发异常的原因。
  3. protect_from_exception_with,我可以致电block_given?,它会返回true,但我不知道如何解决这个问题!
  4. 这有效:

    module CatchException
      extend ActiveSupport::Concern
    
      module ClassMethods
        def protect_from_exception_with(failure_template, params)
          around_action -> { catch_exception_with(failure_template) }, params
        end
      end
    
      private
    
      def log_error(e)
        # Many things happen here
      end
    
      def catch_exception_with(failure_template)
        self.send(params[:action])
      rescue => e
        log_error(e)
        render failure_template
      end
    end
    

    幸运的是,我们仍然在catch_exception_with中设置了参数,让它变得简单,将操作调回控制器!