在Ruby中对字符串和block求解
http://tech.ddvip.com 2008年01月18日 社区交流
内容摘要:对包含代码的字符串和block求解,是我最钟爱的Ruby特性之一。Ruby提供了多种不同类型的求解方式;不过我最常用的是下面这些:eval、instance_eval和class_eval。
同样具有魔法的eval
上述代码展示的是:如何在不同的作用范围中,使用instance_eval对block进行求解。不过,eval方法同样可以在不同的上下文中进行求解操作。下面我来展示如何在block的作用范围中对ruby代码构成的字符串进行求解。
先让我们从一个简单的例子开始,不过让我们先回顾一下如何根据block的binding使用eval。我们需要一个能够帮我们创建block的类。
class ProcFactory
def create
Proc.new {}
end
end
在示例中,ProcFactory类有一个方法:create;它的功能只是简单地创建并返回了一个proc对象。尽管这看起来似乎没什么特别之处,但我们可以在proc对象的作用范围中,使用它对任何包含ruby代码的字符串进行求解。这样,我们不需要直接引用某个对象,便可以在这个对象的上下文中求解ruby代码。
proc = ProcFactory.new.create
eval "self.class", proc.binding #=> ProcFactory
什么时候会用到这样的功能呢?我最近在开发表示SQL的DSL时用到了它。我开始使用类似下面代码的语法:
Select[:column1, :column2].from[:table1, :table2].where do
equal table1.id, table2.table1_id
end
上述代码被求解时,跟在from后面的[]实例方法将所有的表名保存在一个数组中。接下来,当执行where方法时,传递给where的block会执行。此时,method_missing方法会被调用两次,第一次针对:table1,第二次针对:table2。在method_missing的调用中,对之前提到过的、用[]方法创建的表名数组进行检查,以查看标识符参数(:table1和:table2)是否为合法的表名。如果表名在数组中,我们返回一个知道如何应对字段名称的对象;如果表名非法,我们会调用super并抛出NameError。
责编:豆豆技术应用