Durch Hinzufügen von lib zu 'config.autoload_paths' in Rails 3 wird mein Modul nicht automatisch geladen

73

Ich lege einen Dateinamen g.rb in den Seitenordner. Rails.root/libDer Dateiinhalt ist wie folgt:

module Google
end

Dann füge ich hinzu

config.autoload_paths += %W(#{config.root}/lib #{Rails.root}/app/delayed_jobs)

zu meinem Rails.root/config/application.rb

Wenn ich jedoch versuche, Google von aufzurufen rails console, wird eine Ausnahme ausgelöst. Die Ausnahme verschwindet nur, wenn ich ausführe require 'google'. Warum? Sollte meine Datei nicht automatisch geladen werden und sollte ich nicht ohne zusätzliche requireAnweisung auf das Modul zugreifen ?

Phương Nguyễn
quelle

Antworten:

113

Hmm, ich habe eine interessante Sache entdeckt. Damit Rails meine Klasse automatisch laden kann, muss der Klassenname mit dem Dateinamen und der Ordnerstruktur übereinstimmen. Wenn ich beispielsweise möchte, dass das Google-Modul google.rbautomatisch geladen wird , muss ich es direkt unter / lib einfügen (falls ich das automatische Laden von / lib angibte). Wenn ich automatisch laden möchte Google::Docs, platziere ich es entweder in google.rbodergoogle/docs.rb

Phương Nguyễn
quelle
6
Ist das also ein Fehler oder eine Konvention?
Blankman
8
Ich glaube, das ist Konvention. Rails nimmt konstante Namen und macht daraus Pfade. :: wird zu diesem Zweck in / umgewandelt. So wird aus Google :: Docs google / docs.rb. Sie könnten die Nützlichkeit davon diskutieren, aber das ist mein Verständnis der aktuellen Funktionalität.
Ben Hamill
3
Es ist keine Konvention an sich, es ist die Art und Weise, wie der Ruby-Interpreter nach Dingen sucht, soweit ich weiß
Ghoti
1
Wow, das ist mir gerade passiert. Die Konvention interessiert mich nicht wirklich, ich kann meine Module umbenennen. Ich hätte das einfach nie gedacht. +1.
Squarism
3
Es ist eine Rails-Konvention, keine Ruby-Konvention
Yarin
27

Ich hatte ein ähnliches Problem damit, mein Modul auf Heroku laufen zu lassen. Zusätzlich zu der von Stephen C angegebenen Autoload-Namenskonvention stellte ich fest, dass der Modulcode requireaufgrund einer threadsafeAnnahme der Rails-Produktionsumgebung auf Heroku erstellt werden muss (obwohl dies threadsafein meiner production.rbKonfigurationsdatei auskommentiert wurde) Da ich requiredie Moduldatei vor dem Aufrufen includedes Moduls erstellt hatte, begann alles zu funktionieren.

require 'mymodule'
include Mymodule

Bitte werfen Sie einen Blick auf diesen ausgezeichneten Artikel zum Thema, dass Module in Heroku (Produktion) korrekt geladen werden.

Don Leatham
quelle
+1 Dies sollte die akzeptierte Antwort sein. Der Link sollte jedem helfen und Thread-Sicherheit war eigentlich mein Problem. Vielen Dank.
Erik B
24

Das liegt daran, dass beim Autoload nicht alles im Voraus "verlangt" werden muss (Startstrafe). Klassen werden nach Bedarf geladen / referenziert. Dazu müssen Sie wissen, wo Sie nach der Klasse suchen müssen. Andernfalls müssten Sie jede Datei im Autoload-Verzeichnis im Voraus laden, um zu sehen, welche Klassen deklariert sind. Es ist ein Kompromiss, aber alles im Voraus zu verlangen (wie Marbaq vorschlägt), ist kein automatisches Laden. Sie können den von Ruby bereitgestellten Befehl autoload verwenden, der zwei Argumente verwendet, das zu ladende Modul (symbolisiert, dh in Ihrem Fall Google), und das zweite Argument ist der Dateiname, der g.rb wäre, wenn sich lib in Ihrem befindet Ladepfad ($ :). Informationen zum automatischen Laden finden Sie in den Ruby-Dokumenten.

Stephen C.
quelle
1
Übrigens, Konvention besagt, dass Sie lib / g.rb einfach in lib / google.rb umbenennen und auf dem Weg sein sollten.
Stephen C
1

Ich hatte gerade das gleiche Problem und meine "Lösung" (oder besser gesagt die Problemumgehung) bestand darin, jede benötigte Datei von Rails.root / lib in meiner application.rb manuell anzufordern.

require 'lib/message'
require 'lib/store'
require 'lib/vault/vault.rb'
require 'lib/custom_loggers'

module MyApplication
  class Application < Rails::Application

Mein nächster Schritt wäre, die Dateien in Modulordnern zu kategorisieren, wie Sie erwähnen.

Fredrik Boström
quelle
Hallo @morbaq, heute hatte ich das gleiche Problem und Ihre Lösung funktioniert perfekt, wollte nur Danke sagen: D
sameera207
-5

Ich habe diese Lösung vor kurzem gefunden

config / application.rb

module AppName
  class Application < Rails::Application

    # Custom directories with classes and modules you want to be autoloadable.
    config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]
    config.autoload_paths += Dir[Rails.root.join('app', 'lib', 'extensions')] 

  end
end

Der erste Konfigurationsaufruf veranlasst Rails, alle Unterverzeichnisse des Verzeichnisses app / models automatisch zu laden, sodass ich jetzt /app/models/sub_directory/model.rb automatisch laden kann (praktisch zum Organisieren einer App mit einer großen Codebasis).

Der zweite Konfigurationsaufruf veranlasst Rails, das Verzeichnis lib / extensions automatisch zu laden

hoffe das hilft

Hinweis: Ich glaube, dies ist Rails 3 spezifisch

ben.m
quelle