从 Rails 3 到 4 了解 Pundit 的 moneky 补丁实现

Understanding moneky patched implementation of Pundit from Rails 3 to 4

作为我一直在做的迁移工作的一部分,我遇到了 pundit 的猴子补丁初始化。我大部分都理解它,但有一部分导致我出错:

module Pundit

  class << self
    def authorize; raise 'DoNotUseThisMethod'; end
    def authorize!; raise 'DoNotUseThisMethod'; end
  end

  included do
    if respond_to?(:rescue_from)
      rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
    end

    if respond_to?(:helper_method)
      helper_method :authorize
      helper_method :can?
    end
  end

  protected

  ... 
  # authorize, authorize! and other methods defined

启动服务器时出错:

/.rvm/gems/ruby-2.3.3/gems/activesupport-4.2.11.3/lib/active_support/concern.rb:126:in `included': Cannot define multiple 'included' blocks for a Concern (ActiveSupport::Concern::MultipleIncludedBlocks)

我尝试将此模块移动到 concerns 文件夹,但如果这样做,authorize 方法不会被调用。

我在 ApplicationController 中包含的 Pundit 模块。

有什么想法吗?我知道我以前遇到过这个错误,我什至在这里描述过,但这次我没有像其他文件那样命名空间。

我不确定这个 monkeypatch 真正应该完成什么。但是避免错误的一种方法是不使用 ActiveSupport::Concern#included。相反,只需使用它抽象出来的实际 Ruby 钩子 (Module#included):

module Pundit

  class << self
    def authorize; raise 'DoNotUseThisMethod'; end
    def authorize!; raise 'DoNotUseThisMethod'; end

    def self.included(base)
      base.class_eval do
        if respond_to?(:rescue_from)
          rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
        end

        if respond_to?(:helper_method)
          helper_method :authorize
          helper_method :can?
        end
     end
    end
  end
end