我已经设置了几个提供类似功能的模块,并且我有另一个模块来收集所有这些模块,因此在运行时可以确定可用的功能。
这很好用,但每当代码重新加载时,Rails的自动加载功能就会破坏收集模块上的实例变量。
代码看起来像这样:
module ServiceCollection
def self.available_services
@available_services ||= []
end
end
module ServiceProvider
extend ActiveSupport::Concern
included do |includer|
ServiceCollection.available_services.push(includer)
end
end
module MyService
include ServiceProvider
#some functionality here
end
调用ServiceCollection.available_services
将返回包含ServiceProvider
的模块列表,但是在重新加载时,实例变量@available_services
将被重置,后续调用将返回一个空数组。
有一种简单的方法来解决这个问题吗?
答案 0 :(得分:1)
您可以强制加载模块,在您的application.rb文件中调用require
。
类似的东西:
Dir["#{File.expand_path('../..', __FILE__)}/extras/*.rb"].each { |rb| require rb }
答案 1 :(得分:0)
感谢@thaleshcv的答案,但我决定走另一条路,部分受到他的回答的启发。
我将ServiceCollection
的实现更改为以下内容:
module ServiceCollection
def self.available_services
Dir[Rails.root.join("app", "services", "*.rb")].each do |filename|
model_name = Pathname.new(filename.to_s).basename.to_s.chomp('.rb').camelcase
begin
Module.const_get(model_name)
rescue Exception => e
#Log something or whatever
end
end
@available_services ||= []
end
end
调用Module.const_get
会触发Rails的自动加载功能。假设我遵循模块/类/文件名命名约定,那么这应该可以正常工作。 Here's将此功能提取到模块中的要点