在模型中存储 .rb 文件列表

Store a list of .rb files inside model

同事们!我有文档模型。文档应由其中一个解析器处理(在我的项目中,它们被称为 'importers' 并存储在 'lib/importers' 文件夹中)。问题是关于在模型层内实现实体导入器的最佳方法是什么? (例如将文件与进口商相关联)。

  1. 第一个想法是创建导入器 table,但我将有 2 个独立的位置来保存导入器名称(数据库和文件系统)。不良案例:

案例 1:我添加了一个新的导入器,但忘记将其添加到导入器table = 我无法将文档与该导入器相关联

案例2:导入器被重命名,我们忘记在数据库中重命名=错误

  1. 我决定定义

    def Document.importers @importers ||= Dir.entries("#{Rails.root}/lib/importers/") .select { |name| !File.directory?(name) && name != 'base_importer.rb'} .map { |name| name.gsub(/\.rb$/, '') } end

for f.association inout 并将导入器字符串属性添加到文档模型。所以我可以通过以下方式获得进口商 class -- 'importer.classify.constantize'。它有效,但看起来令人毛骨悚然

对于这种情况,您能建议更好的解决方案吗?我将很高兴听到任何想法 ;)

我会在数据库中对它们进行建模,然后在文件发生更改时使用一些系统来更新数据库。这种情况在资产管理系统中经常发生:您有一些物理文件和一些数据,是的,如果它们不同步,您就会遇到问题。因此,您将系统放置到位以尝试使它们保持同步。例如,你可以有一个 rake 任务来根据物理文件更新数据库,然后协议是你需要在更改文件后 运行 rake 任务,如果你不这样做,那么你就搞砸了问题是你的错。开发人员应该能够在这些规则范围内工作。

最终,Rails 是关于对象关系数据的,因此如果您想使用 rails,请使用它。如果您每次都尝试根据文件夹的内容动态构建大量实例,那么您最终会得到一个非常复杂且效率低下的系统。

在我的本地 ruby 聊天中头脑风暴期间做出的解决方案:

我没有提到所有导入器都是从 base_importer 继承的,它也放在 lib/importers 中。我们决定向其中添加 'inheritors' 数组,并使用 ruby 核心提供的钩子 'inherited' 将所有继承者存储在那里 -> http://ruby-doc.org/core-2.2.0/Class.html#method-i-inherited.

class BaseImporter
  @inheritors = []

  def self.inheritors
    @inheritors
  end

  def self.inherited(subclass)
    @inheritors << subclass.name
  end
  # ...
end

我们希望它能很好地工作,但我们忘记了,所有 类 都在 Rails 中预先加载。所以BaseImporter.inheritors会return[]给你全新的系统启动。:

anton@anton:~/Projects/project$ rails c
Running via Spring preloader in process 16832
Loading development environment (Rails 4.2.5)
B2.2.3 :001 > BaseImporter.inheritors
 => [] 

为了强制加载所有导入器,我做了一个初始化程序:

# config/initializers/importers.rb
# Preload importers
require 'base_importer'
Dir.glob("#{Rails.root}/lib/importers/*.rb").each { |file| require file }

BaseImporter 应该首先加载,因为如果任何导入器将在 BaseImporter 之前加载,它不会触发 'inherited' 钩子:

anton@anton:~/Projects/project$ rails c
Running via Spring preloader in process 16846
Loading development environment (Rails 4.2.5)
2.2.3 :001 > require "xxx_importer"
 => true 
2.2.3 :002 > require "base_importer"
 => true 
2.2.3 :003 > require "yyy_importer"
 => true 
2.2.3 :004 > BaseImporter.inheritors
 => ["XxxImporter"] 

欢迎 post 您对此解决方案的反馈。我会很高兴听到它