Une copie de xxx a été supprimée de l'arborescence des modules mais est toujours active

129

Je suis presque sûr que l'erreur n'a rien à voir avec le contenu réel du TenantIdLoadermodule. Au lieu de cela, cela a quelque chose à voir avec les ActiveSupportdépendances.

Je n'arrive pas à surmonter cette erreur. D'après ce que j'ai lu, c'est parce que soit ActiveRecord::Baseen cours de rechargement, soit Company::TenantIdLoaderen cours de rechargement, et cela ne communique pas d'une manière ou d'une autre. Aidez-moi, s'il vous plaît! J'aimerais vraiment pouvoir être mis à niveau vers Rails 4.2.

ÉDITER

J'ai maintenant appris que c'est parce que je fais référence à Tenantce qui est rechargé automatiquement. J'ai besoin de pouvoir faire référence à la classe, alors est-ce que quelqu'un sait comment contourner cela?

config / application.rb

config.autoload_paths += %W( #{config.root}/lib/company )

config / initialiseurs / company.rb

ActionMailer::Base.send(:include, Company::TenantIdLoader)

lib / entreprise / 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
la source
3
Cette réponse aide-t-elle du tout? stackoverflow.com/questions/17561697/…
Waynn Lue
Êtes-vous sûr que la classe Tenant est impliquée? Si vous remplacez les bits de ce code qui utilisent Tenant, obtenez-vous toujours une erreur?
Frederick Cheung
@WaynnLue ouais je pense que c'est la raison, je ne sais pas comment y remédier.
kddeisz
@FrederickCheung J'ai un autre fichier similaire à celui-ci qui est erroné de la même manière, et il contient toujours des erreurs sur la ligne liée à Tenant, donc c'est ma meilleure estimation.
kddeisz
1
Bien que vous n'utilisiez pas Wisper dans Rails ici, il peut être utile pour d'autres personnes de noter que Wisper provoque ce problème de manière assez cohérente si vous ne suivez pas les conseils de ce fil: stackoverflow.com/questions/28346609/…
Steve N

Réponses:

182

Tenantest une sorte de hareng rouge - l'erreur se produirait si vous référençiez un morceau d'application qui doit être chargé par l' const_missingastuce des rails .

Le problème est que vous prenez quelque chose de rechargeable (votre module) et que vous l'incluez ensuite dans quelque chose de non rechargeable ( ActiveRecord::Baseou, dans votre exemple précédent ActionMailer::Base). À un moment donné, votre code est rechargé et maintenant ActiveRecord a toujours ce module inclus même si rails pense qu'il l'a déchargé. L'erreur se produit lorsque vous faites référence à Tenant, car cela oblige les rails à exécuter ses const_missinghooks pour savoir d'où Tenant doit être chargé et ce code panique car le module à partir duquel la recherche constante commence ne devrait pas être là.

Il existe 3 solutions possibles:

  1. Arrêtez d'inclure votre module dans des classes non rechargeables - incluez dans des modèles individuels, des contrôleurs si nécessaire ou créez une classe de base abstraite et incluez le module là-dedans.

  2. Rendez ce module non rechargeable en le stockant quelque part qui ne soit pas dans autoload_paths (vous devrez l'exiger explicitement car les rails ne le chargeront plus par magie pour vous)

  3. Changer Tenant en :: Tenant ( Object.const_missingsera alors invoqué, pas Tenant.const_missing)

Frederick Cheung
la source
30
Il me semble avoir trouvé une troisième solution, même si je me demandais si vous savez pourquoi cela fonctionne. Si je fais référence à :: Tenant, tout fonctionne comme par magie. Peut-être parce qu'il le charge alors en tant que constante de niveau supérieur? Peut être?
kddeisz
3
alors c'est Object.const_missing qui sera invoqué et non YourModule.const_missing donc les choses devraient s'arranger
Frederick Cheung
6
Revenir à l'utilisation de haut niveau a également ::fonctionné pour moi!
Alex Moore-Niemi
7
J'ai eu ce problème de temps en temps et dans mon cas, il était lié au printemps, donc le ./bin/spring stoprésoudre était de le résoudre.
santuxus
2
J'ADORE qu'il s'agisse d'une erreur d'exécution Ruby / Rails - contrairement à tout autre langage, dynamique ou non, Ruby donne aux développeurs la véritable flexibilité illimitée pour n'avoir littéralement aucune idée de l'endroit où les modules sont définis jusqu'à ce que votre programme s'exécute (et dans quel ordre il s'exécute). C'est tellement bien conçu.
Andy Ray
32

Changer ModuleName en :: ModuleName a fonctionné pour moi.

Aman Kumar
la source
6

Je ne sais pas si cela aidera quelqu'un, mais cela a soudainement commencé à se produire après un changement qui ne semblait pas lié. Il a disparu après le redémarrage du serveur d'applications.

boeuf_booléen
la source
0

Changer ModuleNamepour 'ModuleName'.constantizerésoudre le problème pour moi.

Qortex
la source
0

Ce qui a fonctionné pour moi:

Mettre config.eager_load = falseà jour verstrue

dans config/environments/development.rb

Ruby 2.6.5
Rails 5.1.6

Jan Werkhoven
la source
1
Ouais, ne fais certainement pas ça. Cela va tuer votre capacité à recharger du code en développement.
kddeisz
-13

Parfois tu viens

Redémarrez votre serveur,

Albert.Qing
la source
Je ne comprends pas pourquoi voter contre cette réponse? Répéter signifie que c'est important! Pourquoi les choses simples ont-elles beaucoup d'absurdités?
Albert.Qing
7
Ceci est décliné car (a) peu importe le nombre de fois que vous redémarrez votre serveur, cela ne résoudra pas le problème dans la question d'origine, et (b) vous ne devriez pas simplement traiter les symptômes d'un problème, mais le problème lui-même.
tjbp
@tjbp plz attention au mot "parfois" ok?
Albert.Qing
le problème est qu'il est impossible de déboguer l'application en mode développement si vous devez redémarrer le serveur après chaque modification.
Max Ivak
2
Je voterai pour cette réponse car si vous utilisez mongoid et supprimez l'objet X de la console rails, vous obtiendrez cette erreur: A copy of X has been removed from the module tree but is still activesur toutes les pages contenant Object Y.embeds X, et redémarrer le serveur fonctionne vraiment pour ce cas spécifique. Mais vous devez modifier votre réponse.
Lucas Andrade