Eine Kopie von xxx wurde aus dem Modulbaum entfernt, ist aber noch aktiv

129

Ich bin mir ziemlich sicher, dass der Fehler nichts mit dem tatsächlichen Inhalt des TenantIdLoaderModuls zu tun hat . Stattdessen hat es etwas mit ActiveSupportAbhängigkeiten zu tun .

Ich kann diesen Fehler scheinbar nicht überwinden. Nach dem, was ich gelesen habe, liegt es daran, dass entweder ActiveRecord::Baseneu geladen wird oder Company::TenantIdLoaderneu geladen wird, und dass dies irgendwie nicht kommuniziert wird. Hilfe bitte! Ich würde wirklich gerne ein Upgrade auf Rails 4.2 erhalten.

BEARBEITEN

Ich habe jetzt gelernt, dass es daran liegt, dass ich referenziere, Tenantwas automatisch neu geladen wird. Ich muss in der Lage sein, tatsächlich auf die Klasse zu verweisen. Weiß jemand, wie man das umgeht?

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
quelle
3
Hilft diese Antwort überhaupt? stackoverflow.com/questions/17561697/…
Waynn Lue
Sind Sie sicher, dass die Mieterklasse beteiligt ist? Wenn Sie die Teile dieses Codes, die Tenant verwenden, löschen, erhalten Sie trotzdem eine Fehlermeldung?
Frederick Cheung
@WaynnLue Ja, ich denke, das ist der Grund, ich weiß nur nicht, wie ich das beheben soll.
kddeisz
@FrederickCheung Ich habe eine andere Datei ähnlich dieser, die auf die gleiche Weise fehlerhaft ist, und es gibt immer Fehler in der Zeile, die sich auf Tenant bezieht, also würde ich es am besten erraten.
kddeisz
1
Obwohl Sie Wisper in Rails hier nicht verwenden, kann es für andere nützlich sein, zu beachten, dass Wisper dieses Problem ziemlich konsistent verursacht, wenn Sie den Ratschlägen in diesem Thread nicht folgen: stackoverflow.com/questions/28346609/…
Steve N

Antworten:

181

Tenantist eine Art roter Hering - der Fehler würde auftreten, wenn Sie auf eine App verweisen, die per Rails- const_missingTrick geladen werden muss .

Das Problem ist, dass Sie etwas nachladbares (Ihr Modul) nehmen und es dann in etwas nicht nachladbares ( ActiveRecord::Baseoder in Ihrem früheren Beispiel ActionMailer::Base) aufnehmen. Irgendwann wird Ihr Code neu geladen und ActiveRecord enthält dieses Modul immer noch, obwohl Rails glaubt, es entladen zu haben. Der Fehler tritt auf, wenn Sie auf Tenant verweisen, da dies dazu führt, dass Rails ihre const_missingHooks ausführen , um herauszufinden, von wo Tenant geladen werden soll, und dieser Code ausflippt, weil das Modul, von dem aus die konstante Suche beginnt, nicht vorhanden sein sollte.

Es gibt 3 mögliche Lösungen:

  1. Beenden Sie die Aufnahme Ihres Moduls in nicht nachladbare Klassen - fügen Sie sie entweder nach Bedarf in einzelne Modelle und Controller ein oder erstellen Sie eine abstrakte Basisklasse und fügen Sie das Modul dort ein.

  2. Machen Sie dieses Modul nicht nachladbar, indem Sie es an einem Ort speichern, der nicht in autoload_paths enthalten ist (Sie müssen es explizit benötigen, da Rails es nicht mehr magisch für Sie laden).

  3. Ändern des Mandanten in :: Mandant ( Object.const_missingwird dann aufgerufen, nicht Tenant.const_missing)

Frederick Cheung
quelle
30
Ich habe anscheinend eine dritte Lösung gefunden, obwohl ich mich gefragt habe, ob Sie wissen, warum es funktioniert. Wenn ich es als :: Mieter bezeichne, funktioniert alles auf magische Weise. Möglicherweise, weil es dann als Konstante der obersten Ebene geladen wird? Vielleicht?
kddeisz
3
dann ist es Object.const_missing, das aufgerufen wird, nicht YourModule.const_missing, damit die Dinge klappen sollten
Frederick Cheung
6
Das Zurücksetzen auf die oberste Ebene ::hat auch für mich funktioniert!
Alex Moore-Niemi
7
Ich hatte dieses Problem von Zeit zu Zeit und in meinem Fall war es mit dem Frühling verbunden, also ./bin/spring stopwurde es gelöst.
Santuxus
1
Ich LIEBE, dass dies ein Laufzeitfehler von Ruby / Rails ist - im Gegensatz zu jeder anderen Sprache, ob dynamisch oder nicht, bietet Ruby Entwicklern die uneingeschränkte Flexibilität, buchstäblich keine Ahnung zu haben, wo Module definiert sind, bis Ihr Programm ausgeführt wird (und in welcher Reihenfolge es ausgeführt wird). Es ist so gut gestaltet.
Andy Ray
32

Das Ändern von ModuleName in :: ModuleName hat bei mir funktioniert.

Aman Kumar
quelle
6

Ich bin mir nicht sicher, ob dies irgendjemandem helfen wird, aber ich hatte dies plötzlich nach einer Änderung, die nichts damit zu tun hatte. Es ging weg, nachdem ich den Anwendungsserver neu gestartet hatte.

Rindfleisch_Boolescher Wert
quelle
0

Ändern, ModuleNameum 'ModuleName'.constantizedas Problem für mich zu lösen.

Qortex
quelle
0

Was hat bei mir funktioniert:

Update config.eager_load = falseauftrue

im config/environments/development.rb

Ruby 2.6.5
Rails 5.1.6

Jan Werkhoven
quelle
1
Ja, mach das definitiv nicht. Das wird Ihre Fähigkeit zum erneuten Laden von Code in der Entwicklung beeinträchtigen.
kddeisz
-13

Manchmal bist du einfach

Starten Sie Ihren Server neu.

Albert.Qing
quelle
Ich verstehe nicht, warum ich diese Antwort abgelehnt habe. Wiederholen bedeutet, dass es wichtig ist! Warum haben einfache Dinge viel Unsinn?
Albert.Qing
7
Dies wird abgelehnt, weil (a) unabhängig davon, wie oft Sie Ihren Server neu starten, das Problem in der ursprünglichen Frage nicht gelöst wird und (b) Sie nicht einfach die Symptome eines Problems behandeln sollten, sondern das Problem selbst.
tjbp
@tjbp plz vorsichtig mit dem Wort "manchmal" ok?
Albert.Qing
Das Problem ist, dass es unmöglich ist, die Anwendung im Entwicklungsmodus zu debuggen, wenn Sie den Server nach jeder Änderung neu starten müssen.
Max Ivak
2
Ich werde für diese Antwort stimmen, denn wenn Sie Mongoid verwenden und Objekt X von der Rails-Konsole löschen, wird folgende Fehlermeldung angezeigt: A copy of X has been removed from the module tree but is still activeAuf allen Seiten mit Object Y.embeds Xund Neustart funktioniert der Server wirklich für diesen speziellen Fall. Aber Sie sollten Ihre Antwort bearbeiten.
Lucas Andrade