我已经做了一些谷歌搜索,但无济于事。
我的场景是我有一个辅助方法,它采用一些选项,然后通过部分渲染页面上常用的图形元素,通过发送的选项进行调整。这些选项中的大多数具有由助手设置的不同的可覆盖默认值,基于前两个必需参数 - 对象和上下文。
def my_helper(object, context, options = {})
defaults = { ... }
defaults[:foo] = "bar" if object.is_a?(SomeObject)
defaults[:ping] = "pong" if context.eql?(:some_context)
...
render partial: '/path/to/partial', locals: defaults.merge(options)
end
虽然上下文都很好看,但是我决定放弃查看 object 类,并且在可行的情况下使用respond_to?
而不是。我想要避免的是有多个if object.respond_to?(:foo?) && object.foo?
,只使用像if object.respond_to_and_send(:foo?)
这样的东西,如果对象无法响应该方法,它将返回nil。
更新
我忘了提到这是一个Rails 3.2应用程序,这是一个耻辱,因为在Holger Just's answer中提到的Rails 4中更新的try
方法正是我所需要的。
答案 0 :(得分:5)
您可以像这样使用try
:
object.try(:foo?)
它将检查object
是否响应foo?
,如果是,则调用该方法。如果object
未对该方法做出响应,try
将返回nil
。
有关详细信息,请参阅the documentation。
答案 1 :(得分:0)
object.send(:foo) rescue nil
这应该可以解决问题。小心使用这种技术引入细微的错误。 (例如,如果方法调用本身引发错误,您将获得nil并且实际异常将被隐藏)
答案 2 :(得分:0)
您的问题的答案是否。 UPD:object.try(:foo?)
适用于Rails 4,正如 Holger Just 建议的那样。
但是有一些解决方法。其中之一是使用您需要的方法创建一个模块,并使用它扩展您的上下文对象。
module SmartResponder
def respond_to_and_send(method, *args, &block)
public_send(method, *args, &block) if respond_to?(method)
end
end
context = [1,2,3]
context.extend(SmartResponder)
context.respond_to_and_send(:to_s)
# => "[1, 2, 3]"
context.respond_to_and_send(:to_sssss)
# => nil
context.respond_to_and_send(:inject, 100) { |x,y| x+y }
# => 106