Korny’s blog

The personal blog of Korny Sietsma

Ruby DSLs - so easy

By Korny at 9:15 pm on Monday, October 13, 2008

The joy of Ruby - writing simple DSLs is so very easy.  (That’s “Domain Specific Language” for the uninitiated - go look it up, it’s good for you)
I have some code that builds a tree of info from the file system - basically traversing directories and files and loading up definitions in memory.

I wrote some tests initially based on using real file fixtures, and while they worked, they seemed very ugly and confusing - they were basically integration tests not unit tests, and to know why a test failed, you had to go digging around in the filesystem.  Yuck.

Instead I wrote a DSL that lets me specify directories and files like:

@builder = StubDirBuilder.construct(”root”) do
dir ‘one’ do
file ‘loremipsum.txt’, “123″
end
dir ‘two’ do
file ‘loremipsum.txt’, “123″
file ‘egosum.txt’, “456″
end
dir ’single_child’ do
dir ’single_grandchild’ do
file ‘loremipsum.txt’, “123″
end
end
dir ’something_unreadable’ do
unreadable
end
end

This basically sets up the structures in memory to fake the corresponding directories and files when my tests run.

The code is a bit messy to post here (especially as this stupid blog sucks at formatting code) but the basic structure is:

class StubDirBuilder
def self.construct(root_name,&block)
builder = new(root_name)
builder.instance_eval(&block)
builder
end
def initialize(root_name)
… do stuff to set up the data structures
@cwd = root_name
end
def dir(name)
parent = @cwd
begin
@cwd = File.join(@cwd,name)
… process the directory info into memory
yield self if block_given?
ensure
@cwd = parent
end
end
def file(name, contents = “”)
fullname = File.join(@cwd,name)
… process file
end
end

Basically the call to “instance_eval” is ruby magic that evaluates the whole “dir/file” structure in the context of the newly built StubDirBuilder object.  So each time “dir(name) do…” is found, it calls the “dir” method on the StubDirBuilder; ditto for “file” and “unreadable”.  I just keep track of the current directory in “cwd” and store the data as needed.

(Credit for this is due to several different articles - mostly http://blog.8thlight.com/articles/2007/05/20/ruby-dls-blocks and http://www.artima.com/rubycs/articles/ruby_as_dsl.html )

Filed under: geek

1 Comment »

1
Get your own gravatar for comments by visiting gravatar.com

Comment by Korny

October 13, 2008 @ 9:19 pm

Freaking wordpress threw out all my indents. Argh. Too late tonight to fix it - I’ll try to fix it later.

RSS feed for comments on this post. TrackBack URI

Leave a comment

You must be logged in to post a comment.