库暂时修改(核心)Ruby模块

时间:2010-12-27 10:42:52

标签: ruby metaprogramming gem

我曾遇到一个Ruby库(我不确定它是否曾被打包为gem),它允许您方便地对Ruby模块应用临时修改。这些修改仅在“with”声明中执行的块内有效,如:

with(modifications) do
  [interesting stuff requiring the modifications]
end

它确保您不需要永久污染(核心)模块,只是为了在某些地方做一些特殊的事情。

作为我想做的一个具体例子:我想定义一个'in?' Fixnum上的方法,因此内部DSL的用户可以键入:

if value.in? [12, 16, 27, 28]
  [do something interesting]
end

我会用'with'方法包装DSL评估,我不需要用这个来污染Fixnum吗?方法。我知道这不是很难做,但可能有一些黑暗的角落,我觉得这个图书馆非常方便。

有谁知道我要找的这个图书馆的名字?我似乎记得它有点像'plusplus',但Google并没有给我任何东西。

3 个答案:

答案 0 :(得分:1)

嗯..这听起来像是Ruby 2中可能包含的内容的提案。 http://yehudakatz.com/2010/11/30/ruby-2-0-refinements-in-practice/

答案 1 :(得分:1)

我终于找到了答案:Rewrite gem by raganwald。不幸的是,它只是一个概念证明,并没有太大的成果。它的工作原理是将Ruby解析为AST,修改树并将结果转换回Ruby。这当然是非常强大的,但raganwald从来没有引入一般工具来实现特定的管理,而用自己的话来说,创建一个新的工具就是“折磨”。

在String上实现in?方法意味着在AST中搜索表示在String上调用in?并将其转换为其他方法调用的特定S表达式;可能是本地命名空间中的in?(string, args)。这很快就会变成静态类型检查的问题,以免您将每个in?解释为String#in?

答案 2 :(得分:0)

接近了很多方法替换(alias_method,模块包含等),所以我提供了一个抽象代码:

def with_modification   
   replace_method # for instance, alias_method

   yield    

   replace_method_back 
end

它会起作用。当然,您可以通过提供您想要更改的内容的描述来增强此DSL,以使此方法变得灵活,这完全取决于您。