Rails模块自动加载保存状态

时间:2014-11-26 10:57:54

标签: ruby-on-rails ruby

我已经设置了几个提供类似功能的模块,并且我有另一个模块来收集所有这些模块,因此在运行时可以确定可用的功能。

这很好用,但每当代码重新加载时,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将被重置,后续调用将返回一个空数组。

有一种简单的方法来解决这个问题吗?

2 个答案:

答案 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将此功能提取到模块中的要点