我正在使用一个小方法来检查租户是否启用了功能。每个租户都有一个TenantPlan存储标志。 Tenant模型上还有一些标志可用于覆盖特定于计划的标志。一个小功能检测方法是这样的租户模型:ruby方法如何不能repond_方法,而是调用方法?
def has_feature?(feature, feature_default = false)
if tenant_plan
feature = "#{feature}_enabled?".to_sym
return tenant_plan.send(feature) || (respond_to?(feature) and send(feature))
end
feature_default
end
我对这个问题最感兴趣的部分是这样的:
(respond_to?(feature) and send(feature))
我检查,如果的一个领域Tenant模型中存在相同的名称,如果存在,则会得到相同的名称。
如果我使用控制台来检查了这一点:
[1] pry(main)> false and tenant.send(:free_courses_enabled?)
=> false
[2] pry(main)> true and tenant.send(:free_courses_enabled?)
NoMethodError: undefined method `free_courses_enabled?' for #<Tenant:0x007f8f7171d6c8>
from /Users/typeoneerror/.rvm/gems/[email protected]/gems/activemodel-4.2.7.1/lib/active_model/attribute_methods.rb:433:in `method_missing'
我期望send
到甚至没有被调用,如果承租人没有respond_to?
的功能方法,它是什么样子的控制台测试正在发生,但我在测试中发现,即使respond_to?
返回false,发送也会被调用,但不会引发NoMethodError
。
expect(tenant).not_to receive(:free_courses_enabled?)
结果:
expected no Exception, got #<RSpec::Mocks::MockExpectationError: (#<Tenant:0x007fdfd908a2a8>).free_courses_enabled?(no args)
expected: 0 times with any arguments
received: 1 time> with backtrace:
有点欢快的,当我想到正好相反:
expect(tenant).to receive(:free_courses_enabled?).and_call_original
我们得到
NoMethodError:
undefined method `free_courses_enabled?' for #<Tenant:0x007f8254bfedd8>
我不知所措。
在这种情况下,由于表达式的第一部分返回false,在调用该方法时,ruby是否会吞下NoMethodError
异常?希望得到解释,并乐意听取关于重写的任何建议。
它在我看来像一个与ActiveModel的RSpec错误。当我不添加期望,并且在开发中运行代码时,它会按预期行事。
因此,在这一点上,我会仔细检查所有小的基本假设......即使您知道它们应该保留。在您的控制台中...你可以试试'tenant.respond_to?(:free_courses_enabled?)'也可以尝试'tenant.respond_to?(“free_courses_enabled?”)'(你知道你可以使用一个字符串,你不需要to_sym吧?) 'has_feature?'方法我会尝试* not * to_symming它...我也会尝试不要重载变量名称'feature'(万一它是一些奇怪的范围错误)例如:'feature_method =“#{feature} _enabled?''和'respond_to?(feature_method)&& send(feature_method)' –
也尝试'puts“我是否回应方法:#{feature_method.inspect}?#{respond_to?(feature_method)}''检查你'重新尝试你认为你正在尝试,并得到你认为你的回应... –
但终于...是的... ruby定义了“respond_to?”设置与方法集略有不同如果你尝试向他们发送'',实际上不会发生爆炸......所以你有可能得到不同的结果(大多数情况下,如果你使用'method_missing'定义方法) –