一个ruby方法怎么可能不是repond_to一个方法还要调用这个方法呢?
How can a ruby method not repond_to a method but also call the method?
我正在使用一种小方法来检查租户是否启用了某项功能。每个租户都有一个存储标志的 TenantPlan。我在租户模型上也有一些标志,可用于覆盖特定于计划的标志。一个小的特征检测方法在租户模型上看起来像这样:
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))
我正在检查租户模型中是否存在同名字段,如果存在则获取结果。
如果我使用控制台查看:
[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/ruby-2.2.4@doki/gems/activemodel-4.2.7.1/lib/active_model/attribute_methods.rb:433:in `method_missing'
如果 Tenant 没有 respond_to?
功能方法,我希望 send
甚至不会被调用,这看起来像是在控制台测试中发生的事情,但我发现我的测试表明,即使 respond_to?
returns 为假,也会调用发送但不会引发 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>
我很茫然
在这种情况下,ruby 是否会在调用方法时吞下 NoMethodError
异常,因为表达式的第一部分 returns false?希望得到解释并很高兴听到任何关于重写的建议。
在我看来,它就像是 ActiveModel 的 RSpec 错误。当我不添加期望时,当我 运行 在开发中编写代码时,它会按预期运行。
我想我是在 运行 研究了各种图书馆之后才明白这一点的。 Tenant
没有定义名为 payment_options_features?
的方法,所以当我进入控制台并执行以下操作时:
tenant.respond_to?(:payment_options_features?) # false
但是,我相信我的预期是租户不应在我的 RSpec 测试中收到该方法...
expect(tenant).not_to receive(:payment_options_features?)
实际上在租户对象上创建该函数的模拟,因此当测试运行时:
tenant.respond_to?(:payment_options_features?) # true
因为它是 "mocked"。另一种方法是这样做,因为我们知道 send
是一种应该始终存在的方法。
expect(tenant).not_to receive(:send).with('payment_options_features?')
我正在使用一种小方法来检查租户是否启用了某项功能。每个租户都有一个存储标志的 TenantPlan。我在租户模型上也有一些标志,可用于覆盖特定于计划的标志。一个小的特征检测方法在租户模型上看起来像这样:
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))
我正在检查租户模型中是否存在同名字段,如果存在则获取结果。
如果我使用控制台查看:
[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/ruby-2.2.4@doki/gems/activemodel-4.2.7.1/lib/active_model/attribute_methods.rb:433:in `method_missing'
如果 Tenant 没有 respond_to?
功能方法,我希望 send
甚至不会被调用,这看起来像是在控制台测试中发生的事情,但我发现我的测试表明,即使 respond_to?
returns 为假,也会调用发送但不会引发 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>
我很茫然
在这种情况下,ruby 是否会在调用方法时吞下 NoMethodError
异常,因为表达式的第一部分 returns false?希望得到解释并很高兴听到任何关于重写的建议。
在我看来,它就像是 ActiveModel 的 RSpec 错误。当我不添加期望时,当我 运行 在开发中编写代码时,它会按预期运行。
我想我是在 运行 研究了各种图书馆之后才明白这一点的。 Tenant
没有定义名为 payment_options_features?
的方法,所以当我进入控制台并执行以下操作时:
tenant.respond_to?(:payment_options_features?) # false
但是,我相信我的预期是租户不应在我的 RSpec 测试中收到该方法...
expect(tenant).not_to receive(:payment_options_features?)
实际上在租户对象上创建该函数的模拟,因此当测试运行时:
tenant.respond_to?(:payment_options_features?) # true
因为它是 "mocked"。另一种方法是这样做,因为我们知道 send
是一种应该始终存在的方法。
expect(tenant).not_to receive(:send).with('payment_options_features?')