在Ruby中编写DSL的教程

时间:2011-02-08 17:20:50

标签: ruby dsl

有关如何在Ruby中实现DSL的优秀在线教程是什么?我正在寻找解释整个过程的动手实例。

我知道关于DSL和Ruby的好书有这个问题:Good books on Ruby based DSL

4 个答案:

答案 0 :(得分:35)

我认为这是一篇关于在ruby中构建dsl的一系列文章:

http://jroller.com/rolsen/entry/building_a_dsl_in_ruby

答案 1 :(得分:34)

您可以使用Docile gem轻松完成此操作,方法是使用gem,或者阅读the source code以了解其工作原理。

假设您想通过DSL制作披萨

Pizza = Struct.new(:cheese, :pepperoni, :bacon, :sauce)

您使用构建器模式来制作Pizza

class PizzaBuilder
  def cheese(v=true); @cheese = v; end
  def pepperoni(v=true); @pepperoni = v; end
  def bacon(v=true); @bacon = v; end
  def sauce(v=nil); @sauce = v; end
  def build
    Pizza.new(!!@cheese, !!@pepperoni, !!@bacon, @sauce)
  end
end

你想要 DSL ,比如

@sauce = :extra
pizza do
  bacon
  cheese
  sauce @sauce
end
# => should return Pizza.new(true, false, true, :extra)

您所要做的就是将披萨方法定义为

require 'docile'

def pizza(&block)
  Docile.dsl_eval(PizzaBuilder.new, &block).build
end

然后砰的一声,你已经完成了。

答案 2 :(得分:4)

我发现本教程非常好,因为它明确涵盖了使用yieldinstance_eval这两个非常重要的模式:

How do I build DSLs with yield and instance_eval?

答案 3 :(得分:1)

编写DSL的先决条件是理解一些高级编程技术,如产生块,Ruby的方法查找过程和method_missing()等。阅读Metaprogramming Ruby是开发这些高级Ruby技能的最佳方法(该书还包含有关编写内部DSL的部分)。

我在大约20行代码中写了blog post on how to create a Ruby DSL to generate HTML markup。从一些小玩具示例开始,要比直接进入像Erector这样的生产级应用程序要好得多。按照ms-tg的建议研究Docile gem的源代码是非常好的,但它仍然可能有点像你的第一个DSL那样压倒一切。学习一些高级Ruby编程技术,构建一些玩具示例,然后研究Docile源代码。

以下是@ms-tg从头开始解释如何获取Docile gem的一些功能:

def dsl(obj, &block)
  obj.instance_eval(&block)
end

Pizza = Struct.new(:cheese, :pepperoni, :bacon, :sauce)
obj = Pizza.new

dsl(obj) do |pizza|
  pizza.cheese = true
  pizza.pepperoni = true
  pizza.sauce = :extra
end

p obj
# => #<struct Pizza cheese=true, pepperoni=true, bacon=nil, sauce=:extra>

dsl()方法也可用于更简单的示例,例如构建数组的Docile README示例:

arr = []

dsl(arr) do
  push(1)
  push(2)
  pop
  push(3)
end

p arr