How to load a unknown class in a module?
I have some rb files, all with the same structure:
class RandomName < FooBa开发者_StackOverflow社区r
end
The randomname is a random class name which changes in each rb file but all inherits from Foobar.
how i can load all randomclass from there rb files?
I think there are 2 parts to the solution:
How to dynamically instantiate a class
a. Using
String#constantize
from ActiveSupportklass = "SomeNamespace::SomeClassName".constantize klass.new
b. Use
Module#const_get
(which doesn't handle namespaces)klass = const_get(:SomeClassName) klass.new
How to detect a class name
A convention followed widely in ruby is to name the file after the class that it contains, so
random_name.rb
would contain theRandomName
class. If you follow this convention, then you could do something like:Dir["/path/to/directory/*.rb"].each do |file| require file file_name = File.basename(file.path, '.rb') # using ActiveSupport for camelcase and constantize file_name.camelcase.constantize.new end
I think you should explain what you are trying to accomplish. The approach you are taking seems unconventional and there may be a much more effective way of reaching your goal without doing all this loading of files and dynamic instantiation of classes with random names.
Remember, just because ruby lets you do something, it doesn't mean it's a good idea to actually do it!
you can define a method called inherited
in the FooBar class. look here
class FooBar
def self.inherited(subclass)
puts "New subclass: #{subclass}"
end
end
Every time a subclass is created, you will get it in the callback. Then you can do whatever you want with all those subclasses.
I have a similar requirement, passing a class name in as a string. One trick with require is that it doesn't have to be at the start, so I prefer to only load the class I need.
I used eval because it doesn't have any Rails dependencies (I'm writing pure Ruby code here).
The following relies on convention (that the Class is in a file of the same name), but if you do know the class and file, this approach has the advantage of not requiring every file in a directory and only dynamically loading the one you need at the time you need it.
klass = "classname"
begin
# Load the file containing the class from same directory I'm executing in
require_relative klass # Or pass a local directory like "lib/#{klass}"
# Use eval to convert that string to a Constant (also capitalize it first)
k = eval(klass.capitalize).new
rescue
# Do something if the convention fails and class cannot be instantiated.
end
k.foo # Go ahead and start doing things with your new class.
精彩评论