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 的 #class
是 Class
。所以你真正得到的是 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
。就 rescue
个 NameError
module Spree
module Api
class MeController < Spree::Api::BaseController
begin
include MeDecorator
rescue NameError => e
logger.error e
end
end
end
end
我在 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 的 #class
是 Class
。所以你真正得到的是 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
。就 rescue
个 NameError
module Spree
module Api
class MeController < Spree::Api::BaseController
begin
include MeDecorator
rescue NameError => e
logger.error e
end
end
end
end