不,你不能这样做。
cmets 的全部意义在于它们不是程序的一部分!如果您想要一个字符串作为程序的一部分,只需使用字符串即可。
在大多数 Ruby 实现中,cmets 已经在词法分析器中被丢弃,这意味着它们甚至无法到达 解析器,更不用说 解释器 或编译器了。在代码运行时,cmets 早已不复存在……事实上,在 Rubinius 或 YARV 等使用编译器的实现中,根本没有办法将 cmets 存储在编译后的可执行文件中,所以即使它们没有被抛出远离词法分析器或解析器,仍然无法将它们传达给运行时。
因此,您几乎唯一的机会就是解析 Ruby 源文件以提取 cmets。但是,就像我上面提到的那样,您不能只使用 any 解析器,因为大多数现有的解析器都会丢弃 cmets。 (这又是 cmets 的全部意义,因此解析器将它们丢弃并没有错。)然而,有保留 cmets 的 Ruby 解析器,尤其是在诸如此类的工具中使用的解析器作为 RDoc 或 YARD。
YARD 特别有趣,因为它还包含一个查询引擎,它可以让您根据类名、方法名、YARD 标签、API 版本、类型签名等一些强大的谓词来搜索和过滤文档。
但是,如果您确实最终使用 RDoc 或 YARD 进行解析,那么为什么不首先使用它们呢?
或者,就像我上面建议的那样,如果你想要字符串,只需使用字符串:
module MethodAddedHook
private
def method_added(meth)
(@__doc__ ||= {})[meth] = @__last_doc__ if @__last_doc__
@__last_doc__ = nil
super
end
end
class Module
private
prepend MethodAddedHook
def doc(meth=nil, str)
return @__doc__[meth] = str if meth
@__last_doc__ = str
end
def defdoc(meth, doc, &block)
@__doc__[meth] = doc
define_method(meth, &block)
end
end
这给了我们一个方法Module#doc,我们可以用它来记录一个已经存在的方法,通过方法名和一个文档字符串来调用它,或者你可以用它来记录你定义的下一个方法。它通过将文档字符串存储在一个临时实例变量中,然后定义一个 method_added 挂钩来查看该实例变量并将其内容存储在文档哈希中来实现这一点。
还有Module#defdoc方法,一次性定义和记录方法。
module Kernel
private
def get_doc(klass, meth)
klass.instance_variable_get(:@__doc__)[meth]
end
end
这是您的 Kernel#get_doc 方法,用于获取文档(如果该方法未记录,则为 nil)。
class MyClass
doc 'This method tries over and over until it is tired'
def go_go_go(thing_to_try, tries = 10)
puts thing_to_try
go_go_go thing_to_try, tries - 1
end
def some_other_meth; end # Oops, I forgot to document it!
# No problem:
doc :some_other_meth, 'Does some other things'
defdoc(:yet_another_method, 'This method also does something') do |a, b, c|
p a, b, c
end
end
在这里您可以看到记录方法的三种不同方式。
哦,它有效:
require 'test/unit'
class TestDocstrings < Test::Unit::TestCase
def test_that_myclass_gogogo_has_a_docstring
doc = 'This method tries over and over until it is tired'
assert_equal doc, get_doc(MyClass, :go_go_go)
end
def test_that_myclass_some_other_meth_has_a_docstring
doc = 'Does some other things'
assert_equal doc, get_doc(MyClass, :some_other_meth)
end
def test_that_myclass_yet_another_method_has_a_docstring
doc = 'This method also does something'
assert_equal doc, get_doc(MyClass, :yet_another_method)
end
def test_that_undocumented_methods_return_nil
assert_nil get_doc(MyClass, :does_not_exist)
end
end
注意:这很 hacky。例如,没有锁定,所以如果两个线程同时为同一个类定义方法,文档可能会搞砸。 (即:文档字符串可能归因于错误的方法或丢失。)
我相信rake 与它的desc 方法本质上是一样的,并且代码库的测试比这更好,所以如果你打算在生产中使用它,我' d 窃取 Jim 的代码而不是我的代码。