Ответ 1
С ruby 1.9 вы можете использовать require_relative
.
Есть ли более короткий способ потребовать файл, расположенный в той же директории (как выполняется script)?
require File.expand_path(File.dirname(__FILE__) + '/some_other_script')
Я читал, что require "my_script"
и require "./my_script"
будут дважды загружать script (рубин не признает, что он фактически тот же script), и именно поэтому рекомендуется File.expand_path
: if он используется каждый раз, когда требуется script, тогда он будет загружен только один раз.
Мне кажется странным, что краткий язык, такой как Ruby, кажется, не имеет более короткого решения. Например, python просто имеет это:
import .some_other_module_in_the_same_directory
Думаю, я мог бы обезьян-патч require
... но это просто зло!; -)
С ruby 1.9 вы можете использовать require_relative
.
Просто введите filename
.
Да, он будет импортировать его дважды, если вы укажете его как filename
и ./filename
, поэтому не делайте этого. Вы не указываете .rb
, поэтому не указываете путь. Я обычно добавляю основную часть моей логики приложения в файл в lib
, а затем script в bin
выглядит примерно так:
#!/usr/bin/env ruby
$: << File.join(File.dirname(__FILE__), "/../lib")
require 'app.rb'
App.new.run(ARGV)
Еще одно преимущество заключается в том, что мне легче выполнять модульное тестирование, если загрузка логики приложения не запускается автоматически.
Вышеупомянутое будет работать, даже если вы запускаете script из другого каталога. Однако внутри одного и того же каталога более короткие формы, на которые вы ссылаетесь, работают как ожидалось, и, по крайней мере, для ruby 1.9 не приведет к двойному требованию.
puts "start test A"
require 'testb'
require './testb'
puts "finish test A"
puts "start test B"
puts "finish test B"
running 'ruby testa.rb' приведет к:
start test A
start test B
finish test B
finish test A
Однако более длинная форма будет работать даже из другого каталога (например, ruby somedir/ script.rb)
Поместите это в стандартный каталог библиотеки (где-то уже в пути загрузки по умолчанию $:
):
# push-loadpath.rb
if caller.first
$: << File.expand_path(File.dirname(caller.first))
end
Затем это должно работать
% ls /path/to/
bin.rb lib1.rb lib2.rb #...
% cat /path/to/bin.rb
load 'push-loadpath.rb'
require 'lib1'
require 'lib2'
#...
caller
дает вам доступ к текущему столу вызова и сообщает вам, какой файл и где, поэтому push-loadpath.rb
использует это, чтобы добавить файл, который load
'd это в путь загрузки.
Обратите внимание, что вы должны load
файла, а не require
его, чтобы тело можно было вызвать несколько раз (один раз для каждого раза, когда вы хотите изменить путь загрузки).
В качестве альтернативы вы можете обернуть тело методом,
# push-loadpath.rb
def push_loadpath
$: << File.expand_path(File.dirname(caller.first))
end
Это позволит вам require
его и использовать его следующим образом:
% ls /path/to/
bin.rb lib1.rb lib2.rb #...
% cat /path/to/bin.rb
require 'push-loadpath'
push_loadpath
require 'lib1'
require 'lib2'
#...