$30 off During Our Annual Pro Sale. View Details »

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. Defining DSL in Ruby TRUG 17/06/15

  2. Michal Poczwardowski Ruby on Rails developer michal.poczwardowski@netguru.co dmp0x7c5@gmail.com

  3. DSL Domain Specific Language

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

    EXTERNAL • own parser/lexer/syntactic tree • examples: SQL
  5. Examples from Ruby world • rspec • factory-girl • chef

    • sinatra • AR migrations
  6. Why? • easy to read • easy to use by

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

    questions specified just using a DSL instead of complicated forms
  8. 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
  9. Result

  10. How?

  11. 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
  12. QuestionBuilder class QuestionBuilder def text(content) @text = content end def

    answer_option(label) @answer_options << label end end
  13. 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
  14. 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 "
  15. Result --- !ruby/struct:Question text: Where do you live? answer_options: -

    :gdansk - :gdynia - :sopot
  16. docile gem Docile turns any Ruby object into a DSL.

    Especially useful with the Builder pattern.
  17. 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
  18. Resources https://en.wikipedia.org/wiki/Domain-specific_language https://robots.thoughtbot.com/writing-a-domain-specific-language-in-ruby http://ms-ati.github.io/docile/ http://radar.oreilly.com/2014/04/make-magic-with-ruby-dsls.html

  19. Thanks!