Ruby检查常量是否为类

时间:2013-09-10 07:50:19

标签: ruby

我想制作一个标准化大量API的ruby gem

与连接到每个API相关联的逻辑需要抽象为.rb个文件。要加载每个API的逻辑,我循环遍历文件夹的文件:

# Require individual API logic
Dir[File.dirname(__FILE__) + "/standard/apis/*.rb"].each do |file|
  require file
end

每个API都是StandardAPI的常量,因此我可以在每个API上迭代一些代码:

StandardAPI.constants.each do |constant|
  # Standardize this stuff
end

但是,我也有VERSION常数。它很好地循环我的API逻辑类,但是当我到达VERSION时,我遇到了:

:VERSION is not a class/module (TypeError)

如何循环遍历每个API而忽略不是我所需类的常量?

3 个答案:

答案 0 :(得分:3)

您似乎应该可以使用is_a?

class Test
end

Test.is_a?(Class)
=> true

VERSION = 42

VERSION.is_a?(Class)
=> false

答案 1 :(得分:3)

由于Module#constants会返回符号数组,因此您必须先使用Module#const_get查找常量:

Math.const_get(:PI)              #=> 3.141592653589793
StandardAPI.const_get(:VERSION)  #=> the value for StandardAPI::VERSION

然后你可以检查它是否是一个类:

Math.const_get(:PI).class                    #=> Float
Math.const_get(:PI).is_a? Class              #=> false
StandardAPI.const_get(:VERSION).is_a? Class  #=> false

过滤所有类:

StandardAPI.constants.select { |sym| StandardAPI.const_get(sym).is_a? Class }

另一种方法是收集子类,可能使用Class#inherited

# standard_api/base.rb
module StandardAPI
  class Base
    @apis = []

    def self.inherited(subclass)
      @apis << subclass
    end

    def self.apis
      @apis
    end
  end
end

# standard_api/foo.rb
module StandardAPI
  class Foo < Base
  end
end

# standard_api/bar.rb
module StandardAPI
  class Bar < Base
  end
end

StandardAPI::Base.apis
#=> [StandardAPI::Foo, StandardAPI::Bar]

答案 2 :(得分:0)

我猜你可以抓住那个例外并继续

StandardAPI.constants.each do |constant|
  begin
    # Standardize this stuff
    rescue TypeError
      next
  end
end

或@jonas提到

StandardAPI.constants.each do |constant|
  if constant.is_a?(Class)
    # Standardize this stuff
  end
end