为Pathname子实现#absolute_path

时间:2017-01-03 19:34:03

标签: ruby oop

Pathname的一个实例是一个非常有用的对象,因为它响应了所有重要的消息。

例如,即使路径不存在,它也可以告诉您它是否是绝对路径:

some_path = Pathname.new("/some/nonexistent/path")
p some_path.absolute?
#=> true

它可以给你" absolute_path"如果磁盘上已存在路径,则使用方法realpath

another_path = Pathname.new("some/existing/path")
p another_path.realpath
#=> #<Pathname:/Users/max/Dropbox/work/tmp/abs_path/some/existing/path>

但如果路径已经存在realpath,那么

yet_another_path = Pathname.new("some/nonexistent/path")
p yet_another_path.realpath
# `realpath': No such file or directory @ realpath_rec - /Users/max/Dropbox/work/tmp/abs_path/some/nonexistent (Errno::ENOENT)

因此,我尝试实现另一个名为SomeDir的类,该类继承自Pathname并使用&#34;绝对路径响应absolute_path消息(如果存在的话)&# 34 ;.我不认为这太奇怪了,因为它有点像在原始不存在的路径名上调用to_s,除非它给出了absolute_path。

这是我的实施:

require 'pathname'
require 'fileutils'

class SomeDir < Pathname

  attr_reader :cwd_on_instantiation 
  def initialize path
    @cwd_on_instantiation = Dir.pwd 
    super
  end

  def absolute_path
    if exist?
      Pathname.new(to_s).realpath
    elsif absolute?
      Pathname.new(to_s)
    else
      Pathname.new(File.join(cwd_on_instantiation, to_s)) 
    end
  end
end

some_dir = SomeDir.new("some/nonexistent/path")
p some_dir.absolute_path
# #<Pathname:/Users/max/Dropbox/work/tmp/abs_path/some/nonexistent/path>

所以它似乎有效。

现在,我想知道:

  1. 在任何情况下,您都可以看到这不按预期工作吗?
  2. 如果没有absolute_path阻止,我将如何重新实施if...elsif..else方法?
  3. cwd_on_instantiation实例变量的更好名称是什么?
  4. 编辑:

    感谢@coreyward的代码示例。当我chdir时,它似乎无法正常工作:

    require 'pathname'
    require 'fileutils'
    include FileUtils
    
    class FileResolver
      BASE_DIR = Dir.pwd.freeze
    
      attr_reader :filepath
      def initialize(filepath)
        @filepath = filepath
      end
    
      def absolute_path
        Pathname.new(BASE_DIR).join(filepath)
      end
    end
    
    chdir "some" do 
      puts Dir.pwd # /Users/max/Dropbox/work/tmp/freeze_example/some
      yet_another_dir = FileResolver.new('nonexistent')
      p yet_another_dir.absolute_path
      #=> #<Pathname:/Users/max/Dropbox/work/tmp/freeze_example/nonexistent>
    end
    

    不确定为什么Dir.pwd.freeze没有拿起chdir "some"

1 个答案:

答案 0 :(得分:0)

您是否正在尝试为不存在的文件获取虚假路径?如果是这样,您可以通过使用.join并交付必要的组件来提供更好的服务:

Pathname.new(Dir.pwd).join("some/nonexistent/path")

如果您的文件存在,但您的路径字符串是一个片段,并且您需要为realpath提供另一个基本目录,那么您也可以这样做:

path = Pathname.new('/path/and/file.jpg')
path.realpath('some/existing')
#=> '/some/existing/path/and/file.jpg'

示例实现可能是......

class FileResolver
  BASE_DIR = Dir.pwd.freeze

  def initialize(filepath)
    @filepath = filepath
  end

  def absolute_path
    Pathname.new(BASE_DIR).join(@filepath)
  end
end

或者,如果您的文件不是相对于此类而是相对于您的Rails项目,则更好的方法是使用Rails.root.join

Rails.root.join('your/path', 'some/filename.txt')