2

我在两个不同的目录中有两个文件:

module MyModule
  def my_method path
    p File.join (File.dirname __FILE__), path
  end
end

require_relative '../modules/mymodule' # definition of MyModule
class MyClass
  extend MyModule
  my_method 'my_file.yml'
end

我得到了类似的输出,my_home_dir/modules/my_file.yml但我希望它是定义的目录名称在哪里my_home_dir/files/my_file.ymlfilesMyClass

我知道我可以在调用时使用完整路径,my_method但是有没有办法让导入的文件仍然__FILE__设置为导入文件的名称?

基本上,my_method我需要拥有文件的完整路径,并且我只想传递一个相对于我的调用文件路径的路径。

4

2 回答 2

2

__FILE__always 是包含__FILE__变量的文件的名称,因此说my_method将始终返回my_method定义的位置,而不是MyClass调用它的位置。

您可能可以使用以下方式获取您想要的信息caller

module MyModule
  def my_method path
    p caller
  end
end

include MyModule # definition of MyModule
class MyClass
  extend MyModule
  my_method 'my_file.yml'
end

my_class = MyClass.new

哪个输出:

["test.rb:10:in `<class:MyClass>'", "test.rb:8:in `<main>'"]

编辑:

调用者数组只有没有路径的文件名......

好吧,我希望你知道如何解决这个问题,但是......

这是在 test.rb 中:

require './test2'
class MyClass
  extend MyModule
  my_method __FILE__, 'my_file.yml'
end

my_class = MyClass.new

这是在 test2.rb 中:

module MyModule
  def my_method path, file
    dir = File.dirname(path)
    p caller.map{ |c| File.join(dir, c) }
  end
end

运行 test.rb 输出:

["./test.rb:4:in `<class:MyClass>'", "./test.rb:2:in `<main>'"]
于 2013-01-21T21:34:25.120 回答
2

如果您可以传入一个块,则可以使用更简单的方法;使用块的绑定:

# In example.rb:
module Example
  def execute_if_main(&block)
    if $PROGRAM_NAME == eval("__FILE__", block.binding)
      yield
    end
  end
end

然后在测试文件中:

# in test.rb:
require_relative 'example.rb'

include Example

execute_if_main do
  puts "hi, I'm being loaded"
end

仅当 Ruby 解释器直接加载 test.rb 时,才会执行该块。如果 test.rb 是通过其他文件通过 require 加载的,那么最后的块将不会被执行(这就是想法)

于 2013-09-02T22:50:56.227 回答