Ruby一个衬垫,用于方法undefined或nil

时间:2015-04-03 14:05:11

标签: ruby

我很好奇是否有更短的方法来检查是否在对象上定义了方法,如果是,则检查它是否为零。我试过了:

if !obj.respond_to?(:meth) || obj.meth.nil?

但它看起来很长很难看。

5 个答案:

答案 0 :(得分:3)

快速又脏又简洁:

unless (obj.meth rescue nil)
  ...
end

如果向meth发送obj失败(例如因为方法丢失),则表达式采用值nil

当然,这会隐藏meth中的所有错误。

答案 1 :(得分:3)

正如@Sergio建议的那样,try from ActiveSupport正是您想要的。使用try,您的代码将如下所示:

if obj.try(:meth).nil?
  # obj either lacks :meth or has :meth that returns nil
end

我认为非常简洁易读。

如果您没有使用ActiveSupport,您可以自己快速重新实现简单版try

class Object
  def try(method, *args)
    public_send(method, *args) if respond_to?(method)
  end
end

答案 2 :(得分:2)

如果您使用的是rails,则可以使用.try

[1] pry(main)> h = {}
=> {}
[2] pry(main)> h.try(:foo)
=> nil

答案 3 :(得分:2)

部分是为了让它读得很好,我会这样做:

def has_method?(obj, method)
  obj.methods.include?(method)
end

has_method?(2, :+)            #=> true
has_method?('cat', :upcase)   #=> true
has_method?('cat', :group_by) #=> false
has_method?(Array, :new)      #=> true

所以它会是:

!has_method?(obj, :meth) ||  obj.meth.nil?

或只是:

!obj.methods.include?(:meth) || obj.meth.nil?

或:

!(obj.methods.include?(:meth) && obj.meth != nil)

答案 4 :(得分:1)

使用defined?关键字。

irb(main):066:0> obj = "test" # in this case obj is a string
=> "test"
irb(main):067:0> defined? obj.split
=> "method"
irb(main):068:0> defined? obj.not_a_func
=> nil

defined?

  

定义?表达式测试表达式是否引用任何可识别的内容(文字对象,已初始化的局部变量, 方法名称从当前范围可见 等)。 如果无法解析表达式,则返回值为nil