重新定义File :: dirname ruby​​方法

时间:2009-09-30 02:47:13

标签: ruby

我正在尝试重新定义File.dirname方法,首先将%20s更改为空格。但以下给我一个错误

class File
   old_dirname = instance_method(:dirname)    

   define_method(:dirname) { |s|
       s = s.gsub("%20"," ")
       old_dirname.bind(self).call(s)
   }
end

这会导致一个NameError异常:类'File'的未定义方法'dirname'

这样做的正确方法是什么?

3 个答案:

答案 0 :(得分:4)

正如Chuck已经写过的,File::dirnameFile类对象的单例方法(或者更准确地说是File类对象的元类的实例方法),而不是实例方法File班。

所以,你必须打开File的元类,而不是File类本身:

#!/usr/bin/env ruby

class << File
  old_dirname = instance_method :dirname

  define_method :dirname do |*args|
    old_dirname.bind(self).(*args).gsub '%20', ' '
  end
end

require 'test/unit'
class TestFileDirname < Test::Unit::TestCase
  def test_that_it_converts_percent20_to_space
    assert_equal '/foo bar/baz', File.dirname('/foo%20bar/baz/quux.txt')
  end
end

但是,我同意@sheldonh:这违反了File::dirname的API合约。

答案 1 :(得分:3)

小心点。

您正在改变方法的行为,而不仅仅是其实现。这通常是不好的做法,因为它削弱了API作为可靠合同的价值。

相反,请考虑将输入转换为接近接收点。

答案 2 :(得分:1)

dirname是File的类方法,而不是实例方法,因此您只需定义一个新的实例方法。此外,别名方法的惯用方法是使用alias。所以:

class <<File
  alias old_dirname dirname
  def dirname(f)
    old_dirname(f.gsub("%20", " "))
  end
end

class <<whatever语法将方法添加到单个对象 - 在本例中为File类。