One of the most powerful concept of Ruby is metaprogramming. This make the language uniq, powerful and expressive allowing you to create DSL which is tailored to your need. I would try to guide you guys to create a basic DSL using ruby metaprogramming.
Step 1: Ruby blocks
Ruby are simple. You can write a method that can yield. Something like,
Step 2: Ruby blocks sending object
We can send objects from block method back to block caller.
Here is what is happening,
When report block is called from line #7, the flow control goes to line #2
In line #3 the control yields back to line #8
After the yield block is over, the control goes back to line #4, and continues execution
Step 3: instance_eval
Here the puts in line #10 is run on the context of report object. The following example will make things clearer.
Here you see there is no my_print method defined globally but at line #14 the block has access to my_print method. It is because the block is evaluated with the context of a report object.
Step 4: First draft of DSL
Step 5: Second draft of DSL
Lets add some more features to make more out of the DSL.
Now you can go ahead and implement new features on this abstraction. For the source code used here you can have look here.
I once build a gem using the same concept query_report. Here is a demo.