3

I want to make a ruby gem which standardizes a serious of APIs.

The logic associated with connecting to each API needs to be abstracted into .rb files. To load each of the API's logic, I'm looping through the files of a folder:

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

Each API is a constant of the StandardAPI, so I can to iterate some code over each API:

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

However, I have a VERSION constant too. It loops over my API logic classes just fine, but when I gets to VERSION, I run into:

:VERSION is not a class/module (TypeError)

How can I loop over each of the APIs ignoring constants that aren't my required classes?

3 Answers 3

5

Since Module#constants returns an array of symbols, you have to first look up the constant with Module#const_get:

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

Then you can check if it is a class:

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

To filter all classes:

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

Another approach is to collect the sub classes, maybe with 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] 
Sign up to request clarification or add additional context in comments.

Comments

3

It seems you should be able to use is_a?

class Test end Test.is_a?(Class) => true VERSION = 42 VERSION.is_a?(Class) => false 

2 Comments

The issue with this is that StandardAPI.constants doesn't return an array of the constants themselves, but an array of symbols that match the constant names.
0

I guess you can catch that exception and proceed

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

or as @jonas mentioned

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.