Defining DSL in Ruby

Defining DSL in Ruby

4cf300db4be834dfb4ddd76337205946?s=128

Michał Poczwardowski

June 17, 2015
Tweet

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!