Skip to content

Instantly share code, notes, and snippets.

@tarcieri
Created August 12, 2009 21:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tarcieri/166800 to your computer and use it in GitHub Desktop.
Save tarcieri/166800 to your computer and use it in GitHub Desktop.
class Module
# Return all constants presently defined
def all_constants
# I <3 you ActiveSupport, really I do!
if defined?(ActiveSupport::Deprecation)
ActiveSupport::Deprecation.silence { __all_constants }
else
__all_constants
end
end
#######
private
#######
# Actual implementation of all_constants method
def __all_constants
result = {}
parents = [self.class]
until parents.empty?
unprocessed_parents = parents
parents = []
unprocessed_parents.each do |parent|
parent.constants.each do |constant_name|
constant = begin
parent.const_get constant_name
rescue Exception
# Some packages (i.e. Rack) apparently try to automagically
# pull in gems when you frob their constants. The bastards.
# Sometimes ActiveSupport likes to freak out as well. If we
# encounter errors when frobbing constants, just ignore them
# and carry on. And yes, "rescue Exception" is necessary there
next
end
next unless constant.is_a? Module
next if result.include? constant
result[constant] = true
parents << constant
end
end
end
result.keys
end
end
class Class
# Return all descendants of a class
def descendants
if defined?(ActiveSupport::Deprecation)
ActiveSupport::Deprecation.silence { __descendants }
else
__descendants
end
end
#######
private
#######
def __descendants
all_constants.select { |obj| obj.ancestors.include? self }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment