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: geek1 Comment »

Curved corner images in rmagick

By Korny at 12:05 pm on Sunday, July 20, 2008

RMagick is a great ruby library for image manipulation - it’s basically a wrapper around the venerable ImageMagick libraries.  There are some complexities around installing it on some platforms, and you have to be careful with garbage collection, but it’s still very easy to use and very powerful.

The curved corner images I used in previous blog posts could be built in photoshop or gimp or other gui applications, but I wanted something scriptable, so I’m trying to build all images in RMagick - and it’s really not that difficult.

RMagick has a whole set of vector graphics functions, but I’m mainly using one, the roundrectangle function - it’s pretty simple:

image = Magick::Image.new(width+bordsize, height+bordsize) { self.background_color = 'transparent'}
gc = Magick::Draw.new
gc.stroke(bordercolour)
gc.stroke_linecap('round')
gc.stroke_width(bordsize)
gc.fill(innercolour)
gc.roundrectangle(bordsize/2,bordsize/2, width,height, radius, radius)
gc.draw(image)

This basically draws a round rectangle, with a solid border, at offset (bordsize/2,bordsize/2) - you need the offset as otherwise the border edge will overlap the edge of the image.
Adding a shadow is pretty simple, rmagick has the shadow method:

shadow = image.shadow()
image = shadow.composite(image,Magick::NorthWestGravity, Magick::OverCompositeOp)

- this basically works, but sadly you get issues when you save the image. The shadow() method creates a shadow of a given image, with a specified shadow radius, which results in a larger image than the original - so the code above gives you an image which has shadow pixels at negative x and y coordinates!  Some file formats cope with this just fine - png files seem to do ok - but I wanted gif images for ie6 fallback, and gif doesn’t cope at all.

Anyway, to cut a long post short, the final code (see below) has a fair bit of logic for allocating extra space in the image for the shadow.  An example of the basic image-with-border-and-shadow image:

simple shadow sample

One last tweak I did - I wanted to have a shadow on the borders - the dark border is nice for some effects, but I wanted a slightly more 3d look:
sample with dark border
And a more subtle effect with the raised border the same colour as the diagram:
sample with light border

I also added some logic to set transparency of the image, for pretty backgrounds like the example from my last blog post (sample page here) - and to automatically save a gif version for ie6 display.

The full code can be seen at http://www.sietsma.com/korny/corner_test/corners_code.html

Obviously there’s lots of other things you can do - but this is a useful start!

Filed under: geek Leave A Comment »

Sigh - ie6 defeats my cunningness

By Korny at 9:47 am on Sunday, July 6, 2008

Well, my previous post and linked page seems to work nicely. (I did fix a minor glitch in ie7)

However, since then I’ve done some more reading - and my conclusion is, don’t do what I did - ie6 png transparency is just too risky. Have a read of the discussion at http://blogs.cozi.com/tech/2008/03/transparent-png.html?cid=106552420 - they found that when used heavily, the AlphaImageLoader filter causes ie6 to deadlock. Ow. If it’s critical, you can work around this, but it sounds really really painful.

So I’ve reverted to using something that is basically Scott Schiller’s technique - see http://www.sietsma.com/korny/corner_test/test2.html - but on ie6, you get no translucency.

The good news is, I can now use a single image, instead of slicing the image up. And I’ve fiddled my rmagick rounded-corner generation code, it’s now getting pretty nice - I’ll post it when it’s done. Not as nice as what you can do if you’re a photoshop/gimp guru, but it’s nice to have something generated by code, so I can change colours/sizes at will.

The next step is probably to make this stuff javascriptable, so I can use a single div for a minimal styling version, and then prettify it in javascript… possibly. I’m still a bit unsure if using javascript makes the code more ’semantic’ or not.

[ed: sigh - I thought I’d posted this weeks ago.  Somehow, it got saved as a draft…]

Filed under: life Leave A Comment »

Curved Corners with transparent png background on IE6

By Korny at 9:10 pm on Wednesday, June 11, 2008

I’ve been playing in the wonderful world of css - partly for work, and partly for fun.

I wanted to have fluid sized, png-based, rounded-corner dialogs for a web site. This is something that has been solved many times, but not (as far as I can see) for internet explorer 6 - which still has a big share of the browser market.

The best solution I’ve found for other browsers is the one by Scott Schiller at Schillmania - http://www.schillmania.com/content/projects/even-more-rounded-corners/ - which uses a single image, with cunning sprite tricks to get it into position. But on ie6, it has to revert to gif images.

The problem is, you can use pngs on ie6 - most simply, by using the iepngfix.htc behaviour trick (see http://www.twinhelix.com/css/iepngfix/) - but it has one big problem - you can’t align the png images to the right or bottom, so most of the usual tricks used to display corners don’t work.

So, I’ve been hacking around with ways to do corners where all the images are top-left aligned. I have a solution, I’m not sure it’s perfect, but it works - see the demo page at http://www.sietsma.com/korny/corner_test/test.html. This works in ie6, ie7, Firefox 2 and 3, and Safari.

Some caveats:

- it uses the iepngfix.htc behaviour - I experimented with using the Microsoft AlphaImageLoader stuff directly, but iepngfix does some tricks that I can’t reproduce easily, so for now I’m using the code directly.

- it’s a long way from semantic markup; there are a number of divs in there just to make it look right. I can’t see a way around this - I could make some javascript to turn a semantically-nice html page into the mess shown, which might be a good idea - but the end result would be the same (and doing it in javascript can make for ugly corner loading, and hassles re-running the javascript if you populate stuff via ajax). Anyone with hints on how to make this more web-standards-friendly, please tell! I’m still pretty new to the world of front-end stuff.

- there’s a bit of fiddling to make links work properly - the ie png stuff causes screwups if you use relative or absolute positioning on a div with a background image, and then add links to it.  So I had to mess around a bit to work around this - and I probably need to mess around more to make it cleaner.

- there are some ie-specific bits in there, added via conditional comments; at least one of them was pure trial-and-error to get things lining up right!

- there is probably more work needed to make padding and things consistent across browsers.

I’ll try to blog more later about the details, and about how I generated the images…

Filed under: work, geek Leave A Comment »

updates

By Korny at 7:39 am on Saturday, June 7, 2008

I’m still getting spam in the moderation queue. Poot. I’ve gone through and disabled more stuff, I’ll see if I can work this out somehow.

Things seem to have been somewhat down lately. We’ve had two funerals in the past month, one for Yolande’s grandmother, a fabuous gal who is sorely missed; and one for Sophie and Aaron’s daughter Jordan, also a very sad story. Phew. I don’t know if it’s just random, or if it’s the age we have gotten to, but there have been a lot of funerals in the last few years…

On the work front, I’m on a nifty Sensis R&D project - more details when it goes public. But the lack of a front-end coder on the project has forced me to cram my CSS and Javascript considerably - I’ll have to have a go at styling this blog!

Comments are back on, at least from here on, hopefully I can get spam blocked somehow, but it seems pointless to block friends but not spammers.

Filed under: life Leave A Comment »

no comment

By Korny at 11:18 am on Monday, March 31, 2008

Disabling comments for now (not that I get many!) - despite making comments moderation-only, I still get a vast number of failed spam attempts. Maybe if I turn off comments I’ll drop off their lists. And maybe I’ll get a pet unicorn for Christmas!

Filed under: life — Comments Off

Faking DNS with Ruby and Sinatra

By Korny at 3:37 pm on Friday, March 7, 2008

I had an annoying problem, so I needed a hacky solution…

At work, we have a large number of boxes with dynamic IP addresses. Getting a static IP address is a complete pain, and keeping boxes running is bad for the planet.

IP addresses don’t *usually* change, but the do change often enough to be annoying - especially when you want to run a VMWare server to do something background-ish, and find that it’s IP address has changed and you have to open the console just to find the new address. Bleah.

I’m sure a DNS/DHCP trick could be done somewhere, somehow - probably setting up a special DNS server somewhere locally could be done. But I needed something quickly, so some ruby hackery was the solution…

Basically I set up a tiny web server running Sinatra, a really really simple web framework. It just listens to http posts containing mac addresses, host names, and IP addresses, and stores them (in a YAML text file on disk - this isn’t meant to be scalable!). It also serves up a general status page, plus a simple /etc/hosts file snippet containing all known hosts.

I then have a really tiny ruby script that I run on each other box, which posts that box’s IP address to the server whenever it changes. (Currently this means on Ubuntu boxes, it runs from /etc/network/if-up.d/, on RedHat it runs from a script called /sbin/ifup-local)

At any stage, a user can load the file served by the sinatra server at http://the_server:4567/hosts - this gives a snippet of text that can be pasted into an /etc/hosts file (or the Windows equivalent). I might automate this step eventually, but for now it’s a manual process; it’s usually pretty clear when your hosts file is wrong, and not that hard to update it.

The code is real simple. First, the script to post data from each machine - this basically runs ‘ipconfig’ and extracts useful fields, it would need fiddling to work on Windows or anywhere that had a different ipconfig command (or didn’t use ‘eth0′):
(note - file saved as text attachment to get around this blog’s limitations):
postip.rb

Next, the server. Sinatra does most of the work for me - but it’s documentation is kind of thin, so some bits took some fiddling. Still, it really doesn’t get much easier than this:
fakedns.rb

And that’s it!

Filed under: geek1 Comment »

Getting things done again

By Korny at 5:48 pm on Friday, February 15, 2008

While I’m blogging…

I’ve started using a Getting Things Done TiddlyWiki - there seem to be a few of these around, I’m using the d-cubed tiddlywiki from http://www.dcubed.ca/ - it’s quite neat, and I seem to be managing to keep it up to date. I’ve set up a second standard TiddlyWiki for “general stuff” - things that aren’t tasks so much as reference info.

This is helped by the fact that I’ve set up a https based Subversion repository at home, which I’m now using to store all my vital configs, scripts, etc. - and being http based, I can check in/out files from work as well as home; I can even mount it as a WebDAV disk from OSX, Linux and (to a lesser degree) Windows. Though this seems to generate a pile of checkins, so I don’t do it often - manually checking in and out will do me just fine.

And it’s very nice to be able to share and access all the little handy scripts, to-do lists, and the like. Especially to-do lists; I haven’t managed before this to find a way to carry around *electronic* to-do lists that I could access from anywhere, and keep backed up. I was doing OK with index cards a-la HipsterPDA, but they aren’t so good when I want to put in URLs, or back them up! Still, they are my fallback solution for sorting out tasks in meetings or on the train… My N95 will actually render the TiddlyWiki, which is pretty impressive, but it’s not really usable, and there isn’t a subversion client for the N95 anyway!

Now I just have to work out how to integrate this with Google Mail, Google Calendar, Remember the Milk, my Delicious tags, and all the other places I’ve strewn todo-lists and starred items and the like. :)

Filed under: life — Comments Off

Twitter, Twibble, GPS and Maps!

By Korny at 5:29 pm on Friday, February 15, 2008

I’ve been getting hooked on twitter - you can find me at http://twitter.com/kornys . Ephemeral micro-blogging! Beware, most of what I write is entirely trivial - but that’s half the fun.

Worse than that, I’ve found ‘twibble’ (http://www.das-zentralorgan.de/twibble/) , a java phone app that lets me sent tweets on the fly, and tags them with my GPS location!
So you can go to http://twittermap.com/maps, enter “kornys” and see where I’ve been. Unless I have a sudden rash of privacy concerns - but at the moment, this stuff is kind-of fun.

Filed under: geek — Comments Off

comments, trackbacks, eggs and spam

By Korny at 8:29 am on Monday, February 11, 2008

I foolishly left the default wordpress setting to “send me an e-mail but allow comments”. So now I’m on some spam source - I’ve made comments “moderate only” but I have to log in regularly and kill a pile of spam in the “to-moderate” folder. Maybe it’ll force me to blog more!

Filed under: life5 Comments »
Next Page »