Ruby and the Zen of every-day monotony

I have been pushing the Ruby language onto people for years now, trying to get them to use it for those little day-to-day tasks which just need to get done. Although Ruby on Rails has gained the Ruby language a lot of exposure it has unfortunately left people with the mistaken belief that if they aren't creating funky web2.0 sites then they can't benefit from the underlying language. Nothing could be further from the truth.

Recently I was tasked with testing a system against an SQL database which required me to come up with a lot of dummy data. This is a dull and thankless task at the best of times and so I did what any self-respecting programmer would do, I wrote a tool to do it for me. While my language of choice remains C# for day to day programming I like to do these small tasks in Ruby. There are a couple of reasons for this.

Firstly, I like Ruby as a language and I like to flex my Ruby-brain muscles. Secondly, I feel that Ruby is better at handling sets of data than C# is. Thirdly, I find that these little junky throw-away tools are perfectly suited to the dynamic nature of Ruby. Writing tools in Ruby I find that the code flows and changes with my understanding of the problem. While on a larger project this seems like a fairly frightening and dangerous idea, on these smaller scale projects it is perfect.

The best of example for this in my testing tool is dealing associative entities. These tables often just contain 3 integers; an auto generated arbitrary primary key and two foreign keys into the tables they join. Here is an example from a system where you are connecting Persons and Groups. A Person may belong to many Groups and a Group may contain many Persons.



CREATE TABLE [PersonGroup](
[PersonGroupId] [int] IDENTITY(1,1) NOT NULL,
[PersonId] [int] NOT NULL,
[GroupId] [int] NOT NULL )


Adding data to this style of table is simplicity itself. You can ignore the PersonGroupId column because it will be auto populated for you so you'll get:


INSERT INTO [PersonGroup]( PersonId, GroupId )
VALUES( @PersonId, @GroupId )

Now all you need to do is replace @PersonId and @GroupId with the identity values of the items you want to join and you're off and racing. It becomes a long-winded process however when you need to conditionally connect hundreds of items in both tables. In the case of generating my test-data I needed people to be in about half of the groups. That is, for each Person/Group pair, there was maybe (50/50 chance) going to be a connection.

That sounds like a spec and we can draw a few simple requirements from it:

  • Perform an action with each potential pair of items from two collections
  • Maybe perform a given action based on random chance
  • Create an SQL insert statement for the PersonGroup table

Here is the ruby code I used to do it. Given the above definitions above I hope that the code should be decipherable even if you don't know any Ruby:



def with_each_pair_of( a, b )
a.each do elem_of_a
b.each do elem_of_b
yield elem_of_a, elem_of_b
end
end
end

def maybe
yield if rand( 100 ) < 50
end

with_each_pair_of (1..10), (1..5) do personId, groupId
maybe do
puts "INSERT INTO [PersonGroup]( PersonId, GroupId )"
puts "VALUES( #{personId}, #{groupId} )"
end
end


16 lines including white-space and I ended with two fairly re-usable routines to boot! This little program will output the SQL code required to conditionally connect Persons with ids in the range [1, 10] and Groups with ids in the range [1, 5]. You could easily change the values of ids to some other set of data if necessary.

I love having a maybe method which sometimes executes a block of code. It brings to mind all number of other non-deterministic programming keywords. Imagine reading some banking software that contains the following:



practically_never do
rip_off_bank
end

I personally encourage others to learn Ruby for these sorts of tasks. For windows developers your best bet is the Ruby one-click installer. This will get you everything you need to get started in one installer package. The package even includes an MSDN-type integrated help engine called fxri and a copy of the first edition of the book Programming Ruby as a compiled help document which is a soup-to-nuts tour of the Ruby language.

If you want a more up to date experience and you live in Perth, the .NET Community of Practice library has a copy of the second edition of Programming Ruby and I know Mitch is still looking for someone to do a review.

Well, I hope that my small example has intrigued someone into trying the Ruby language. In my experience, investing any amount of time into learning Ruby will pay-off ten-fold.

ruby
Posted by: Mike Minutillo
Last revised: 27 May, 2011 02:42 PM History

Comments

No comments yet. Be the first!

No new comments are allowed on this post.