it-swarm.com.de

Bester Weg, um Modul/Klasse aus dem lib-Ordner in Rails 3 zu laden?

Da die neueste Version von Rails 3 keine Module und Klassen aus lib mehr automatisch lädt, Was wäre der beste Weg, um sie zu laden?

Von github:

A few changes were done in this commit:

Do not autoload code in *lib* for applications (now you need to explicitly 
require them). This makes an application behave closer to an engine 
(code in lib is still autoloaded for plugins);
268
Vincent

Ab Rails 2.3.9 gibt es eine Einstellung in config/application.rb, in der Sie Verzeichnisse angeben können, die Dateien enthalten, die automatisch geladen werden sollen.

Von application.rb:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
248
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

Quelle: Rails 3 Quicktip: Lädt das lib-Verzeichnis einschließlich aller Unterverzeichnisse automatisch. Vermeiden Sie das langsame Laden von .

Bitte beachten Sie, dass die im lib-Ordner enthaltenen Dateien nur geladen werden, wenn der Server gestartet wird. Wenn Sie möchten, dass diese Dateien automatisch geladen werden, lesen Sie: Rails 3 Quicktip: Lädt lib-Ordner im Entwicklungsmodus automatisch neu. Beachten Sie, dass dies nicht für eine Produktionsumgebung gedacht ist, da das permanente Nachladen die Maschine verlangsamt.

196
thankful

Die Magie des Autoloadings

Ich denke, die Option zum Steuern der Ordner, aus denen das Autoloading-Material erstellt wird, wurde in anderen Antworten ausreichend behandelt. Falls jedoch jemand anderes Probleme hat, die Sachen geladen haben, obwohl die Autoload-Pfade nach Bedarf geändert wurden, versucht diese Antwort zu erklären, was die Magie hinter dieser Autoload-Sache ist.

Wenn es darum geht, Sachen aus Unterverzeichnissen zu laden, gibt es ein Gotcha oder eine Konvention, die Sie kennen sollten. Manchmal macht es die Ruby/Rails-Magie (dieses Mal meistens Rails) schwer zu verstehen, warum etwas passiert. Jedes in den Autoload-Pfaden deklarierte Modul wird nur geladen, wenn der Modulname dem Namen des übergeordneten Verzeichnisses entspricht. Also, falls Sie versuchen, in lib/my_stuff/bar.rb etwas einzutragen:

module Foo
  class Bar
  end
end

Es wird nicht automatisch geladen. Wenn Sie das übergeordnete Verzeichnis in foo umbenennen, hosten Sie Ihr Modul unter folgendem Pfad: lib/foo/bar.rb. Es wird für Sie da sein. Eine andere Option besteht darin, der Datei, die Sie automatisch laden möchten, den Namen des Moduls zu geben. Natürlich kann es dann nur eine Datei mit diesem Namen geben. Für den Fall, dass Sie Ihre Dateien in viele Dateien aufteilen müssen, können Sie natürlich diese eine Datei verwenden, um andere Dateien anzufordern. Ich empfehle das jedoch nicht, da Rails im Entwicklungsmodus diese anderen Dateien dann nicht automatisch automatisieren kann Laden Sie sie für Sie auf. Wenn Sie wirklich möchten, können Sie eine Datei mit dem Modulnamen haben, die dann die tatsächlich für die Verwendung des Moduls erforderlichen Dateien angibt. Sie könnten also zwei Dateien haben: lib/my_stuff/bar.rb und lib/my_stuff/foo.rb und die erstere wie oben und die letztere eine einzige Zeile enthalten: require "bar" und das würde genauso funktionieren.

P.S. Ich fühle mich gezwungen, noch eine wichtige Sache hinzuzufügen. Wann immer ich etwas im lib-Verzeichnis haben möchte, das automatisch geladen werden muss, neige ich dazu zu denken, dass, wenn ich etwas speziell für dieses Projekt entwickle (was normalerweise der Fall ist, das es eines Tages sein könnte) verwandeln sich in ein "statisches" Codefragment, das in vielen Projekten verwendet wird, oder ein git-Untermodul usw. In diesem Fall sollte es definitiv im lib-Ordner liegen. Dann ist sein Platz möglicherweise überhaupt nicht im lib-Ordner. Vielleicht sollte es sich in einem Unterordner unter dem App-Ordner befinden. · Ich habe das Gefühl, dass dies die neue Art von Rails ist. Offensichtlich ist die gleiche Magie überall dort, wo Sie Ihre Sachen in Ihre Autoload-Pfade einfügen, also ist es gut für diese Dinge. Jedenfalls sind dies nur meine Gedanken zu diesem Thema. Sie können nicht zustimmen. :)


UPDATE: Über die Art der Magie ..

Wie Severin in seinem Kommentar hervorhob, ist der Kern "Autoload a module mechanism" zwar sicher Teil von Ruby, aber das Autoload-Pfad-Zeug nicht. Sie brauchen Rails nicht, um autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar") zu tun. Und wenn Sie das Modul Foo zum ersten Mal referenzieren möchten, wird es für Sie geladen. Was jedoch Rails tut, gibt uns die Möglichkeit, Sachen automatisch aus registrierten Ordnern zu laden und zu laden. Dies wurde so implementiert, dass etwas von den Namenskonventionen angenommen werden muss. Wenn es nicht so implementiert worden wäre, müsste jedes Mal, wenn Sie auf etwas verweisen, das gerade nicht geladen ist, alle Dateien in allen Autoload-Ordnern durchlaufen und überprüft werden, ob eine von ihnen enthält, worauf Sie zu verweisen versuchten. Dies würde wiederum die Idee des automatischen Ladens und des automatischen Ladens zunichte machen. Mit diesen Konventionen kann jedoch von dem Modul/der Klasse abgezogen werden, wo versucht wird zu laden, wo dies definiert ist, und lädt es nur.

81
Timo

Achtung: Wenn Sie den "Affen-Patch" oder "Offene Klasse" aus Ihrem "lib" -Ordner laden möchten, verwenden Sie nicht den "Autoload" -Ansatz !!! 

  • " config.autoload_paths " Ansatz: funktioniert nur, wenn Sie eine Klasse laden, die nur an EINER Stelle definiert ist. Wenn eine Klasse bereits an anderer Stelle definiert wurde, können Sie sie mit dieser Methode nicht erneut laden.

  • " config/initializer/load_rb_file.rb " Ansatz: funktioniert immer! Was auch immer die Zielklasse ist eine neue Klasse oder ein "offener Klasse" oder "Affen-Patch" für vorhandene Klassen, es funktioniert immer! 

Weitere Informationen finden Sie unter: https://stackoverflow.com/a/6797707/445908

41

Sehr ähnlich, aber ich denke, das ist etwas eleganter:

config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]
28
Brian Armstrong

In meinem Fall habe ich versucht, einfach eine Datei direkt unter dem lib-Verzeichnis zu laden. 

Innerhalb von application.rb ...

require '/lib/this_file.rb' 

funktionierte nicht einmal in der Konsole und dann, als ich es versuchte 

require './lib/this_file.rb' 

und Rails lädt die Datei perfekt. 

Ich bin immer noch ziemlich noob und weiß nicht, warum das funktioniert, aber es funktioniert. Wenn jemand es mir erklären möchte, würde ich es sehr schätzen: D Ich hoffe, das hilft jemandem so oder so. 

14
Nick Res

Ich hatte das gleiche Problem. So habe ich es gelöst. Die Lösung lädt das lib-Verzeichnis und alle Unterverzeichnisse (nicht nur die direkten). Natürlich können Sie dies für alle Verzeichnisse verwenden.

# application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
7
hjuskewycz

config.autoload_paths funktioniert bei mir nicht. Ich löse es auf andere Weise

Ruby on Rails 3 lädt den Code (autoload) nicht automatisch aus dem Ordner/lib. Ich löse es durch Einfügen von ApplicationController

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 
5
msa7

Wenn nur bestimmte Dateien Zugriff auf die Module in lib benötigen, fügen Sie den Dateien, die sie benötigen, einfach eine Anforderung hinzu. Wenn beispielsweise ein Modell auf ein Modul zugreifen muss, fügen Sie Folgendes hinzu:

require 'mymodule'

am Anfang der Datei model.rb.

4
Mike Fischer

Ab Rails 5 wird empfohlen, den lib-Ordner unter dem App-Verzeichnis abzulegen oder stattdessen andere aussagekräftige Namensräume für den Ordner als services, presenters, features usw. zu erstellen und unter dem App-Verzeichnis für das automatische Laden durch Rails zu speichern.

Bitte überprüfen Sie auch diesen GitHub Discussion Link .

2
Ashik Salman

Es gibt mehrere Gründe, warum Sie Probleme beim Laden von lib haben könnten - siehe hier - http://www.williambharding.com/blog/technology/Rails-3-autoload-modules-and-classes-in-production/

  • autoload-Pfad korrigieren
  • threadsafe verwandt
  • benennung in Bezug
  • ...
1
Chris Kimpton

Schreibe den Dateinamen richtig.  

Ernst. Ich habe eine Stunde lang mit einer Klasse gekämpft, weil die Klasse Governance :: ArchitectureBoard war und die Datei in lib/governance/architecture_baord.rb war (transponiert O und A in "board").

Im Rückblick scheint es offensichtlich, aber es war der Teufel, der das aufspürte. Wenn die Klasse nicht in der Datei definiert ist, in der Rails erwartet, dass sie sich auf den Klassennamen stützt, wird sie einfach nicht gefunden. 

0
David Hempy