0
0
Rubyprogramming~10 mins

DSL building patterns in Ruby - Step-by-Step Execution

Choose your learning style9 modes available
Concept Flow - DSL building patterns
Define DSL class/module
Define methods for DSL keywords
Create instance or context
Evaluate DSL block
Store or process DSL data
Use DSL results
This flow shows how a Ruby DSL is built by defining methods inside a class or module, then running a block in that context to collect or process data.
Execution Sample
Ruby
class GreetingDSL
  def initialize
    @messages = []
  end
  def say(text)
    @messages << text
  end
  def run(&block)
    instance_eval(&block)
    @messages
  end
end

result = GreetingDSL.new.run do
  say "Hello"
  say "World"
end

puts result.inspect
This Ruby code defines a simple DSL to collect greeting messages and then prints the collected messages.
Execution Table
StepActionEvaluationResult
1Create GreetingDSL instanceGreetingDSL.newInstance with empty @messages array
2Call run with blockrun { say "Hello"; say "World" }Executes block in instance context
3Inside block: call say("Hello")say("Hello")@messages = ["Hello"]
4Inside block: call say("World")say("World")@messages = ["Hello", "World"]
5run returns @messagesreturn @messages["Hello", "World"]
6puts result.inspectputs ["Hello", "World"].inspect["Hello", "World"] printed
7EndNo more codeExecution stops
💡 Execution stops after printing the collected messages array.
Variable Tracker
VariableStartAfter Step 3After Step 4Final
@messages[]["Hello"]["Hello", "World"]["Hello", "World"]
Key Moments - 3 Insights
Why does the block inside run use instance_eval?
Using instance_eval runs the block with self as the DSL instance, so calls like say "Hello" call the DSL methods directly (see execution_table steps 2-4).
How does the say method add messages?
The say method appends the given text to the @messages array, updating state step-by-step (see variable_tracker).
What does run return and why?
run returns the @messages array after the block runs, so the collected data is accessible outside (see execution_table step 5).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at step 3, what is the value of @messages after say("Hello")?
A[]
B["World"]
C["Hello"]
D["Hello", "World"]
💡 Hint
Check variable_tracker column 'After Step 3' and execution_table step 3.
At which step does the run method return the collected messages?
AStep 5
BStep 4
CStep 2
DStep 6
💡 Hint
Look at execution_table step 5 where run returns @messages.
If instance_eval was not used in run, what would happen to calls like say "Hello" inside the block?
AThey would call the say method on the DSL instance as expected.
BThey would cause an error because say is undefined in the block's context.
CThey would call a global say method.
DThey would be ignored silently.
💡 Hint
Recall that instance_eval changes self so DSL methods are found (see key_moments question 1).
Concept Snapshot
Ruby DSL building pattern:
- Define a class/module with methods as DSL keywords
- Use instance_eval to run a block in DSL context
- Collect data in instance variables
- Return or process collected data after block
- Enables clean, readable domain-specific code blocks
Full Transcript
This example shows how to build a simple Ruby DSL by defining a class with methods that represent DSL commands. The run method uses instance_eval to execute a block where these DSL methods can be called directly. Each call to say adds a message to an internal array. After the block finishes, the collected messages are returned and printed. The execution table traces each step, showing how the internal state changes and how the block is evaluated. Key moments clarify why instance_eval is needed and how data is collected. The quiz tests understanding of variable changes and method calls within the DSL context.