我想弄清楚如何为我的Ruby项目创建一种“无类DSL”,类似于如何在Cucumber步骤定义文件中定义步骤定义或路径是在Sinatra应用程序中定义的。如何在Ruby中创建一个无类DSL?
例如,我想有一个地方我所有的DSL函数被调用的文件:
#sample.rb
when_string_matches /hello (.+)/ do |name|
call_another_method(name)
end
我认为这是一个不好的做法,污染了一堆的是方法,全局(Kernel
)命名空间特定于我的项目。所以方法when_string_matches
和call_another_method
将在我的库中定义,并且sample.rb
文件将在我的DSL方法的上下文中进行评估。
更新:下面是这些DSL方法目前如何定义一个例子:
方法是在被子类一类中定义的DSL(我想找到一种方法,再利用之间的这些方法简单的DSL和类实例):
module MyMod
class Action
def call_another_method(value)
puts value
end
def handle(text)
# a subclass would be expected to define
# this method (as an alternative to the
# simple DSL approach)
end
end
end
在某些时候
然后,我的程序的初始化过程中,我想解析sample.rb
文件和存储这些动作以后执行的:
module MyMod
class Parser
# parse the file, saving the blocks and regular expressions to call later
def parse_it
file_contents = File.read('sample.rb')
instance_eval file_contents
end
# doesnt seem like this belongs here, but it won't work if it's not
def self.when_string_matches(regex, &block)
MyMod.blocks_for_executing_later << { regex: regex, block: block }
end
end
end
# Later...
module MyMod
class Runner
def run
string = 'hello Andrew'
MyMod.blocks_for_executing_later.each do |action|
if string =~ action[:regex]
args = action[:regex].match(string).captures
action[:block].call(args)
end
end
end
end
end
到目前为止我所拥有的问题(以及我尝试过的以上没有提到的各种问题)是在文件中定义了块时,实例方法不可用(我知道它现在处于不同的阶级)。但是我想要做的更像是在这种情况下创建一个实例并进行评估,而不是在Parser
课程中评估。但我不知道该怎么做。
我希望这是有道理的。任何帮助,经验或建议,将不胜感激。
我有很多东西需要消化,因为其中有些东西有点过头,但它仍然有用。谢谢! – Andrew 2012-07-27 05:30:16