Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Defining DSL in Ruby

Defining DSL in Ruby

Michał Poczwardowski

June 17, 2015
Tweet

More Decks by Michał Poczwardowski

Other Decks in Programming

Transcript

  1. DSL INTERNAL • just embedded in GPL (General Purpose Language)

    EXTERNAL • own parser/lexer/syntactic tree • examples: SQL
  2. Why? • easy to read • easy to use by

    non-programmers • in Ruby… easy to implement!
  3. Potential project • DSL for defining online surveys • All

    questions specified just using a DSL instead of complicated forms
  4. Survey DSL 01: survey :trug_questions do 02: title 'A few

    questions about TRUG' 03: question :city, kind: :single_choice do 04: text 'Where do you live?' 05: answer_option :gdansk 06: answer_option :gdynia 07: answer_option :sopot 08: end 09: end
  5. Question + QuestionBuilder Question = Struct.new(:text, :answer_options) class QuestionBuilder def

    initialize @text = 'Unset Text' @answer_options = [] end def build Question.new(@text, @answer_options) end end
  6. QuestionBuilder class QuestionBuilder def text(content) @text = content end def

    answer_option(label) @answer_options << label end end
  7. instance_eval def build_question(&block) builder = QuestionBuilder.new builder.instance_eval(&block) builder.build end build_question

    do text 'Where do you live?' answer_option :gdansk answer_option :gdynia answer_option :sopot end
  8. It may be a string def build_question(dsl_string) builder = QuestionBuilder.new

    builder.instance_eval(dsl_string) builder.build end build_question " text 'Where do you live?' answer_option :gdansk answer_option :gdynia answer_option :sopot "
  9. docile gem Docile turns any Ruby object into a DSL.

    Especially useful with the Builder pattern.
  10. docile gem 01: with_array([]) do 02: push 1 03: push

    2 04: pop 05: push 3 06: end #=> [1, 3] def with_array(arr=[], &block) Docile.dsl_eval(arr, &block) end