[英]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.