繁体   English   中英

标记要在模块中使用的特定 Rails 模型的最佳方法

[英]Best approach to mark specific Rails Models to be used in a module

我正在尝试编写一个 lib 插件/扩展来执行一个操作,我需要知道哪些模型已被标记为与此插件一起使用。

目前,我正在以acts_as_something方法的方式标记模型,该方法被添加到每个打算与插件一起使用的模型中。

插件的主文件如下所示

# lib/foo.rb
module Foo
  class << self
    attr_accessor :models
  end
  self.models = []

  module Model
    def acts_as_foo
      Foo.models << self
    end
end

ActiveSupport.on_load(:active_record) do
  extend Foo::Model
end

预期用途是然后调用控制器Foo.perform ,它需要知道标记的模型才能执行预期的操作,其想法是从Foo.models获取模型列表。

如果在development.rb中将config.eager_load设置为 true ,它会按预期工作,否则模型的文件尚未使用/加载,因此Foo.models是一个空数组。

我的目标是能够向 Foo 添加更多模型,而无需像这样更改 Foo 的代码。

#app/models/bar.rb
class Bar < ApplicationRecord
  acts_as_foo
end

关于实现这一点的最佳方法的任何想法?

之前在我的 gem 中遇到过类似的问题

我最终加载模型文件(这是我的最低要求,因为 DSL 代码就像你的acts_as_foo ),并没有立即使用Rails.application.eager_load!加载所有与 Rails 相关的文件Rails.application.eager_load! .

# lib/foo.rb
module Foo
  class << self
    attr_accessor :models
  end

  self.models = []

  class Engine < Rails::Engine
    initializer 'foo.eager_load_models' do |app|
      unless app.config.eager_load
        models_load_path = File.join(Rails.root, 'app', 'models')

        # copied from https://apidock.com/rails/Rails/Engine/eager_load%21/class
        matcher = /\A#{Regexp.escape(models_load_path.to_s)}\/(.*)\.rb\Z/
        Dir.glob("#{models_load_path}/**/*.rb").sort.each do |file|
          app.require_dependency file.sub(matcher, '\1')
        end
      end
    end
  end

  module Model
    def acts_as_foo
      Foo.models << self
    end
  end
end

ActiveSupport.on_load(:active_record) do
  extend Foo::Model
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM