Rails 引擎不缓存
在开发过程中,我尝试通过在 ActiveRecord::Base
类中包含一个方法来收集应用程序中的所有模型,以便他们可以配置模型,并且它将为我提供一个将该模型添加到全局数组的钩子。
module EngineName
module ActiveRecordExtensions
extend ActiveSupport::Concern
included do
def self.inherited(klass) #:nodoc:
klass.class_eval do
def self.config_block(&block)
abstract_model = EngineName::AbstractModel.new(self)
abstract_model.instance_eval(&block) if block
EngineName::Models.add(abstract_model)
end
end
end
end
end
end
我的 EngineName::Models
类只是一个包含所有模型的包装器。
module EngineName
class Models
class << self
def all
@models ||= []
end
alias_method :models, :all
def navigation
@models - excluded_navigation_models
end
def routed
@models - excluded_route_models
end
# Creates an array of models if none exists. Appends new models
# if the instance variable already exists.
def register(klass)
if @models.nil?
@models = [klass]
else
@models << klass unless @models.include?(klass) || excluded_models.include?(klass)
end
end
alias_method :add, :register
end
end
end
不过,每次刷新时,模型中的 config_block 方法都会被调用,并依次在我的全局模型数组中一遍又一遍地附加相同的模型。
正如您在下面看到的,每当我循环遍历所有模型时,它都会继续附加自身。
有什么方法可以在我的引擎中缓存某些类吗?或者我使用模型本身内的钩子注册模型的方法是否存在缺陷?
In development I am trying to gather all models within my app by including a method within ActiveRecord::Base
classes so they can configure the models and it will give me a hook to add that model to a global array.
module EngineName
module ActiveRecordExtensions
extend ActiveSupport::Concern
included do
def self.inherited(klass) #:nodoc:
klass.class_eval do
def self.config_block(&block)
abstract_model = EngineName::AbstractModel.new(self)
abstract_model.instance_eval(&block) if block
EngineName::Models.add(abstract_model)
end
end
end
end
end
end
My EngineName::Models
class is just a wrapper that holds all models.
module EngineName
class Models
class << self
def all
@models ||= []
end
alias_method :models, :all
def navigation
@models - excluded_navigation_models
end
def routed
@models - excluded_route_models
end
# Creates an array of models if none exists. Appends new models
# if the instance variable already exists.
def register(klass)
if @models.nil?
@models = [klass]
else
@models << klass unless @models.include?(klass) || excluded_models.include?(klass)
end
end
alias_method :add, :register
end
end
end
On each refresh though, the config_block
method within my model gets called and in turn appends the same model over and over within my global array of models.
As you can see down below, whenever I loop through all my models, it will keep on appending itself.
Is there any way to cache certain classes within my engine? Or is there a flaw within my approach of registering models with a hook within the model itself?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是,在您的开发环境中,您的模型会根据每个请求重新加载,以便对这些类的更改生效,并且您不必在每次更改源代码时重新启动服务器。您可以在控制台中看到此行为:
这意味着当您调用
@models.include?(klass)
时,您实际上是在对照上一个请求中的实例检查该对象的当前实例。您会注意到,随着时间的推移,您的内存会变得臃肿,因为这些对象不会被删除 - 因为垃圾收集将保留它们,因为 @models 实例变量中对它们的引用。这在生产中不会成为问题,因为类只加载一次,但它会给您带来开发问题。为了解决这个问题,我建议这样做:
使用哈希可以让您通过模型的名称来跟踪模型,并且每当模型的新版本出现时,它都会替换旧的过时版本。这应该对您的开发环境有所帮助。要获取所有模型的列表,您只需使用
@models.values
即可;要获取模型名称列表,您只需使用@models.keys
即可。The issue is that in your development environment your models get reloaded on every request so that changes to these classes take effect and you don't have to re-boot your server every time you make a change to your source code. You can see this behavior in the console:
What this means is that when you call
@models.include?(klass)
you are actually checking your current instantiation of that object against one from a previous request. What you'll notice is that over time your memory gets bloated because these objects will not be deleted - since garbage collection will keep them around because of the reference to them in your @models instance variable. This won't be a problem in production, because classes are only loaded once, but it will cause you problems in development.To get around this I would recommend doing something like this:
Using a hash will let you keep track of models by their names, and whenever a new version of a model comes around it will replace the old out-dated version. This should help in your development environment. To get a list of all the models you'll simply use
@models.values
and to get a list of the model names you'll simply use@models.keys
.