xxx 的副本已从模块树中删除,但仍处于活动状态
Posted
技术标签:
【中文标题】xxx 的副本已从模块树中删除,但仍处于活动状态【英文标题】:A copy of xxx has been removed from the module tree but is still active 【发布时间】:2015-06-20 14:15:11 【问题描述】:我很确定该错误与TenantIdLoader
模块的实际内容无关。相反,它与ActiveSupport
Dependencies 有关。
我似乎无法克服这个错误。根据我的阅读,这是因为 ActiveRecord::Base
正在重新加载或 Company::TenantIdLoader
正在重新加载,并且不知何故没有传达这一点。请帮忙!我真的很想升级到 Rails 4.2。
编辑
我现在知道这是因为我引用了Tenant
,它会自动重新加载。我需要能够实际引用该类,所以有人知道如何解决这个问题吗?
config/application.rb
config.autoload_paths += %W( #config.root/lib/company )
config/initializers/company.rb
ActionMailer::Base.send(:include, Company::TenantIdLoader)
lib/company/tenant_id_loader.rb
module Company
module TenantIdLoader
extend ActiveSupport::Concern
included do
cattr_accessor :tenant_dependency
self.tenant_dependency =
after_initialize do
self.tenant_id = Tenant.active.id if self.class.tenant_dependent? and self.new_record? and Tenant.active.present? and !Tenant.active.zero?
end
end
# class methods to be mixed in
module ClassMethods
# returns true if this model's table has a tenant_id
def tenant_dependent?
self.tenant_dependency[self.table_name] ||= self.column_names.include?('tenant_id')
end
end
end
end
【问题讨论】:
这个答案有帮助吗? ***.com/questions/17561697/… 您确定涉及到租户类吗?如果您将使用 Tenant 的代码部分剔除,您还会收到错误吗? @WaynnLue 是的,我认为这就是原因,我只是不知道如何解决它。 @FrederickCheung 我有另一个与此类似的文件,它以同样的方式出错,并且总是在与租户相关的行上出错,所以这是我最好的猜测。 虽然您在这里没有在 Rails 中使用 Wisper,但如果您不遵循此线程中的建议,其他人可能会注意到 Wisper 相当一致地导致此问题:***.com/questions/28346609/…跨度> 【参考方案1】:Tenant
有点像红鲱鱼 - 如果您引用了需要通过 rails 的const_missing
技巧加载的任何应用程序位,则会发生错误。
问题是您正在获取可重新加载的内容(您的模块),然后将其包含在不可重新加载的内容中(ActiveRecord::Base
或在您之前的示例中为ActionMailer::Base
)。在某些时候你的代码被重新加载,现在 ActiveRecord 仍然包含这个模块,即使 rails 认为它已经卸载了它。当您引用租户时会发生错误,因为这会导致 rails 运行其const_missing
挂钩以找出应该从哪里加载租户,并且代码会因为常量搜索开始的模块不应该存在而崩溃。
有 3 种可能的解决方案:
停止将您的模块包含到不可重新加载的类中 - 根据需要包含到单个模型、控制器中,或者创建一个抽象基类并将模块包含在其中。
将此模块存储在 autoload_paths 之外的某个位置,使其不可重新加载(您必须明确要求它,因为 rails 将不再为您神奇地加载它)
将租户更改为 ::Tenant(然后将调用 Object.const_missing
,而不是 Tenant.const_missing
)
【讨论】:
我似乎找到了第三种解决方案,但我想知道您是否知道它为什么有效。如果我引用它是 ::Tenant,那么一切都会神奇地进行。可能是因为它随后将其作为***常量加载?也许? 那么它将调用 Object.const_missing 而不是 YourModule.const_missing 所以事情应该会解决 使用::
退出到顶层也对我有用!
我时不时会遇到这个问题,在我的情况下它与弹簧有关,所以 ./bin/spring stop
正在解决它。
我喜欢这是一个 runtime Ruby/Rails 错误 - 与任何其他语言(无论是否动态)不同,Ruby 为开发人员提供了真正无限的灵活性,让他们完全不知道模块在哪里被定义直到你的程序执行(以及它执行的order)。它设计得非常好。【参考方案2】:
将 ModuleName 更改为 ::ModuleName 对我有用。
【讨论】:
【参考方案3】:不确定这是否会对任何人有所帮助,但在一个看似无关的更改之后,我突然开始发生这种情况。我重新启动应用程序服务器后它就消失了。
【讨论】:
【参考方案4】:将ModuleName
更改为'ModuleName'.constantize
为我解决了这个问题。
【讨论】:
【参考方案5】:解决此问题的另一种方法是在不可重新加载的文件中直接要求模块。
在lib/company/tenant_id_loader.rb
的顶部放置require_relative '../../app/models/tenant'
或相对于租户模型的id 加载器的任何路径。
【讨论】:
【参考方案6】:什么对我有用:
将config.eager_load = false
更新为true
在config/environments/development.rb
Ruby 2.6.5 导轨 5.1.6
【讨论】:
是的,绝对不要这样做。这会扼杀你在开发中重新加载代码的能力。以上是关于xxx 的副本已从模块树中删除,但仍处于活动状态的主要内容,如果未能解决你的问题,请参考以下文章