Есть ли более короткий способ требовать файл в том же каталоге в ruby? - PullRequest
56 голосов
/ 25 апреля 2009

Есть ли более короткий способ требовать, чтобы файл находился в том же каталоге (где выполняется скрипт)?

require File.expand_path(File.dirname(__FILE__) + '/some_other_script')

Я читал, что require "my_script" и require "./my_script" фактически загрузят скрипт дважды (ruby не распознает, что это на самом деле один и тот же скрипт), и именно поэтому рекомендуется File.expand_path: если он используется Если скрипт требуется, он будет загружен только один раз.

Мне кажется странным, что лаконичный язык, такой как Ruby, кажется, не имеет более короткого решения. Например, Python просто имеет это:

import .some_other_module_in_the_same_directory

Полагаю, я мог бы подлатать обезьяну require ... но это просто зло! ; -)

Ответы [ 4 ]

90 голосов
/ 22 октября 2011

С ruby ​​1.9 вы можете использовать require_relative.

12 голосов
/ 26 апреля 2009

Просто требуется filename.

Да, он будет импортирован дважды, если вы укажете filename и ./filename, так что не делайте этого. Вы не указываете .rb, поэтому не указывайте путь. Обычно я помещаю большую часть логики приложения в файл в lib, а затем в bin пишу скрипт, который выглядит примерно так:

#!/usr/bin/env ruby

$: << File.join(File.dirname(__FILE__), "/../lib")
require 'app.rb'
App.new.run(ARGV)

Еще одним преимуществом является то, что мне проще выполнять модульное тестирование, если загрузка логики приложения не начинает автоматически его выполнять.

3 голосов
/ 25 апреля 2009

Поместите это в стандартный каталог библиотеки (где-то, который уже находится в вашем пути загрузки по умолчанию $:):

# 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 сделал его в путь загрузки.

Обратите внимание, что вам следует 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'
#...
3 голосов
/ 25 апреля 2009

Вышеописанное будет работать, даже если вы запускаете скрипт из какого-то другого каталога. Однако в том же каталоге более короткие формы, на которые вы ссылаетесь, работают должным образом и, по крайней мере, для ruby ​​1.9 не приведут к двойному требованию.

testa.rb

puts "start test A"
require 'testb'
require './testb'
puts "finish test A"

testb.rb

puts "start test B"
puts "finish test B"

запуск 'ruby testa.rb' приведет к:

start test A
start test B
finish test B
finish test A

Однако более длинная форма будет работать даже из другого каталога (например, ruby ​​somedir / script.rb)

...