论坛首页 Ruby版

对require的疑惑

浏览 2261 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
最后更新时间:2006-10-07
我的ruby代码的开发目录结构如下:

root
  - src
    a.rb
    b.rb
  - test
    - src
      test_a.rb
      test_b.rb


我的b.rb要依赖a.rb文件。
现在写成这样:
b.rc
require 'src/a'
...


test_a.rb
require 'src/a'



问题是,我不希望在b.rb里面require 'src/a'。因为一旦发布了的话,不一定还会存在一个src目录。但是require 'a'根本不行。因为运行test_a.rb的时候当前目录不是src。


查了一下解决方法,似乎可以用:

require "#{File.dirname(__FILE__)}/a"

这在b.rb里面是可以工作的(虽然感觉还不太舒服)

但是,在b_test.rb里面,这个就无法工作了。如果按照相对路径写成:
require "#{File.dirname(__FILE__)}/../../src/a"
也不成。

因为一个惊人的事实:

require仅仅保证同一个字符串代表的文件不会被load两次,test_a.rb里面的require和b.rb里面的require虽然实际上指向了同一个文件,但是因为字符串不同,文件仍然会被load两次!

晕了。到底怎样组织才对?莫非要象c++的#include一样要每个文件弄一个逻辑开关?

还是说必须把src目录加到$:变量中?
   
最后更新时间:2006-10-07
ajoo 写道


因为一个惊人的事实:

require仅仅保证同一个字符串代表的文件不会被load两次,test_a.rb里面的require和b.rb里面的require虽然实际上指向了同一个文件,但是因为字符串不同,文件仍然会被load两次!




如果真是这样,那这是一个 bug 啊,可以发到 ruby-talk 中去问问。
   
0 请登录后投票
最后更新时间:2006-10-07
对,改$:
脚本语言通常不用src目录,因为也没bin目录。按gem的一般习惯,源码放lib,test目录下的文件中开头可以这么干
$: << ("#{File.dirname(__FILE__)}/../lib") if __FILE__ == $0
   
0 请登录后投票
最后更新时间:2006-10-08
cookoo 写道
对,改$:
脚本语言通常不用src目录,因为也没bin目录。按gem的一般习惯,源码放lib,test目录下的文件中开头可以这么干
$: << ("#{File.dirname(__FILE__)}/../lib") if __FILE__ == $0


那么就是说,lib里面的文件互相引用就直接用"require 'a'"这种了?


可是,方便是方便,我怎么保证我的'a'不会和别人的'a'重名呢?java有很长的com.mycompany.myproject.myclass来减少名字冲突的情况,ruby里怎么搞?或者说,ruby会很聪明地先寻找该文件所在目录?(不知道怎么做这个, 如果Kernel::require用__FILE__,那么指向的不是我的文件,而是Kernel的文件,对么?)
   
0 请登录后投票
最后更新时间:2006-10-08
为了避免require路径里名字冲突,你可以在lib里构建以项目为名的目录,甚至可以学java那样com/mycompany/myproject这样搞三层目录嵌套,然后require 'com/mycompany/myproject/xxx',虽然没人搞这么复杂。

那个__FILE__判断是个保护措施而已,为了防止从外部require测试文件。
   
0 请登录后投票
最后更新时间:2006-10-08
uncutstone 写道
ajoo 写道


因为一个惊人的事实:

require仅仅保证同一个字符串代表的文件不会被load两次,test_a.rb里面的require和b.rb里面的require虽然实际上指向了同一个文件,但是因为字符串不同,文件仍然会被load两次!




如果真是这样,那这是一个 bug 啊,可以发到 ruby-talk 中去问问。

require就是这样设计的.by-design,不是bug。
   
0 请登录后投票
最后更新时间:2006-10-08
对了,说起gems,windows下因为默认设了rubygems的启动参数,所以require可以直接require一个gem而不是通过require_gem方法。其实gems是真正会出冲突的地方,核心库开发时要冲突早冲了。gems系统有一套自己的require系统,会判断gem的版本。为了减少可能的冲突我建议关掉那个参数,这样普通的require就不会require到一个gem了。
   
0 请登录后投票
最后更新时间:2006-10-08
这不算惊人的事实,请大大们看斧头书第二版某页……
   
0 请登录后投票
最后更新时间:2006-12-05
关于require,在Pickaxe上117页有脚注
2. This is not strictly true. Ruby keeps a list of the files loaded by require in the array $". However, this
list contains just the names of files as given to require. It’s possible to fake Ruby out and get the same file
loaded twice.
require '/usr/lib/ruby/1.9/English.rb'
require '/usr/lib/ruby/1.9/rdoc/../English.rb'
$" → ["/usr/lib/ruby/1.9/English.rb", "/usr/lib/ruby/1.9/rdoc/../English.rb"]
In this case, both require statements ended up pointing at the same file but used different paths to load it.
Some consider this a bug, and this behavior may well change in later releases.

在较新的ruby1.9中已经修正了这个bug
   
0 请登录后投票
最后更新时间:2006-10-10
njmzhang 写道


在较新的ruby1.9中已经修正了这个bug


果真是个 bug , 我的感觉还不错。呵呵
   
0 请登录后投票
论坛首页 Ruby版

跳转论坛:
JavaEye推荐