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


129

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

我似乎无法摆脱这个错误。从我读到的内容来看,这是因为要么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

3
这个答案有帮助吗?stackoverflow.com/questions/17561697/...
Waynn略

您确定涉及租户类吗?如果将使用Tenant的代码中的位存根,仍然会出错?
Frederick Cheung

@WaynnLue是的,我认为这就是原因,我只是不知道如何解决。
kddeisz 2015年

@FrederickCheung我有另一个与此文件类似的文件,该文件以相同的方式出错,并且总是在与Tenant相关的行上出错,所以这是我的最佳猜测。
kddeisz 2015年

1
虽然你没有使用WISPER在Rails的这里,它可能是其他人有用的注意,WISPER导致此问题非常一致,如果你不按照这个线程的建议:stackoverflow.com/questions/28346609/...
史蒂夫ñ

Answers:


182

Tenant有点像红色鲱鱼-如果您引用需要通过Rails的const_missing技巧加载的应用程序的任何部分,则会发生错误。

问题是您正在获取可重装的东西(您的模块),然后将其包含在不可重装的东西中(ActiveRecord::Base或者,在您先前的示例中ActionMailer::Base)。在某个时候,您的代码被重新加载,并且即使Rails认为ActiveRecord已卸载它,现在ActiveRecord仍然包含该模块。当您引用Tenant时会发生错误,因为这会导致Rails运行其const_missing钩子来找出应该从哪个位置加载Tenant,并且该代码会出现异常,因为不应该从那里开始进行常量搜索。

有3种可能的解决方案:

  1. 停止将模块包含在不可重载的类中-可以根据需要将模块包含在单个模型中,也可以将其包含在控制器中,或者创建一个抽象基类并将模块包含在其中。

  2. 通过将模块存储在autoload_paths之外的某个地方,使其不可重载(您必须明确要求它,因为Rails将不再为您神奇地加载它)

  3. 将Tenant更改为:: Tenant(Object.const_missing然后将调用,而不是Tenant.const_missing


30
我似乎已经找到了第三个解决方案,尽管我想知道您是否知道它为什么有效。如果我引用的是:: Tenant,那么一切都会神奇地完成。可能是因为它随后将其作为顶级常量加载?也许?
kddeisz 2015年

3
那么将调用Object.const_missing而不是YourModule.const_missing,这样事情应该可以解决
Frederick Cheung

6
回到顶层使用::对我也有用!
Alex Moore-Niemi 2015年

7
我时有发生此问题,在我的情况下,它与春天有关,因此可以./bin/spring stop解决此问题。
santuxus

1
我喜欢这是一个运行时 Ruby / Rails错误-与其他任何语言(无论是否动态)不同,Ruby为开发人员提供了真正的无限灵活性,使您几乎不知道在程序执行之前(在执行顺序上)定义模块的位置。如此精心设计。
安迪·雷


6

不知道这是否会对任何人有帮助,但是在发生似乎无关的更改之后,我突然开始发生这种情况。重新启动应用程序服务器后,它消失了。


0

更改ModuleName'ModuleName'.constantize解决这个问题对我来说。


0

对我有用的是:

更新config.eager_load = falsetrue

config/environments/development.rb

Ruby 2.6.5
Rails 5.1.6


1
是的,绝对不要这样做。那将杀死您在开发中重新加载代码的能力。
kddeisz

-13

有时候你只是

重新启动服务器,


我不明白为什么要拒​​绝这个答案?重复意味着很重要!为什么简单的事情有很多废话?
Albert.Qing

7
这是不好的意思,因为(a)无论您重新启动服务器多少次,它都不能解决原始问题中的问题,并且(b)您不应该简单地处理问题的症状,而要处理问题本身。
tjbp

@tjbp plz注意单词“有时”好吗?
Albert.Qing

问题是,如果每次更改后都必须重新启动服务器,则无法在开发模式下调试应用程序。
Max Ivak '18

2
我将对此答案投赞成票,因为如果您使用的是Mongoid并从Rails控制台删除对象X,则会出现此错误:A copy of X has been removed from the module tree but is still active在所有具有Object的页面上Y.embeds X,重新启动服务器确实适用于此特定情况。但是您应该编辑答案。
卢卡斯·安德拉德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.