2011-02-08 14 views

Respuesta

34

Puede hacer esto más fácil con el Docilegem, ya sea mediante el uso de la gema, o mediante la lectura de the source code para entender cómo funciona

decir que quiere hacer una pizza a través de una conexión DSL

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

y utiliza un patrón 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([email protected], [email protected], [email protected], @sauce) 
    end 
end 

y desea que un DSL, diga algo como

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

Todo lo que tiene que hacer es definir el método depizza como

require 'docile' 

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

y Bang, ya está hecho.

+5

-1 porque, aunque dócil es ciertamente muy agradable, usarlo * * no pasa por el proceso de escribir una normal de Rubí DSL en lugar de explicar cómo se hace. – 00dani

+4

@ 00Davo mientras tiene derecho a su opinión, es un gesto muy antipático. Especialmente teniendo en cuenta que el código fuente de Docile es una excelente manera de aprender a crear un DSL en ruby. –

+0

Hmm. Eché un vistazo a la fuente, y tienes razón; de hecho es bastante ilustrativo. Cambiaré mi voto, pero también le recomiendo que edite la respuesta para incluir una referencia a la fuente de Docile. (Oh, acabo de intentarlo y, al parecer, mi voto está bloqueado a menos que la respuesta esté editada, por lo que en realidad * necesitarás * editar, ¿no es así?) – 00dani

4

encuentro este tutorial muy bueno, ya que cubre explícitamente los dos patrones muy importantes de la utilización yield y instance_eval:

How do I build DSLs with yield and instance_eval?

+0

Estaba buscando este ejemplo que había leído cuando era un principiante. Este es uno de los mejores ejemplos que he leído sobre la construcción de una DSL. –

0

Un requisito previo para la escritura de una conexión DSL es la comprensión de algunas técnicas de programación avanzadas como bloques rendimiento , El método de búsqueda de métodos de Ruby y method_missing(), etc. Leer Metaprogramming Ruby es la mejor manera de desarrollar estas habilidades avanzadas de Ruby (el libro también contiene una sección sobre cómo escribir DSL internas).

Escribí blog post on how to create a Ruby DSL to generate HTML markup en aproximadamente 20 líneas de código. Es mucho mejor comenzar con algunos ejemplos de juguetes pequeños que pasar directamente a una aplicación de nivel de producción como Erector. Estudiar el código fuente del Docile gem como lo sugiere ms-tg es excelente, pero aún así puede ser un poco abrumador como su primer DSL. Aprende algunas técnicas avanzadas de programación de Ruby, construye algunos ejemplos de juguetes y luego estudia el código fuente de Docile.

Aquí es cómo conseguir algunas de las funcionalidades 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 método dsl() también se puede utilizar para ejemplos más triviales, como el ejemplo Docile README de la construcción de una matriz:

arr = [] 

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

p arr 
+1

Claro, puede usar un 'instance_eval' desnudo, pero luego no podrá usar variables de instancia, o variables locales, y no podrá encadenar contextos (piense en DSL multinivel, que son comunes) . ¿Tiene sentido? Entonces, lo que Docile agrega son soluciones estándar para estos problemas, para que los proyectos no tengan que seguir redescubriendo y reinventando la rueda en esto. –

Cuestiones relacionadas