我有一些rb文件,都具有相同的结构:
class RandomName < FooBar
end
randomname是一个随机类名,它在每个rb文件中都有变化,但都是从Foobar继承的。
我如何从rb文件加载所有randomclass?
答案 0 :(得分:4)
您可以在FooBar类中定义一个名为inherited
的方法。看here
class FooBar
def self.inherited(subclass)
puts "New subclass: #{subclass}"
end
end
每次创建子类时,您都会在回调中获得它。然后你可以用所有这些子类做任何你想做的事。
答案 1 :(得分:4)
我认为解决方案有两个部分:
如何动态实例化一个类
一个。使用String#constantize
from ActiveSupport
klass = "SomeNamespace::SomeClassName".constantize
klass.new
湾使用Module#const_get
(不处理名称空间)
klass = const_get(:SomeClassName)
klass.new
如何检测班级名称
ruby中广泛使用的约定是在文件包含的类之后命名,因此random_name.rb
将包含RandomName
类。如果您遵循此约定,那么您可以执行以下操作:
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
我认为你应该解释一下你想要完成的事情。您正在采取的方法似乎是非常规的,并且可能有一种更有效的方法来实现您的目标,而无需执行所有这些文件加载和具有随机名称的类的动态实例化。
请记住,仅仅因为红宝石让你做某事,这并不意味着实际做到这一点是个好主意!
答案 2 :(得分:0)
我有类似的要求,将类名作为字符串传递。需要的一个技巧是它不必在开始时,所以我更喜欢只加载我需要的类。
我使用了eval,因为它没有任何Rails依赖项(我在这里编写纯Ruby代码)。
以下内容依赖于约定(Class位于同名文件中),但如果您确实知道类和文件,则此方法的优点是不需要目录中的每个文件,只能动态加载在你需要的时候你需要的。
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.