wake-up-neo.net

Rails 5: Lädt lib-Dateien in die Produktion

Ich habe eine meiner Apps von Rails 4.2.6 auf Rails 5.0.0 aktualisiert. Der pgrade Guide besagt, dass Die Autoload-Funktion ist jetzt in der Produktion standardmäßig deaktiviert.

Jetzt bekomme ich immer einen Fehler auf meinem Produktionsserver, da ich alle lib-Dateien mit Autoload in die Datei application.rb Lade.

module MyApp
    class Application < Rails::Application
        config.autoload_paths += %W( lib/ )
    end
end

Im Moment habe ich config.enable_dependency_loading Auf true gesetzt, aber ich frage mich, ob es eine bessere Lösung dafür gibt. Es muss einen Grund dafür geben, dass das automatische Laden in der Produktion standardmäßig deaktiviert ist.

108
Tobias

Das automatische Laden ist in der Produktionsumgebung aus Gründen der Threadsicherheit deaktiviert. Vielen Dank an @ Зелёный für den Link.

Ich habe dieses Problem gelöst, indem ich die lib-Dateien in einem lib -Ordner in meinem app -Verzeichnis abgelegt habe, wie am Github empfohlen. Jeder Ordner im Ordner app wird von Rails automatisch geladen.

29
Tobias

Meine Liste der Änderungen nach dem Wechsel zu Rails 5:

  1. Platziere lib dir in app, weil der gesamte Code in der App automatisch geladen wird in dev und eifrig geladen in prod und am wichtigsten ist automatisch geladen in der Entwicklung, so dass Sie nicht jeden Server neu starten müssen wenn Sie Änderungen vornehmen.
  2. Entfernen Sie alle require -Anweisungen, die auf Ihre eigenen Klassen in lib verweisen, da diese ohnehin alle automatisch geladen werden, wenn ihre Datei-/Verzeichnisnamen korrekt sind und wenn Sie require -Anweisungen verlassen, kann dies zu Fehlern führen Autoreloading. Weitere Infos hier
  3. Einstellen config.eager_load = true in allen Umgebungen, um Probleme beim Laden von Code in dev zu sehen.
  4. Verwenden Rails.application.eager_load! vor dem Spielen mit Threads, um "zirkuläre Abhängigkeit" -Fehler zu vermeiden.
  5. Wenn Sie Ruby/Rails-Erweiterungen haben, belassen Sie diesen Code im alten lib -Verzeichnis und laden Sie sie manuell vom Initializer. Dadurch wird sichergestellt, dass Erweiterungen geladen werden, bevor Ihre weitere Logik, die davon abhängen kann:

    # config/initializers/extensions.rb
    Dir["#{Rails.root}/lib/Ruby_ext/*.rb"].each { |file| require file }
    Dir["#{Rails.root}/lib/Rails_ext/*.rb"].each { |file| require file }
    
140
Lev Lukomsky

Ich habe gerade config.eager_load_paths Anstelle von config.autoload_paths Verwendet, um akostadinov im Github-Kommentar zu erwähnen: https://github.com/Rails/rails/issues/13142#issuecomment-27549207

# config.autoload_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('lib')

Es funktioniert auf Entwicklungs- und Produktionsumgebung.

Vielen Dank Johan für den Vorschlag, #{Rails.root}/lib Durch Rails.root.join('lib') zu ersetzen!

64

Es muss einen Grund dafür geben, dass das automatische Laden in der Produktion standardmäßig deaktiviert ist.

Hier ist eine lange Diskussion zu diesem Thema. https://github.com/Rails/rails/issues/13142

20
Зелёный

Dies ermöglicht das automatische Laden der Bibliothek und funktioniert auch in Produktionsumgebungen.

P.S. Ich habe meine Antwort geändert. Jetzt werden beide eifrigen Autoload-Pfade unabhängig von der Umgebung hinzugefügt, damit auch in benutzerdefinierten Umgebungen gearbeitet werden kann (z. B. Stage).

# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...
11
srghma

In gewisser Hinsicht ist hier ein einheitlicher Ansatz in Rails 5 zur Zentralisierung der Eager- und Autoload-Konfiguration. Gleichzeitig wird der erforderliche Autoload-Pfad hinzugefügt, wenn Eager-Load konfiguriert ist, da dies sonst nicht möglich ist richtig arbeiten:

# config/application.rb
...
config.paths.add Rails.root.join('lib').to_s, eager_load: true

# as an example of autoload only config
config.paths.add Rails.root.join('domainpack').to_s, autoload: true
...
4
pocheptsov

Für jemanden, der mit so etwas zu kämpfen hat, reicht es nicht aus, ein Verzeichnis unter app/ Zu platzieren. Ja, Sie werden automatisch geladen, dies ist jedoch nicht erforderlich beim erneuten Laden müssen die Namensraumkonventionen eingehalten werden .

Die Verwendung des Initialisierers zum Laden der alten Root-Ebene lib verhindert außerdem das erneute Laden der Funktion während der Entwicklung.

2
Abdullah Barrak

Durch das Verschieben des lib-Ordners in die App konnte ein Problem behoben werden, da meine Twitter-API in der Produktion nicht ausgeführt werden konnte. Ich hatte "nicht initialisierte Konstante TwitterApi" und meine Twitter-API befand sich in meinem lib-Ordner. Ich hatte config.autoload_paths += Dir["#{Rails.root}/app/lib"] in meiner application.rb, aber es hat nicht funktioniert, bevor der Ordner verschoben wurde.

Das hat den Trick gemacht

0
Laurie

um Levs Antwort zusammenzufassen: mv lib app reichte aus, um meinen gesamten lib Code automatisch laden/neu laden zu lassen.

(Rails 6.0.0beta3 sollte aber gut funktionieren auf Rails 5.x auch)

0
localhostdotdev