如何在ruby中获取源代码文本?

时间:2011-12-29 09:56:50

标签: ruby

受到运行时编辑源代码的一些lisp魔力的启发,

我想用红宝石做。看起来我无法从方法/类中获取源代码, 有办法吗?

我在这里写了一个示例源代码:

def helloworld n
  "hello #{n}"
end

o = Kernel.method :helloword

Kernel.define_singleton_method o.name do |n|
  eval o.source_code.sub('hello', 'hello world')
end

helloworld 'halida' #=> 'hello world halida'

3 个答案:

答案 0 :(得分:0)

您无法获取代码的一部分的字符串表示,编辑它并期望Ruby重新评估您的更改。实现所需功能的唯一方法是使用ParseTree获取源代码的s表达式,编辑并使用{​​{1}}生成一串ruby代码。他们将Ruby2Rubydef ...添加到字符串中并使用它调用eval。

在现实世界中,它太难以且容易出错。但我不知道其他任何方式。

注意:ParseTree仅适用于Ruby 1.8。

答案 1 :(得分:0)

看一下method_source gem。它由pry REPL用于show-method命令。

看起来这个gem使用标准Method#source_location(在Ruby 1.9中可用)来定位方法并获取其源代码。显然,它不适用于动态定义的方法和C方法。有关详细信息,请参阅文档。

答案 2 :(得分:0)

您可以轻松地获取Ruby中方法的源代码。

想象一下以下假设课程:

class Klass
  def self.foo
    :foo
  end

  def bar
    :bar
  end
end

如您所见,此类有两种方法:

  • 一个类方法.foo
  • 实例方法#bar

使用.method.instance_method以编程方式访问它们:

m1 = Klass.method :foo
=> #<Method: Klass.foo>

m2 = Klass.instance_method :bar
=> #<UnboundMethod: Klass#bar>

您可以使用.source方法查看其源代码:

puts m1.source
  def self.foo
    :foo
  end
=> nil

puts m2.source
  def self.bar
    :bar
  end
=> nil

因为Ruby有开放类和动态加载,你也可以添加或 在运行时更改方法。只需重新打开课程并重新定义方法:

Klass.foo
=> :foo

class Klass
  def self.foo
    :foobar
  end
end

Klass.foo
=> :footer

以前在课程中定义的其他方法将不受影响:

Klass.bar
=> :bar

警告:在运行时重新定义类行为(也称为“Monkey Patching”) 是一个非常强大的工具,它也可能有点危险。当前版本的Ruby 支持一种更加可控的方式来实现这种称为“改进”的方法。

你可以learn more about using refinements here