Domain-Specific Languages

The goal of metaprogramming in Ruby is often the creation of domain-specific languages, or DSLs. A DSL is just an extension of Ruby’s syntax (with methods that look like keywords) or API that allows you to solve a problem or represent data more naturally than you could otherwise. For our examples, we’ll take the problem domain to be the output of XML formatted data, and we’ll define two DSLs—one very simple and one more clever—to tackle this problem.[*]

Simple XML Output with method_missing

We begin with a simple class named XML for generating XML output. Here’s an example of how the XML can be used:

pagetitle = "Test Page for XML.generate"
XML.generate(STDOUT) do 
  html do
    head do
      title { pagetitle }
      comment "This is a test"
    end
    body do
      h1(:style => "font-family:sans-serif") { pagetitle }
      ul :type=>"square" do
        li { Time.now }
        li { RUBY_VERSION }
      end
    end
  end
end

This code doesn’t look like XML, and it only sort of looks like Ruby. Here’s the output it generates (with some line breaks added for legibility):

<html><head>
<title>Test Page for XML.generate</title>
<!-- This is a test -->
</head><body>
<h1 style='font-family:sans-serif'>Test Page for XML.generate</h1>
<ul type='square'>
<li>2007-08-19 16:19:58 -0700</li>
<li>1.9.0</li>
</ul></body></html>

To implement this class and the XML generation syntax it supports, we rely on:

  • Ruby’s block structure

  • Ruby’s parentheses-optional method invocations

  • Ruby’s syntax for passing hash literals to methods without curly braces ...

Get The Ruby Programming Language now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.