Reputation: 385910
In ruby, if I do "require foo", is there a way to subsequently determine the name of the module or modules defined in foo.rb?
For example, say I have a ruby file named foo.rb that looks like this:
# foo.rb
module MyModule
def self.summary
"this does something useful"
end
...
end
In another script, after I do "require foo", how can I determine that I now have a module named MyModule?
Ultimate what I'm after is to be able to do something like this:
file = someComputedFileName()
require file
puts "summary of #{file}: #{???::summary}
While I could force myself to make module names and file names identical, I'd rather not. I want a bit more freedom in making short filenames but more expressive module names. However, I am guaranteeing to myself that each file will only define a single module (think: plugins).
Upvotes: 3
Views: 1453
Reputation: 1360
I don't know if this is the best solution, but off the top of my head this seems to work:
all_constants = Object.constants
require 'foo'
foo_constants = Object.constants - all_constants
foo_constants should give you only the modules, classes or other constants that were defined by foo.rb.
Upvotes: 4
Reputation: 18111
One approach would be to use ObjectSpace.each_object(Module) to find all defined modules before requiring the file. Then, after you require the file, loop over all defined modules again and see if there are any new ones.
require "set"
old_modules = SortedSet.new
ObjectSpace.each_object(Module) {|m| old_modules.add(m) }
file = someComputedFileName()
require file
new_modules = SortedSet.new
ObjectSpace.each_object(Module) {|m| new_modules.add(m) unless old_modules.include?(m) }
puts "summary of #{file}: #{new_modules.to_a.map{|m|m.summary}.join(',')}"
That would also let you define more than one module in the file.
Upvotes: 3