Ruby - 检查控制器是否已定义

时间:2017-08-01 11:26:20

标签: ruby-on-rails ruby solidus

我正在使用Solidus和Ruby on Rails创建一个网上商店,我为该网店提供了多个模块。

所以,我将一个控制器定义为一个名为'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模块和网上商店的集成测试中编写了单元测试。单元测试工作正常,但集成测试给出以下错误:

错误: MeEndpointsTest#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:在'block in'中

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

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

2 个答案:

答案 0 :(得分:0)

这最终有效:

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

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

答案 1 :(得分:0)

if defined?应该完全按照理论要求做。问题是你正在检查if defined? Spree::Api::MeController.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如果未定义并加载nil实际上不会查找它必要的文件。如果常量没有值,它将返回rescue。只需NameError一个module Spree module Api class MeController < Spree::Api::BaseController begin include MeDecorator rescue NameError => e logger.error e end end end end

<Mvx.MvxAutoCompleteTextView
     android:id="@+id/actSignal"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_margin="5dp"
     android:completionThreshold="1"
     local:MvxItemTemplate="@layout/searchitemview"
     local:MvxBind="ItemsSource Items; PartialText ItemSearchTerm; SelectedObject Item;" />