27

在 ruby​​ 程序中管理 require 路径的最佳方法是什么?

让我举一个基本的例子,考虑如下结构:

\MyProgram

\MyProgram\src\myclass.rb

\MyProgram\test\mytest.rb

如果在我的测试中使用require '../src/myclass',那么我只能从\MyProgram\test文件夹调用测试,但我希望能够从任何路径调用它!

我想出的解决方案是在所有源文件中定义以下行:

ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(ROOT)然后总是使用require "#{ROOT}/src/myclass"

有更好的方法吗?

4

7 回答 7

32

从 Ruby 1.9 开始,您可以使用require_relative来执行此操作:

require_relative '../src/myclass'

如果您在早期版本中需要此功能,您可以根据此 SO 注释从扩展 gem 中获取它。

于 2010-09-10T13:31:07.803 回答
12

这是一个稍微修改的方法:

$LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), "..", "src"))

通过将源路径添加到 $LOAD_PATH(又名 $:),您不必在需要代码时明确提供根等,即 require 'myclass'

于 2009-05-26T11:32:20.823 回答
9

同样,噪音较小的恕我直言:

$:.unshift File.expand_path("../../src", __FILE__)
require 'myclass'

要不就

require File.expand_path "../../src/myclass", __FILE__

在 (Debian) Linux 上使用 ruby​​ 1.8.7 和 1.9.0 进行测试 - 请告诉我它是否也适用于 Windows。

为什么标准库中没有内置更简单的方法(例如'use'、'require_relative'或sg)?更新:require_relative 从 1.9.x 开始就存在

于 2009-11-07T02:38:04.627 回答
2

使用以下代码要求特定文件夹中的所有“rb”文件(=> Ruby 1.9):

path='../specific_folder/' # relative path from current file to required folder

Dir[File.dirname(__FILE__) + '/'+path+'*.rb'].each do |file|
  require_relative path+File.basename(file) # require all files with .rb extension in this folder
end
于 2011-01-03T17:02:56.733 回答
2
Pathname(__FILE__).dirname.realpath

以动态方式提供绝对路径。

于 2010-12-01T14:57:49.070 回答
1

sris 的答案是标准方法。

另一种方法是将您的代码打包为 gem。然后 ruby​​gems 将负责确保您的库文件在您的路径中。

于 2009-05-26T11:38:22.933 回答
0

这就是我最终得到的——一个 Ruby 版本的setenvshell 脚本:

  # Read application config                                                       
$hConf, $fConf = {}, File.expand_path("../config.rb", __FILE__)
$hConf = File.open($fConf) {|f| eval(f.read)} if File.exist? $fConf

  # Application classpath                                                         
$: << ($hConf[:appRoot] || File.expand_path("../bin/app", __FILE__))

  # Ruby libs                                                                     
$lib = ($hConf[:rubyLib] || File.expand_path("../bin/lib", __FILE__))
($: << [$lib]).flatten! # lib is string or array, standardize                     

然后我只需要确保这个脚本在其他任何事情之前被调用一次,并且不需要接触各个源文件。

我在配置文件中放置了一些选项,例如外部(非 gem)库的位置:

# Site- and server specific config - location of DB, tmp files etc.
{
  :webRoot => "/srv/www/myapp/data",
  :rubyLib => "/somewhere/lib",
  :tmpDir => "/tmp/myapp"
}

这对我来说效果很好,只需更改配置文件中的参数,我就可以在多个项目中重用 setenv 脚本。比 shell 脚本更好的选择,IMO。

于 2009-11-12T12:11:12.990 回答