Sep 12, 2011

Ruby's instance_eval and Structured Configuration Files

Recently at work I was setting up a section of the program involving a user-configurable GUI element. Initially I thought about using something like XML to handle this, however if I went that route I'd have to manage parsing the XML through some library, traversing the XML tree, and create some sort of GUI element based on what type of node it was, what the attributes were, etc.

On top of that it was highly likely that the requirements for this GUI system would change and the level of sophistication behind the GUI system would increase - buttons would need to do more complicated tasks that could potentially be arbitrary. Having a hard-coded system in C# would not be feasible since tweaking logic would require a re-compile and an application restart.

I decided that since the system already had an IronRuby install built in, perhaps I could do this configuration file in Ruby as well. Given an XML configuration file that looks like this:
<group name="Buttons">
<button text="Cool Script">
<something_crazy_and_awesome />
I could translate this to Ruby that looks like this:

group "Buttons" do
line do
button "Cool Script" do

On top of that in order to use this configuration file in a program I don't actually need to parse the file, I can just execute it within the context of different objects. For the dialog box that allows the user to set up the configuration I can just execute the Ruby code within that dialog box object and it will automatically create the elements that allow the user to change the configuration. Then in the part of the application where the user actually uses the configuration, I can just execute the file again but with a different definition of group, line, etc. that construct the proper GUI elements.

This is not just applicable to GUI elements, you can use this for anything that uses some sort of structured configuration. Rake uses this to great effect with tasks. But how would you go about implementing this pattern?

Turns out it's really simple using instance_eval. Here's an example that constructs the GUI element (this is in
IronRuby so it uses .NET for GUI construction):
class GroupBuilder
def initialize parent, name, &block
@group_box =
instance_eval &block

def line &block, &block)

class LineBuilder
attr_accessor :panel

def initialize parent, &block
# in the GUI environment we use a panel for adding things
@panel =
parent.Controls.Add @panel

instance_eval &block

def button text, &block, text, &block)

# ... anything else that can be placed in a line ...

class ButtonBuilder
def initialize parent, text, &block
# create a button
btn =
# bind the click event of the button to execute the
# Ruby code within the block
btn.Click { self.instance_eval &block }
parent.Controls.Add btn

def something_crazy_and_awesome
# do something crazy and awesome

class ScriptProcessor
def initialize control, script
@control = control

def group name, &block, name, &block)
To do all this stuff, you can just create a ScriptProcessor object, pass in a .NET control and a script filename:

f =, "my_config_file.rb")

For each type of nested element you can create a class which define a method for the various types of sub-elements that you are allowed to have. Each of those methods will then handle the processing that needs to happen when the system sees an element of that type.

I think you could probably do this without classes and just use lambdas, but I think the code is clearer when you have objects since it is very explicit as to what each object is for.

Doing this with C# is a bit trickier since C# doesn't have instance_eval, but it turns out you can have a bit of a hack in order to get it to work quite well. I'll write up a quick post about this at a later date.

No comments: