我有一个像这样的代码的宝石:
def read(file)
@file = File.new file, "r"
end
现在的问题是,你有一个像这样的目录结构:
app/main.rb
app/templates/example.txt
和main.rb
包含以下代码:
require 'mygem'
example = MyGem.read('templates/example.txt')
它出现了File Not Found: templates/example.txt
。如果example.txt
与main.rb
位于同一目录中,则会起作用,但如果它位于目录中则不行。为了解决这个问题,我在relative_to
中添加了一个名为read()
的可选参数。这需要一个绝对路径,所以上面可能需要:
require 'mygem'
example = MyGem.read('templates/example.txt', File.dirname(__FILE__))
工作正常,但我认为这有点难看。无论如何都要这样做,以便类知道调用哪个文件read()
并根据它来计算路径?
答案 0 :(得分:4)
有一个有趣的图书馆 - i told you it was private。人们可以用它从外面调用来保护他们的方法。代码找到调用方法的文件并将其删除。使用以下行找到罪犯:
offender = caller[0].split(':')[0]
我猜您可以在MyGem.read代码中使用它:
def read( file )
fpath = Pathname.new(file)
if fpath.relative?
offender = caller[0].split(':')[0]
fpath = File.join( File.dirname( offender ), file )
end
@file = File.new( fpath, "r" )
end
这样你就可以使用相对于你的Mygem调用者而不是pwd的路径。正是您在app/main.rb
答案 1 :(得分:2)
嗯,你可以使用来电,比其他人说的更可靠。
在您的gem文件中,在任何类或模块之外,请输入:
c = caller
req_file = nil
c.each do |s|
if(s =~ /(require|require_relative)/)
req_file = File.dirname(File.expand_path(s.split(':')[0])) #Does not work for filepaths with colons!
break
end
end
REQUIRING_FILE_PATH = req_file
这将在90%的时间内工作,除非要求脚本执行Dir.chdir。 File.expand_path依赖于此。我担心,除非你的要求者通过__FILE__
,否则如果他们改变了工作目的,你就无能为力。
答案 2 :(得分:1)
您也可以查看caller:
def read(file)
if /^(?<file>.+?):.*?/ =~ caller(1).first
caller_dir, caller_file = Pathname.new(Regexp.last_match[:file]).split
file_with_path = File.join caller_dir, file
@file = File.new "#{file_with_path}", "r"
end
end
我不建议您这样做(由于caller(1)
,上面的代码会间接调用,因为请参阅caller
上的文档。此外,如果调用者路径旨在包含冒号,则应更准确地调整上述正则表达式。
答案 3 :(得分:1)
这应该适用于典型用途(我不确定它对间接使用的抵抗力,如madusobwa above所述):
def read_relative(file)
@file = File.new File.join(File.dirname(caller.first), file)
end
另外,请考虑添加方法的块形式,以便在屈服后关闭文件。在当前形式中,您迫使客户使用ensure
包装他们对宝石的使用。
答案 4 :(得分:1)
接受文件路径String作为参数。转换为Pathname对象。检查路径是否相对。如果是,则转换为绝对。
def read(file)
fpath = Pathname.new(file)
if fpath.relative?
fpath = File.expand_path(File.join(File.dirname(__FILE__),file))
end
@file = File.new(fpath,"r")
end
您可以使此代码更简洁(更简洁)。