Почему относительный путь не работает в Ruby
Я начинаю изучать Ruby, одна вещь, которую я не понимаю, почему относительный путь для директивы require не работает в ruby. Это то, что работает почти на каждом языке сценариев, который я сейчас (JSP, PHP...). Я объясню с реальным примером. У меня есть папка с именем фигуры, которая содержит 3 класса форма, прямоугольник и квадрат. У меня есть еще один файл test_shapes.rb, откуда я звоню и тестирую свои классы. Когда я импортирую свои классы в основной файл следующим образом:
require "./shape"
require "./rectangle"
require "./square"
Я получил ошибку для не найденных файлов. Когда я включаю имя моей подпапки, например:
require "./shapes/shape"
require "./shapes/rectangle"
require "./shapes/square"
Код отлично работает. Потому что я указал весь путь к корневому каталогу проекта (папка lib, я думаю). Когда я включаю, я включаю абсолютный путь к жесткому диску, например:
require "#{File.dirname(__FILE__)}/shape"
require "#{File.dirname(__FILE__)}/rectangle"
require "#{File.dirname(__FILE__)}/square"
Он отлично работает.
Итак, я просто хочу объяснить, почему первый метод импорта (относительный путь к текущей папке) не работает.
Ответы
Ответ 1
Относительный путь основан на рабочем каталоге. Я предполагаю, что есть основной файл в том же каталоге. Если вы запустите ruby ./shapes/main.rb
в корне проекта, ruby попытайтесь найти {project_root}/shape.rb
, а не {project_root}/shapes/shape.rb
. Это не работает.
Вам нужно использовать require_relative
, как показано ниже.
# {project_root}/shapes/main.rb
require_relative './shape'
require_relative './rectangle'
require_relative './square'
Ответ 2
Вы используете относительный путь. И они относятся к тому месту, где выполняется ваш script. Вообще это плохая идея. Вы должны использовать либо абсолютный путь, либо относительный путь к точному файлу, где выполняется require
.
require File.expand_path("../shape", __FILE__)
PS: require_relative выглядит более лаконичным
Ответ 3
require (name) → true или false
Загружает заданное имя, возвращая true, если успешно и false, если функция уже загружена.
Если имя файла не разрешено к абсолютному пути, оно будет искать в каталогах, перечисленных в $LOAD_PATH ($:).
Если имя файла имеет расширение ".rb", оно загружается в качестве исходного файла; если расширение ".so", ".o" или ".dll" или расширение общей библиотеки по умолчанию на текущей платформе, Ruby загружает общую библиотеку в качестве расширения Ruby. В противном случае Ruby пытается добавить ".rb", ".so" и т.д. К имени до его обнаружения. Если имя файла не найдено, будет добавлен LoadError.
Для расширений Ruby указанное имя файла может использовать любое расширение общей библиотеки. Например, в Linux расширение сокета - "socket.so" и требует, чтобы "socket.dll" загрузил расширение сокета.
Абсолютный путь загруженного файла добавляется к $LOADED_FEATURES ($ "). Файл не будет загружен снова, если его путь уже появился в $. Например, требуется" a"; require './a' не будет загружать a.rb снова.
требуется "my-library.rb"
требуется "db-driver"
Любые константы или глобалы в загруженном исходном файле будут доступны в глобальном пространстве имен вызывающих программ. Однако локальные переменные не будут распространяться в среду загрузки.
require_relative (строка) → true или false
Ruby пытается загрузить библиотеку с именем string относительно требуемого пути к файлу. Если путь к файлам не может быть определен, LoadError будет поднят. Если файл загружен, возвращается true и false в противном случае.
Ссылка: http://ruby-doc.org/core-2.1.2/Kernel.html#require-method