[英]Best approach to mark specific Rails Models to be used in a module
I am trying to write a lib plugin/extension to perform an action where I need to know which Models have been marked for use with this plugin.我正在尝试编写一个 lib 插件/扩展来执行一个操作,我需要知道哪些模型已被标记为与此插件一起使用。
Currently, I am marking the models in the fashion of acts_as_something
method which is added to each Model intended to be used with the plugin.目前,我正在以
acts_as_something
方法的方式标记模型,该方法被添加到每个打算与插件一起使用的模型中。
The main file of the plugin looks like this插件的主文件如下所示
# 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
The intended use is to then call in a controller Foo.perform
, which needs to know the marked models in order to carry out the intended action, the idea being getting the list of models from Foo.models
.预期用途是然后调用控制器
Foo.perform
,它需要知道标记的模型才能执行预期的操作,其想法是从Foo.models
获取模型列表。
It works as intended if when config.eager_load
is set to true in development.rb
, otherwise the files of the models have not been used/loaded yet and therefore Foo.models
is an empty Array.如果在
development.rb
中将config.eager_load
设置为 true ,它会按预期工作,否则模型的文件尚未使用/加载,因此Foo.models
是一个空数组。
My goal is to be able to add more models to Foo without having to change Foo's code like this.我的目标是能够向 Foo 添加更多模型,而无需像这样更改 Foo 的代码。
#app/models/bar.rb
class Bar < ApplicationRecord
acts_as_foo
end
Any ideas on the best way to implement this?关于实现这一点的最佳方法的任何想法?
I had a similar problem before in my gem .我之前在我的 gem 中遇到过类似的问题。
I ended up loading ONLY model files (which is the minimum of my requirement same as yours because the DSL code is there like your acts_as_foo
), and not immediately eager loading all Rails-related files using Rails.application.eager_load!
我最终只加载模型文件(这是我的最低要求,因为 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.