Was ist die beste Praxis , wenn ich will require
eine relative Datei in Ruby und ich möchte es in beiden 1.8.x arbeiten und> = 1.9.2?
Ich sehe einige Optionen:
- einfach
$LOAD_PATH << '.'
alles tun und vergessen - machen
$LOAD_PATH << File.dirname(__FILE__)
require './path/to/file'
- Überprüfen Sie, ob
RUBY_VERSION
<1.9.2, und definieren Sie dannrequire_relative
alsrequire
,require_relative
überall dort verwenden , wo es später benötigt wird - Überprüfen Sie, ob dies
require_relative
bereits vorhanden ist. Versuchen Sie in diesem Fall, wie im vorherigen Fall fortzufahren - Verwenden Sie seltsame Konstruktionen wie - leider scheinen sie in Ruby 1.9 nicht vollständig zu funktionieren, weil zum Beispiel:
require File.join(File.dirname(__FILE__), 'path/to/file')
$ cat caller.rb require File.join(File.dirname(__FILE__), 'path/to/file') $ cat path/to/file.rb puts 'Some testing' $ ruby caller Some testing $ pwd /tmp $ ruby /tmp/caller Some testing $ ruby tmp/caller tmp/caller.rb:1:in 'require': no such file to load -- tmp/path/to/file (LoadError) from tmp/caller.rb:1:in '<main>'
- Noch seltsamere Konstruktion: scheint zu funktionieren, ist aber seltsam und sieht nicht ganz gut aus.
require File.join(File.expand_path(File.dirname(__FILE__)), 'path/to/file')
- Verwenden Sie Backports Gem - es ist ziemlich schwer, es erfordert Rubygems-Infrastruktur und enthält Tonnen anderer Problemumgehungen, während ich nur
require
mit relativen Dateien arbeiten möchte .
Bei StackOverflow gibt es eine eng verwandte Frage , die einige weitere Beispiele enthält, aber keine klare Antwort gibt - was eine bewährte Methode ist.
Gibt es eine anständige, von allen akzeptierte universelle Lösung, mit der meine Anwendung sowohl auf Ruby <1.9.2 als auch auf> = 1.9.2 ausgeführt werden kann?
AKTUALISIEREN
Klarstellung: Ich möchte nicht nur Antworten wie "Sie können X machen" - tatsächlich habe ich die meisten fraglichen Entscheidungen bereits erwähnt. Ich möchte eine Begründung , dh warum es sich um eine bewährte Methode handelt, welche Vor- und Nachteile sie hat und warum sie unter den anderen ausgewählt werden sollte.
require
undrequire_relative
?a.rb
und den Interpreter dazu bringen möchten, den Inhalt der Dateib.rb
im aktuellen Verzeichnis zu lesen und zu analysieren (normalerweise das gleiche Verzeichnis wie beia.rb
), schreiben Sie einfachrequire 'b'
und dies ist in Ordnung, da der Standardsuchpfad das aktuelle Verzeichnis enthält. In modernerem Ruby 1.9 müssen Sierequire_relative 'b'
in diesem Fall schreiben , darequire 'b'
nur in Standardbibliothekspfaden gesucht wird. Das ist die Sache, die die Vorwärts- und Rückwärtskompatibilität für einfachere Skripte unterbricht, die nicht richtig installiert werden (z. B. Skripte selbst installieren ).backports
nur für verwendenrequire_relative
, siehe meine Antwort ...Antworten:
Eine Problemumgehung dafür wurde gerade zu dem Juwel "aws" hinzugefügt, also dachte ich, ich würde es teilen, da es von diesem Beitrag inspiriert wurde.
https://github.com/appoxy/aws/blob/master/lib/awsbase/require_relative.rb
Auf diese Weise können Sie
require_relative
wie in Ruby 1.9.2 in Ruby 1.8 und 1.9.1 verwenden.quelle
require_relative
Funktion ist in einem Erweiterungsprojekt für die Ruby-Kernbibliotheken enthalten, das Sie hier finden: rubyforge.org/projects/extensions Sie sollten in der Lage sein, sie mit zu installierengem install extensions
.require_relative
Fügen Sie dann in Ihrem Code die folgende Zeile vor dem hinzu : erfordern 'extensions / all' (bezogen auf Aurrils Beitrag hier )Bevor ich zu 1.9.2 gesprungen bin, habe ich Folgendes für relative Anforderungen verwendet:
Es ist ein bisschen komisch, wenn man es zum ersten Mal sieht, weil es so aussieht, als gäbe es am Anfang ein zusätzliches '..'. Der Grund ist, dass
expand_path
ein Pfad relativ zum zweiten Argument erweitert wird und das zweite Argument so interpretiert wird, als wäre es ein Verzeichnis.__FILE__
offensichtlich ist kein Verzeichnis, aber das spielt keine Rolle , daexpand_path
ist es egal , ob die Dateien vorhanden ist oder nicht, es wird nur einige Regeln anwenden zu erweitern Dinge wie..
,.
und~
. Wenn Sie über das anfängliche "waitaminute" hinwegkommen können, gibt es dort kein Extra..
? Ich denke, dass die obige Zeile ganz gut funktioniert.Dass unter der Annahme
__FILE__
ist/absolute/path/to/file.rb
, was passiert ist , dassexpand_path
die Zeichenfolge wird konstruieren/absolute/path/to/file.rb/../relative/path
und dann eine Regel anwenden , die besagen , dass..
sollte die Pfadkomponente , bevor es (entfernenfile.rb
in diesem Fall), Rückkehr/absolute/path/to/relative/path
.Ist das Best Practice? Kommt darauf an, was du damit meinst, aber es scheint, als ob es überall in der Rails-Codebasis ist, also würde ich sagen, dass es zumindest eine allgemein verbreitete Redewendung ist.
quelle
Die Spitzhacke hat dafür einen Ausschnitt für 1.8. Hier ist es:
Es verwendet im Grunde nur das, was Theo geantwortet hat, aber Sie können es trotzdem verwenden
require_relative
.quelle
$RUBY_VERSION
oder überprüfen, obrequire_relative
direkt vorhanden?require_relative
definiert ist.Es ist keine gute Sicherheitsgewohnheit: Warum sollten Sie Ihr gesamtes Verzeichnis verfügbar machen?
Dies funktioniert nicht, wenn RUBY_VERSION <1.9.2
Sie haben bereits geantwortet, warum dies nicht die besten Optionen sind.
Dies mag funktionieren, aber es gibt einen sichereren und schnelleren Weg: um mit der LoadError-Ausnahme umzugehen:
quelle
Ich bin ein Fan von der Verwendung des Edelsteins rbx-require-relative ( Quelle ). Es wurde ursprünglich für Rubinius geschrieben, unterstützt aber auch MRI 1.8.7 und macht in 1.9.2 nichts. Das Erfordernis eines Edelsteins ist einfach und ich muss keine Codefragmente in mein Projekt werfen.
Fügen Sie es Ihrem Gemfile hinzu:
Dann
require 'require_relative'
vor dirrequire_relative
.Zum Beispiel sieht eine meiner Testdateien folgendermaßen aus:
Dies ist die sauberste Lösung unter diesen IMOs, und der Edelstein ist nicht so schwer wie Backports.
quelle
Das
backports
Edelstein ermöglicht nun das individuelle Laden von Backports.Sie könnten dann einfach:
Dies
require
hat keine Auswirkungen auf neuere Versionen und aktualisiert auch keine anderen integrierten Methoden.quelle
Eine andere Möglichkeit besteht darin, dem Interpreter mitzuteilen, welche Pfade gesucht werden sollen
quelle
Ein Problem, auf das ich bei den auf __FILE__ basierenden Lösungen nicht hingewiesen habe, ist, dass sie in Bezug auf Symlinks nicht funktionieren. Sagen Sie zum Beispiel, ich habe:
Das Hauptskript, der Einstiegspunkt, die Anwendung ist foo.rb. Diese Datei ist mit ~ / Scripts / foo verknüpft, das sich in meinem $ PATH befindet. Diese require-Anweisung ist fehlerhaft, wenn ich 'foo' ausführe:
Da __FILE__ ~ / Scripts / foo ist, sucht die obige Anweisung require nach ~ / Scripts / foo / lib / someinclude.rb, das offensichtlich nicht existiert. Die Lösung ist einfach. Wenn __FILE__ eine symbolische Verknüpfung ist, muss sie dereferenziert werden. Der Pfadname # realpath hilft uns in dieser Situation:
quelle
Wenn Sie einen Edelstein bauen würden, würden Sie den Ladepfad nicht verschmutzen wollen.
Bei einer eigenständigen Anwendung ist es jedoch sehr praktisch, das aktuelle Verzeichnis wie in den ersten beiden Beispielen zum Ladepfad hinzuzufügen.
Meine Stimme geht an die erste Option auf der Liste.
Ich würde gerne solide Ruby Best Practices-Literatur sehen.
quelle
Ich würde meine eigene definieren,
relative_require
wenn sie nicht existiert (dh unter 1.8) und dann überall dieselbe Syntax verwenden.quelle
Ruby on Rails Weg:
quelle