Tutoriales para escribir DSL en Ruby


¿Cuáles son los buenos tutoriales en línea sobre cómo implementar DSL en Ruby? Estoy buscando ejemplos prácticos que expliquen todo el proceso.

Soy consciente de que hay esta pregunta en buenos libros sobre DSL y Ruby: Buenos libros sobre DSL basado en Ruby.

 31
Author: Community, 2011-02-08

4 answers

Creo que esta es una gran serie de artículos sobre la construcción de un dsl en ruby:

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

 34
Author: Upgradingdave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-08 17:45:45

Puedes hacer esto muy fácil con el Dócil gem , ya sea usando la gema, o leyendo el código fuente para entender cómo funciona.

Digamos que quieres hacer una Pizza a través de un DSL

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

Y se utiliza un patrón de constructor para hacer la 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

Y quieres un DSL , di algo como

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

Todo lo que tienes que hacer es definir el método pizza como

require 'docile'

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

Y bang, estás acabado.

 34
Author: ms-tg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-26 15:04:10

Encuentro este tutorial muy bueno, ya que cubre explícitamente los dos patrones muy importantes de usar yield y instance_eval:

¿Cómo construyo DSL con yield e instance_eval?

 4
Author: Alex Popov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-17 00:52:17

Un prerrequisito para escribir un DSL es entender algunas técnicas avanzadas de programación como producir bloques, el proceso de búsqueda de métodos de Ruby y method_missing(), etc. Leer Metaprogramar Ruby es la mejor manera de desarrollar estas habilidades avanzadas de Ruby (el libro también contiene una sección sobre escribir DSL internos).

Escribí una entrada de blog sobre cómo crear un DSL Ruby para generar marcado HTML en aproximadamente 20 líneas de código. Es mucho mejor empezar con un pequeño juguete ejemplos, que para saltar a la derecha en una aplicación de grado de producción como Erector. Estudiar el código fuente de la gema Dócil como sugiere ms-tg es excelente, pero todavía podría ser un poco abrumador como su primer DSL. Aprenda algunas técnicas avanzadas de programación Ruby, construya algunos ejemplos de juguetes y luego estudie el código fuente Dócil.

Aquí está cómo obtener parte de la funcionalidad de la gema Dócil como se explica por @ms-tg desde cero:

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>

El dsl() el método también se puede usar para ejemplos más triviales, como el README Dócil ejemplo de construcción de una matriz:

arr = []

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

p arr
 1
Author: Powers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-13 04:51:58