Schienen 5: Laden Sie lib-Dateien in die Produktion

128

Ich habe eine meiner Apps von Rails 4.2.6 auf Rails 5.0.0 aktualisiert. Im Upgrade-Handbuch heißt es, dass die Autoload-Funktion jetzt in der Produktion standardmäßig deaktiviert ist.

Jetzt wird auf meinem Produktionsserver immer eine Fehlermeldung angezeigt, da ich alle lib-Dateien mit Autoload in die application.rbDatei lade .

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

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

Tobias
quelle
verrückte Sache, und die Dokumente sagen dir immer noch, dass du auto_load machen sollst. Ich war sehr verwirrt darüber, was in der Produktionsumgebung für eine neue App falsch läuft. Und seit ich mit Rails 5 gelernt habe, habe ich den Migrationsleitfaden nicht gelesen. Ich habe ein Dokumentproblem eingereicht, um dieses Problem hoffentlich zu lösen: github.com/rails/rails/issues/27268
akostadinov
1
Erstaunlicherweise habe ich zwei Dateien in libdir, eine Datei ist in Runtime leicht verfügbar, aber eine andere muss manuell benötigt werden: D
illusionist
@Tobias Mit welcher Lösung sind Sie gelandet?
Geoboy
@geoboy Ich gruppiere Code (wie Validators) in Ordnern direkt in der App / im Verzeichnis, da der Code dort automatisch geladen wird.
Tobias
Hier geht es um den richtigen Dateipfad und die richtige Klassendefinition in Rails 5.2: Dateipfad: Klassendefinitionapp/services/paylinx/paylinx_service.rb : module Paylinx class PaylinxService end end. Ich habe diese autoload_pathsSachen ausprobiert . funktioniert bei mir nicht
NamNamNam

Antworten:

161

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

  1. Platz lib dir in, appda der gesamte Code in der App automatisch in dev geladen und eifrig in prod geladen wird und vor allem in der Entwicklung automatisch geladen wird, damit Sie den Server nicht jedes Mal neu starten müssen, wenn Sie Änderungen vornehmen.
  2. Entfernen Sie alle requireAnweisungen, die auf Ihre eigenen Klassen verweisen, libda sie ohnehin requireautomatisch geladen werden, wenn ihre Datei- / Verzeichnisnamen korrekt sind. Wenn Sie Anweisungen hinterlassen , kann das automatische Laden unterbrochen werden. Mehr Infos hier
  3. Stellen Sie config.eager_load = truein allen Umgebungen ein, um Probleme beim Laden von Code in dev eifrig zu sehen.
  4. Verwenden Sie diese Option, Rails.application.eager_load!bevor Sie mit Threads spielen, um Fehler bei "zirkulären Abhängigkeiten" zu vermeiden.
  5. Wenn Sie Ruby / Rails-Erweiterungen haben, lassen Sie diesen Code im alten libVerzeichnis und laden Sie sie manuell vom Initialisierer. Dadurch wird sichergestellt, dass Erweiterungen vor Ihrer weiteren Logik geladen werden, 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 }
Lev Lukomsky
quelle
8
Wie benutzt man den libOrdner jetzt? Ich meine, libdir in appdir zu verschieben scheint eine Art Workaround zu sein.
Martin Svoboda
3
/app/lib/platzierte eine Datei / Klasse und es wird NICHT automatisch geladen. getestet in Schienen 5.1, neues Projekt
Tim Kretschmer
29
Es ist erwähnenswert, dass Sie den Frühling stoppen müssen. Ich habe alles nach app / lib / verschoben und mich dann ein wenig gefragt, warum ich meine Klassen immer noch nicht von der Konsole aus verwenden konnte. spring stop ftw :)
jacklin
1
Wohin würde die folgende Zeile gehenRails.application.eager_load!
Steven Aguilar
1
Dies mag funktionieren, ist aber nicht die beste Lösung. Die Ordnerstruktur ist ebenfalls semantisch. Dinge in libhaben eine andere wahrgenommene Nähe zum Projekt als Dinge im appVerzeichnis. Einige der anderen Antworten sind besser als diese.
CWitty
84

Ich habe nur Akostadinov im Github-Kommentar verwendet, config.eager_load_pathsanstatt ihn zu config.autoload_pathserwähnen: https://github.com/rails/rails/issues/13142#issuecomment-275492070

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

Es arbeitet in der Entwicklungs- und Produktionsumgebung.

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

Michał Zalewski
quelle
3
Klappt wunderbar. Die Syntax hat mir nicht gefallen, also habe ich sie geändert config.eager_load_paths << Rails.root.join('lib').
3limin4t0r
2
Für mich war das die beste Antwort. Mein Projekt begann auf Rails 5.2 von Grund auf neu und der Ordner / lib wurde immer noch außerhalb des Ordners / app erstellt. Ich habe keinen guten Grund gesehen, es zu bewegen.
Samir Haddad
1
Ja, das funktioniert! Scheint, dass Rails-Entwickler es wirklich genießen, Probleme beim Laden der Bibliothek zu verursachen: D bis zum nächsten Mal!
Damien Roche
To Rails 5.2 verwendet config.eager_load_paths += [Rails.root.join('lib')]stattdessen, weil config.eager_load_pathses sich um ein eingefrorenes Array handelt
William Wong Garay
@WilliamWongGaray config.eager_load_paths ist schreibgeschützt, wenn Sie versuchen, es im Initialisierer zu ändern. Wenn Sie Pfade hinzufügen application.rb, funktioniert dies mit beiden Methoden.
Michał Zalewski
31

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

Ich habe dieses Problem gelöst, indem ich die lib-Dateien in einem libOrdner in meinem appVerzeichnis gespeichert habe, wie auf Github empfohlen . Jeder Ordner im appOrdner wird automatisch von Rails geladen.

Tobias
quelle
6
Wenn Sie nicht durch einen langen Diskussionsthread über Github stöbern möchten, finden Sie hier eine ausführliche Erklärung: kollektividea.com/blog/archives/2016/07/22/…
Ernest
7
Ich habe verwendet config.eager_load_paths << "#{Rails.root}/lib", das ist besser IMO, um die empfohlene Rails-App-Struktur zu befolgen.
Akostadinov
2
Putting lib in app/libvon Schienen empfohlen Mitglieder github.com/rails/rails/issues/13142#issuecomment-275549669
eXa
4
Dies ruiniert völlig, was der Zweck libist. Ich würde warten, bis sich Tenderlove oder DHH einschalten. In der Zwischenzeit würde ich (persönlich) empfehlen, bei der Antwort von @Lev Lukomsky zu bleiben.
Josh Brody
@JoshBrody Meine Meinung ist jetzt, dass Sie das /libVerzeichnis überhaupt nicht brauchen sollten . Bibliotheken von Drittanbietern sind meistens Edelsteine, und wenn nicht, sollte ein Edelstein erstellt werden. Für andere Dateien erstelle ich bestimmte Ordner im /appVerzeichnis. Zum Beispiel validators.
Tobias
22

Es muss einen Grund geben, warum 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

Зелёный
quelle
1
Diese Diskussion ist die beste, wenn auch lange gelesene Informationsquelle zu dem Thema, auf das ich gestoßen bin.
Jason
12

Dies ermöglicht das automatische Laden von Bibliotheken und funktioniert auch in der Produktionsumgebung.

PS Ich habe meine Antwort geändert. Jetzt werden beide Pfade zum automatischen Laden unabhängig von der Umgebung erweitert, um auch in benutzerdefinierten Umgebungen (wie z. B. Stage) arbeiten zu können.

# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...
Srghma
quelle
2
Können Sie erläutern, warum dies das Problem behebt?
Stuart.Sklinar
@ Stuart.Sklinar Dies ermöglicht das automatische Laden von Bibliotheken und funktioniert auch in der Produktionsumgebung. PS Ich habe meine Antwort geändert, jetzt wird sie zu beiden eifrigen Autoload-Pfaden hinzugefügt, unabhängig von der Umgebung, um auch in benutzerdefinierten Umgebungen (wie Stage) arbeiten zu können
srghma
1
Könnten Sie erweitern (in Ihrer Antwort)? Nur-Code-Antworten helfen niemandem wirklich zu verstehen, warum es "so" gemacht werden sollte - ich sollte hinzufügen, dass ich kein Ruby-Entwickler bin, sondern nur dabei helfe, SO zu klären. Das Hinzufügen eines Kommentars zu einer "Nur-Code-Antwort" würde einen tatsächlichen Kontext ergeben.
Stuart.Sklinar
1
@ Stuart.Sklinar sicher
Srghma
5

Ändern Sie einfach config.autoload_paths in config.eager_load_paths in der Datei config / application.rb. Da in Rails 5 das automatische Laden für die Produktionsumgebung standardmäßig deaktiviert ist. Für weitere Details folgen Sie bitte dem Link .

 #config.autoload_paths << "#{Rails.root}/lib"
  config.eager_load_paths << Rails.root.join('lib')

Es funktioniert sowohl für die Umweltentwicklung als auch für die Produktion.

Jitendra Rathor
quelle
4

In gewissem Sinne gibt es in Rails 5 einen einheitlichen Ansatz zur Zentralisierung der Eifrig- und Autoload-Konfiguration. Gleichzeitig wird der erforderliche Autoload-Pfad hinzugefügt, wenn das Eifrig-Laden konfiguriert wird, da es sonst nicht ordnungsgemäß funktioniert:

# 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
...
pocheptsov
quelle
2

Für jeden, der wie ich damit zu kämpfen hat, reicht es nicht aus, nur ein Verzeichnis darunter zu platzieren app/. Ja, Sie erhalten ein automatisches Laden, aber kein erneutes Laden, für das die Namespace-Konventionen erfüllt sein müssen .

Durch die Verwendung des Initialisierers zum Laden der alten Root-Ebene libwird außerdem verhindert, dass die Funktion während der Entwicklung neu geladen wird.

Abdullah Barrak
quelle
0

Das Verschieben des lib-Ordners in die App hat zur Lösung eines Problems beigetragen. Meine Twitter-API wurde in der Produktion nicht ausgeführt. Ich hatte "konstantes TwitterApi nicht initialisiert" 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

Laurie
quelle
-6

um Levs Antwort zusammenzufassen: mv lib appwar genug, um meinen gesamten libCode automatisch laden / neu laden zu lassen.

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

localhostdotdev
quelle