Ruby - 检查控制器是否定义

Ruby - Check if controller defined

我在 Rails 上使用带有 Ruby 的 Solidus 创建网上商城,我有多个模块用于该网上商城。

所以,我使用以下代码将一个 me 控制器定义到一个名为 'solidus_jwt_auth' 的模块中:

module Spree
  module Api
    class MeController < Spree::Api::BaseController
      def index
        ...
      end

      def orders
        ...
      end

      def addresses
        ...
      end
    end
  end
end

我想在另一个名为 'solidus_prescriptions' 的模块中扩展它,因此我使用以下代码为此创建了一个装饰器 me_decorator:

if defined? Spree::Api::MeController.class
  Spree::Api::MeController.class_eval do
    def prescriptions
      ...
    end

    def create_prescription
      ...
    end

    private

    def prescription_params
      params.require(:prescription).permit(
          *Spree::CustomerPrescription.permitted_attributes
      )
    end
  end
end

为此,我在 solidus_prescription 模块中编写了单元测试,在网上商店中编写了集成测试。单元测试工作正常,但集成测试出现以下错误:

错误: 我端点测试#test_me/prescriptions_post_endpoint_throws_an_error_when_wrong_params: AbstractController::ActionNotFound:找不到 Spree::Api::MeController 的操作 'create_prescription' test/integration/me_endpoints_test.rb:68:在`块中'

这意味着他找不到另一个模块中定义的MeController。我该如何检查 MeController 是否已定义,因为下面的代码对我没有任何帮助:

if defined? Spree::Api::MeController.class
end

这最终奏效了:

def class_defined?(klass)
  Object.const_get(klass)
rescue
  false
end

if class_defined? 'Spree::Api::MeController'
 ....
end

if defined? 理论上应该完全符合您的要求。问题是您正在检查 if defined? Spree::Api::MeController.class。你的 class 的 #classClass。所以你真正得到的是 if defined? Class 这永远是真的!

这个问题很可能不是条件失败,而是它永远不会被读取。 Rails 延迟加载您编写的大部分代码,这意味着直到在执行某处调用文件时才会读取文件。

装饰器模块应该只包含您要添加的方法,没有条件或使用 class_eval。那么在原来的class中就可以包含了。

module Spree
  module Api
    class MeController < Spree::Api::BaseController
      include MeDecorator
    end
  end
end

如果出于任何原因您不确定 MeDecorator 是否会被定义,请不要使用 defined?,因为 defined? MeDecorator 如果未定义则不会真正去寻找它并加载必要的文件。如果常量没有值,它将 return nil。就 rescueNameError

module Spree
  module Api
    class MeController < Spree::Api::BaseController
      begin
        include MeDecorator
      rescue NameError => e
        logger.error e
      end
    end
  end
end