Ruby on rails xxx的副本已从模块树中删除,但仍处于活动状态

Ruby on rails xxx的副本已从模块树中删除,但仍处于活动状态,ruby-on-rails,ruby,ruby-on-rails-4,Ruby On Rails,Ruby,Ruby On Rails 4,我很确定错误与TenantIdLoader模块的实际内容无关。相反,它与ActiveSupport依赖项有关 我似乎无法克服这个错误。从我所读到的,这是因为要么是ActiveRecord::Base被重新加载,要么是Company::tenatidloader被重新加载,而它不知何故没有传达这一点。救命啊!我非常希望能够升级到Rails 4.2 编辑 我现在了解到,这是因为我正在引用自动重新加载的Tenant。我需要能够实际引用这个类,所以有人知道如何绕过这个问题吗 config/applica

我很确定错误与
TenantIdLoader
模块的实际内容无关。相反,它与
ActiveSupport
依赖项有关

我似乎无法克服这个错误。从我所读到的,这是因为要么是
ActiveRecord::Base
被重新加载,要么是
Company::tenatidloader
被重新加载,而它不知何故没有传达这一点。救命啊!我非常希望能够升级到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\u id\u 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

Tenant
有点像是在转移注意力——如果你引用了rails的
const_missing
技巧需要加载的任何应用程序,就会出现错误

问题是,您正在获取一些可重新加载的内容(您的模块),然后将其包含在一些不可重新加载的内容中(
ActiveRecord::Base
,或者在前面的示例中
ActionMailer::Base
)。在某个时候,代码被重新加载,现在ActiveRecord仍然包含这个模块,即使rails认为它已经卸载了它。引用租户时会发生错误,因为这会导致rails运行其
const_missing
钩子来找出租户应该从哪里加载,并且代码会崩溃,因为常量搜索开始的模块不应该在那里

有3种可能的解决方案:

  • 停止将模块包含到不可重新加载的类中—根据需要将其包含到各个模型、控制器中,或者创建一个抽象基类并将模块包含在其中

  • 通过将此模块存储在非自动加载路径中的某个位置,使其不可重新加载(您必须明确要求它,因为rails将不再神奇地为您加载它)

  • 将租户更改为::租户(
    Object.const\u missing
    将被调用,而不是
    Tenant.const\u missing


  • 模块名称更改为::模块名称对我来说很有效。

    不确定这是否对任何人都有帮助,但在一次看似无关的更改后,我突然发现这种情况。重新启动应用程序服务器后,它消失了。

    ModuleName
    更改为
    'ModuleName'

    config.eager\u load=false更新为
    true

    config/environments/development.rb中

    Ruby 2.6.5

    Rails 5.1.6

    解决此问题的另一种方法是要求文件中直接包含不可重新加载的模块


    lib/company/tenant\u id\u loader.rb的顶部,放置
    require\u relative'../../app/models/tenant'
    或任何与id loader相对的路径到租户模型。

    这个答案有帮助吗?您确定涉及租户类吗?如果你删除了使用Tenant的代码,你还会出错吗?@WaynnLue是的,我想这就是原因,我只是不知道如何修复它。@FrederickCheung我有另一个类似于此的文件,它以同样的方式出错,它总是在与Tenant相关的行上出错,所以这是我最好的猜测。虽然您在Rails中没有使用Wisper,但其他人可能会注意到,如果您不遵循本文中的建议,Wisper会一直导致此问题:我似乎找到了第三种解决方案,不过我想知道您是否知道它为什么有效。如果我引用的是::Tenant,那么一切都会神奇地发生。可能是因为它将它作为顶级常量加载?也许吧?那么将调用的是Object.const_missing,而不是YourModule.const_missing,所以应该使用
    返回到顶级,这对我也适用!我经常遇到这个问题,在我的例子中,它与spring有关,因此执行
    /bin/spring stop
    可以解决它。我喜欢这是一个运行时Ruby/Rails错误-不同于任何其他语言,动态或非动态,Ruby为开发人员提供了真正无限的灵活性,在程序执行之前(以及以什么顺序执行),他们完全不知道在哪里定义了模块。设计得太好了。是的,绝对不要这样做。这将扼杀您在开发中重新加载代码的能力。