Se ha eliminado una copia de xxx del árbol de módulos pero aún está activa.

129

Estoy bastante seguro de que el error no tiene nada que ver con el contenido real del TenantIdLoadermódulo. En cambio, tiene algo que ver con las ActiveSupportdependencias.

Parece que no puedo superar este error. Por lo que he leído, es porque ActiveRecord::Basese está volviendo a cargar o Company::TenantIdLoaderse está volviendo a cargar, y de alguna manera no se está comunicando eso. ¡Ayuda por favor! Realmente me gustaría poder actualizarme a Rails 4.2.

EDITAR

Ahora he aprendido que es porque estoy haciendo referencia a Tenantque se recarga automáticamente. Sin embargo, necesito poder hacer referencia a la clase, entonces, ¿alguien sabe cómo solucionar esto?

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
kddeisz
fuente
3
¿Ayuda esta respuesta? stackoverflow.com/questions/17561697/…
Waynn Lue
¿Estás seguro de que la clase de inquilinos está involucrada? Si elimina los bits de ese código que usan Tenant, ¿aún obtiene un error?
Frederick Cheung
@WaynnLue, sí, creo que esa es la razón, simplemente no sé cómo solucionarlo.
kddeisz
@FrederickCheung Tengo otro archivo similar a este que tiene errores de la misma manera, y siempre errores en la línea relacionada con el Inquilino, por lo que es mi mejor suposición.
kddeisz
1
Aunque no esté utilizando Wisper en Rails aquí, puede ser útil para otras personas notar que Wisper causa este problema de manera bastante consistente si no sigue los consejos de este hilo: stackoverflow.com/questions/28346609/…
Steve N

Respuestas:

182

Tenantes una especie de arenque rojo: el error ocurriría si hiciera referencia a cualquier bit de aplicación que deba cargarse con el const_missingtruco de rails .

El problema es que está tomando algo recargable (su módulo) y luego lo incluye en algo no recargable ( ActiveRecord::Baseo, en su ejemplo anterior ActionMailer::Base). En algún momento, su código se vuelve a cargar y ahora ActiveRecord todavía tiene este módulo incluido, aunque rails cree que lo ha descargado. El error ocurre cuando hace referencia al Inquilino porque eso hace que los rieles ejecuten sus const_missingganchos para averiguar desde dónde se debe cargar el Inquilino y ese código se asusta porque el módulo desde el que comienza la búsqueda constante no debería estar allí.

Hay 3 posibles soluciones:

  1. Deje de incluir su módulo en clases no recargables: incluya en modelos individuales, controladores según sea necesario o cree una clase base abstracta e incluya el módulo allí.

  2. Haga que este módulo no sea recargable almacenándolo en un lugar que no esté en autoload_paths (tendrá que requerirlo explícitamente ya que los rieles ya no lo cargarán mágicamente por usted)

  3. Cambiar inquilino a :: inquilino ( Object.const_missingse invocará, no Tenant.const_missing)

Frederick Cheung
fuente
30
Parece que encontré una tercera solución, aunque me preguntaba si sabes por qué funciona. Si hago referencia a que era :: Inquilino, todo funciona mágicamente. ¿Posiblemente porque lo está cargando como una constante de nivel superior? ¿Tal vez?
kddeisz
3
entonces es Object.const_missing que se invocará, no YourModule.const_missing para que las cosas funcionen
Frederick Cheung
66
¡Retroceder al nivel superior usando también ::funcionó para mí!
Alex Moore-Niemi
77
Ocurría este problema de vez en cuando y en mi caso estaba relacionado con la primavera, por lo que hacerlo ./bin/spring stopfue resolverlo.
santuxus
2
ME ENCANTA que este sea un error de tiempo de ejecución de Ruby / Rails: a diferencia de cualquier otro lenguaje, dinámico o no, Ruby brinda a los desarrolladores la verdadera flexibilidad ilimitada para no tener literalmente idea de dónde se definen los módulos hasta que se ejecuta el programa (y en qué orden se ejecuta). Está muy bien diseñado.
Andy Ray
32

Cambiar ModuleName a :: ModuleName funcionó para mí.

Aman Kumar
fuente
6

No estoy seguro de si esto ayudará a alguien, pero de repente esto comenzó a ocurrir después de un cambio que parecía no estar relacionado. Se fue después de reiniciar el servidor de aplicaciones.

carne booleana
fuente
0

Cambiar ModuleNamepara 'ModuleName'.constantizeresolver el problema para mí.

Qortex
fuente
0

Lo que funcionó para mí:

Actualizar config.eager_load = falseatrue

en config/environments/development.rb

Ruby 2.6.5
Rails 5.1.6

Jan Werkhoven
fuente
1
Sí, definitivamente no hagas esto. Eso matará tu capacidad de recargar código en desarrollo.
kddeisz
-13

A veces solo

Reinicia tu servidor,

Albert.Qing
fuente
No entiendo por qué rechazar esta respuesta? ¡Repetir significa que es importante! ¿Por qué las cosas simples tienen muchas tonterías?
Albert.Qing
77
Esto se rechaza porque (a) no importa cuántas veces reinicie su servidor, no resolverá el problema en la pregunta original, y (b) no debería simplemente tratar los síntomas de un problema, sino el problema en sí.
tjbp
@tjbp por favor tenga cuidado con la palabra "a veces" ¿ok?
Albert.Qing
El problema es que es imposible depurar la aplicación en modo de desarrollo si tiene que reiniciar el servidor después de cada cambio.
Max Ivak
2
Voy a votar por esta respuesta porque si está usando mongoid y elimina el objeto X de la consola de rails, obtendrá este error: A copy of X has been removed from the module tree but is still activeen todas las páginas que tienen Object Y.embeds X, y reiniciar el servidor realmente funciona para este caso específico. Pero deberías editar tu respuesta.
Lucas Andrade