3

gem本格的な API を標準化した ruby​​ を作りたい。

各 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 をループするにはどうすればよいですか?

4

3 に答える 3

4

はシンボルの配列を返すため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]
于 2013-09-10T08:30:36.203 に答える
3

is_a?を使用できるはずです。

class Test
end

Test.is_a?(Class)
=> true

VERSION = 42

VERSION.is_a?(Class)
=> false
于 2013-09-10T08:09:41.790 に答える
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
于 2013-09-10T08:09:32.007 に答える