57

是否有更短的方法来要求位于同一目录中的文件(作为正在执行的脚本)?

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

4 回答 4

100

从 ruby​​ 1.9 开始,您可以使用require_relative.

检查最新的文档require_relative其他版本的核心 API。

于 2011-10-22T19:40:16.113 回答
13

只需要filename.

filename是的,如果您将其指定为and ,它将导入两次./filename,所以不要这样做。您没有指定.rb,所以不要指定路径。我通常将我的大部分应用程序逻辑放到一个文件中lib,然后在其中有一个bin看起来像这样的脚本:

#!/usr/bin/env ruby

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

另一个优点是,如果加载应用程序逻辑没有自动开始执行它,我发现更容易进行单元测试。

于 2009-04-26T13:01:17.500 回答
3

即使您从其他目录运行脚本,上述内容也将起作用。但是,在同一目录中,您引用的较短形式按预期工作,至少对于 ruby​​ 1.9 不会导致双重要求。

testa.rb

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

测试b.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)

于 2009-04-25T12:55:53.170 回答
3

把它放在一个标准库目录中(某个地方已经在你的默认 loadpath 中$:):

# 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'
#...
于 2009-04-25T13:56:32.650 回答