A C# 3.5 pattern – the Accept Block pattern
A coworker pointed me towards this blog post as a useful trick to make code read cleaner. I’ve been using this trick in C# for quite some time, as it’s a very fundamental pattern in Ruby programming. In my head I call this the “Accept Block” pattern, but I’m fairly certain its just a syntactic version of an existing pattern (the Strategy pattern?). In some sense, it’s like being able to write your own version of the “using” or “lock” statements.
Here’s the old imperative way you might write some code:
{
SetupTheDatabase();
bool ShouldExit = SomeFunctionThatNeedsADatabase();
TeardownTheDatabase();
if (ShouldExit)
return;
DoOtherStuff();
}
And here’s how you’d rewrite it using the pattern:
{
SetupTheDatabase();
try {
block()
} finally {
TeardownTheDatabase(); // Note: Make sure this doesn’t throw!
}
}
void Foo()
{
bool ShouldExit;
WithEnsureDatabaseIsSetup(() => {
ShouldExit = SomeFunctionThatNeedsADatabase();
if (ShouldExit)
return;
});
DoOtherStuff();
}
In my opinion, the 2nd version is better to read, and more importantly, allows you to encapsulate the “setup/teardown” pattern – this way, this block of code is consistent, removes copy-paste errors from writing the same thing over and over again, and is easily updated if you want to do additional work when setting up the database.
But there’s a gotcha!
There’s a bug in the above code though that’s quite subtle, and that has bitten me a few times – the syntax () => { } is defining a closure, an anonymous function who can use variables bound inside its lexical environment (to understand the difference, take a look at that ShouldExit variable – even though it’s not a parameter of the function, we were still able to use it). When you call return, in the original example we will exit Foo() – in the new version, we will exit the closure and still execute DoOtherStuff()! Here’s how we should fix it:
{
bool ShouldExit;
WithEnsureDatabaseIsSetup(() => {
ShouldExit = SomeFunctionThatNeedsADatabase();
});
if (ShouldExit)
return; // Now we’ll return properly
DoOtherStuff();
}
Ruby doesn’t have this problem
This is a fundamental pattern in Ruby and built into the language and the runtime, so much so that it has special syntax to make it happen. However in Ruby a “block” is a slightly different syntactic structure than a function, so return will do what you expect:
an_array.each { |item| # This is a block with 1 param
print item
return if item > 2 # Actually returns from Foo, not from block
}
end
Yikes! for nerds: how to get the code
I ran out of time yesterday, but as promised, here’s how to build and run Yikes!
Quick Start
cd yikes
rake && rake ffmpeg
ruby lib/main.rb -l /path/to/videos -t /path/to/ipod/output -r 1800 -b
Getting the code
By far, the best way to get the code is via Git; this lets you view the entire commit history, as well as send me changes. If you don’t have Git, you can download precompiled source code trees for Linux or Mac OS X 10.5. The Git clone URL via Github is git://github.com/xpaulbettsx/yikes.git
Building (“Huh? Building? On Ruby?”)
(If you downloaded the precompiled version, skip this part!) Even though the application is in Ruby, we need to build ffmpeg and its associated libraries from source, so you need to have the XCode tools installed, and you probably need MacPorts as well. While building this takes forever, it’s fairly easy:
Running the app
Right now, you have to run Yikes! from the command line, but the syntax is pretty easy. Here’s a sample:
# The long version
ruby lib/main.rb –library /path/to/videos –target /path/to/ipod/output –rate 1800 –background
# or if you want the short version
ruby lib/main.rb -l /path/to/videos -t /path/to/ipod/output -r 1800 -b
# If you want to run it on the sample files for development, there’s an easier way
rake run
Yikes! It’s your videos on your iPod!
For awhile, I’ve been working on a project that is pretty cool, and I’m finally getting near the “first 90% done” software development mark; now I’ve got the 2nd 90% to get it to production-quality, and the 3rd 90% will make it actually good. Here’s the screenshot:

Yes, the UI is rough-draft, I’ve got to go to town on it in CSSEdit
What’s it do?
In its simple mode, Yikes! will take a directory and convert all the movies to iPod/iPhone format (H.264 MPEG-4′s, so compatible with most players), and it will skip files it’s already converted. This isn’t too far off from what you could do with Handbrake and some clever bash scripts.
However, you can also run the program in background mode, and this is where it gets really useful. You give the program a folder of videos, and a place to put the iPod videos, and it will start a web site that you can go to on another computer, where you can see the converted videos, download them, or (and here’s the clever part), add it to iTunes as a video podcast, which will copy all the videos to your iPod automagically.
Where’s the code?
Github! http://github.com/xpaulbettsx/yikes
Update: Changed URL from earlier, merged webif-ramaze into master
Later today once I’m back at home I’ll put up a “how to get/build the code”, as it’s a little tricky. I’m working on official releases for Mac and Linux, and a Windows port is in the future; while I haven’t been coding towards it, I also have made sure to not choose anything that’s completely impossible for Win32.
Thoughts? Ideas? Comments? Want to help?
Since I’m always busy with work, it’s taken me quite a while to get to this point, and I’m definitely open to accepting contributions and making this a real open-source project; so far, I’ve set up Github and a bug tracker (but no mailing list, forums, documentation, etc). If you’re not handy with coding, websites, or art/design, I would even just appreciate suggestions or ideas for cool features. My Email address is paul at paulbetts dot org, let me know!
Getting a backtrace in Ruby
Here’s a handy trick I found while trying to practice more of “red-green-refactor”, a method that will dump the stack of every thread without halting the application. Note that this trick uses fork(), so Windows Rubyists are out in the cold (all three of them).
fork do
ObjectSpace.each_object(Thread) do |th|
th.raise Exception, "Stack Dump" unless Thread.current == th
end
raise Exception, "Stack Dump"
end
end
This is courtesy of Robert Klemme, via the Ruby Talk mailing list
A powerful UI programming metaphor from Aaron Hillegass
Once upon a time (before Baywatch), there was a man with no name. Knight Industries decided that if this man were given guns and wheels and booster rockets, he would be the perfect crime-fighting tool. First they thought, “Let’s subclass him and override everything we need to add the guns and wheels and booster rockets.” The problem was that to subclass Michael Knight, you would need to know an awful lot about his guts so that you could wire them to guns and booster rockets. So instead, they created a helper object, the Knight Industries 2000 Super Car, or “Kitt”.
Notice how this is different from the RoboCop approach. RoboCop was a man subclassed and extended. The whole RoboCop project involved dozens of surgeons who extended the man’s brain into a fighting machine. This is the approach taken with many object-oriented frameworks.
While approaching the perimeter of an arms dealer compound, Michael Knight would speak to Kitt over his watch-radio. “Kitt”, he would say, “I need to get to the other side of that wall.” Kitt would then blast a big hole in the wall with a rocket. After destroying the wall, Kitt would return control to Michael, who would stroll through the rubble.
– from Cocoa Programming for Mac OS X, by Aaron Hillegass
Even if you don’t care about programming on the Mac, you should take a look because the developers at NeXT were really ahead of their time when they created the Cocoa framework. Objective C is like the “metal” version of Ruby, especially when you look at features in Obj-C like how their vtables are structured and their emphasis on introspection and mixins (called “categories” in Obj-C), and Cocoa takes full advantage of these features to make a really elegant, reusable UI framework.
pathedit 0.1 – Change your filesystem using your favorite editor
I read on one of the Planets about this idea, but I could never find the post so I reimplemented the idea in Ruby. The idea is, you can use a text editor to do mass file moves/renames/copies/etc. I wrote it to organize my downloaded TV shows, and it works pretty well and hasn’t eaten any of my data yet. Of course, the standard caveats apply.
The utility reads paths from either standard input or passed as parameters. Here’s the output from --help
If no files are given, the paths will be read from standard input
Specific options:
-a, –action type Action to perform (one of ‘copy’, ‘move’, ‘symlink’)
Common options:
-d, –debug Run in debug mode (Extra messages)
-v, –verbose Run verbosely
-h, –help Show this message
–version Show version
Caveats for this version
- Might give you problems on Windows unless you pass paths as parameters – soon to be fixed
- Can only use GUI editors in Linux, cause that’s the only operating system that handles GUI apps correctly – hopefully I can fix this too
Download it!
Qt4 Ruby and Metaprogramming 0.1 – Wiring up slots automatically
In my attempts to learn Qt 4 and QtRuby, it’s pretty obvious that there’s a huge potential for doing Rails-like things, such as declaration by convention. To this end, here’s an example of what you can do with the code I’m writing: this loads a UI file and wires something up to the Open action:
class ActionOpenHandler < Qt::Object
slots "on_activated()"
def initialize(main = nil)
super
@main = main
end
def on_activated
path = nil
Qt::FileDialog.new do |fd|
path = fd.get_open_file_name()
end
return unless path
text = nil; File.open(path, ‘r’) {|f| text = f.read}
@main.findChild(Qt::TextEdit, "textBrowser").text = text
end
end
a = Qt::Application.new(ARGV)
QtSuperLoader.new.initialize_and_hook("./main.ui").show
a.exec
Next, I’m seeking to replace the ugly line "@main.findChild(Qt::TextEdit, "textBrowser").text = text" with the more palatable "@main.text_browser.text = text". However, this is a bit more tricky, because findChild creates strongly-typed objects – there may be some trickery to get around it though involving QMetaObject.
Here’s the files, including the code that supports it all: qttest.rb and Translator.ui
Extracting a zip file in Ruby
I just spent like 2 hours trying to get this damn piece of code to work – trying to extract a zip file to a temporary directory. Most of my problems were because of the lack of documentation in rubyzip, but the end result appears to work. Here it is, obviously you need the abovementioned library from Rubygems.
UUIDchars = ("a".."f").to_a + ("0".."9").to_a
def uuid_seg(len)
ret = ""
1.upto(len) { |i| ret < < UUIDchars[rand(UUIDchars.size-1)] }; ret
end
def random_uuid
"#{uuid_seg(8)}-#{uuid_seg(4)}-#{uuid_seg(4)}-#{uuid_seg(4)}-#{uuid_seg(12)}"
end
def extract_zip_to_tempdir(zip_path)
temp_root = Pathname.new((ENV[‘TEMP’] || ENV[‘TMP’] || ‘/tmp’))
raise "Can’t find a temp directory" unless temp_root.exist?
# Figure out our temp directory
temp_dir = nil
while (temp_dir = temp_root.join(random_uuid())).exist?
nil
end
temp_dir.mkpath
ZipFile.open(zip_path) do |zf|
zf.each do |e|
if (m = /^(.*)[\\\/][^\\\/]*$/.match(e.name))
temp_dir.join(m[1]).mkpath
end
zf.extract(e.name, File.join(temp_dir.to_s, e.name))
end
end
temp_dir.to_s
end
Don’t worry, I haven’t forgotten QtRuby on Win32!
I was planning on posting the same kind of tutorial for Win32 for using QtRuby, but I’m currently stuck as to how to get it to build. After fighting with random build glitches for three hours or so (making progress, slowly), I’m currently stuck here:
C:/MinGW/bin/g++.exe -IC:/Qt/4.3.0/include/QtDBus -IC:/Qt/4.3.0/include/QtTest
-IC:/Qt/4.3.0/include/QtUiTools -IC:/Qt/4.3.0/include/QtScript -IC:/Qt/4.3.0/in
clude/QtSvg -IC:/Qt/4.3.0/include/QtXml -IC:/Qt/4.3.0/include/QtSql -IC:/Qt/4.3.
0/include/QtOpenGL -IC:/Qt/4.3.0/include/QtNetwork -IC:/Qt/4.3.0/include/QtDesig
ner -IC:/Qt/4.3.0/include/QtDesigner -IC:/Qt/4.3.0/include/QtAssistant -IC:/Qt/4
.3.0/include/Qt3Support -IC:/Qt/4.3.0/include/QtGui -IC:/Qt/4.3.0/include/QtCore
-IC:\Qt\4.3.0\mkspecs/default -IC:/Qt/4.3.0/include/Qt -IC:/Qt/4.3.0/include C
:/Qt/4.3.0/lib/libQtCore4.a C:/Qt/4.3.0/lib/libQtNetwork4.a C:/Qt/4.3.0/lib/libQ
tSql4.a C:/Qt/4.3.0/lib/libQtXml4.a C:/Qt/4.3.0/lib/libQtGui4.a C:/Qt/4.3.0/lib/
libQtUiTools.a C:/Qt/4.3.0/lib/libQtSvg4.a C:/Qt/4.3.0/lib/libQtOpenGL4.a C:/Qt/
4.3.0/lib/libQt3Support4.a -o C:\Users\paulbe\AppData\Local\Temp/3428-qtguess C
:\Users\paulbe\AppData\Local\Temp/3428-qtguess.cpp
Compiler output:
C:\Users\paulbe\AppData\Local\Temp/3428-qtguess.cpp:8:2: warning: no newline at
end of file
C:\Users\paulbe\AppData\Local\Temp/ccMxaaaa.o(.text+0×147):3428-qtguess.cpp:
undefined reference to `_imp___ZN12QApplicationC1ERiPPci‘
C:\Users\paulbe\AppData\Local\Temp/ccMxaaaa.o(.text+0×154):3428-qtguess.cpp:
undefined reference to `QApplication::~QApplication()’
collect2: ld returned 1 exit status
Thoughts? It looks like I’ve got some sort of compiler mismatch (one library compiled with MSVC and one compiled with MinGW, probably). I have no idea where though, I’m 85% sure that Qt is compiled with MinGW
Update: Alright, the new plan is to compile everything from scratch, and see if I can get some better results.
Update 2: It’s definitely the compiler difference:
{ Snip! }
SYMBOL TABLE:
[ 0](sec 1)(fl 0×00)(ty 0)(scl 3) (nx 0) 0×00000000 .text
[ 1](sec 2)(fl 0×00)(ty 0)(scl 3) (nx 0) 0×00000000 .idata$7
[ 2](sec 3)(fl 0×00)(ty 0)(scl 3) (nx 0) 0×00000000 .idata$5
[ 3](sec 4)(fl 0×00)(ty 0)(scl 3) (nx 0) 0×00000000 .idata$4
[ 4](sec 5)(fl 0×00)(ty 0)(scl 3) (nx 0) 0×00000000 .idata$6
[ 5](sec 1)(fl 0×00)(ty 0)(scl 2) (nx 0) 0×00000000 __ZN12QApplicationC2ERiPPci
[ 6](sec 3)(fl 0×00)(ty 0)(scl 2) (nx 0) 0×00000000 __imp___ZN12QApplicationC2ERiPPci
[ 7](sec 0)(fl 0×00)(ty 0)(scl 2) (nx 0) 0×00000000 __head_QtGui4_dll
The compiler’s looking for __imp___ZN12QApplicationC1ERiPPci, but the precompiled library has C2. I don’t understand why Qt’s distributing a busted library – this would break even their samples in straight C++ – it’s possible that Mingw updated behind their back though.
Cross-platform UI with Qt4 and Ruby – Mac/Linux HOWTO
Today I’ve spent the day working on figuring out how to make UIs using Ruby and Qt4. If you haven’t heard of it, Qt4 is an awesome UI framework written in C++. Since C++ is way too much work, some great KDE devs wrote a bindings generator for Qt4 called qt4-qtruby. While this package is fairly “linuxy”, it’s pretty easy to build it on Mac OS X too, making it possible to write GUI programs for OS X without having to delve into RubyCocoa which has too much hackiness (in my opinion), or even worse, Objective C. Furthermore, your code that you write on OS X will look great on Windows and Linux too!
Starting from scratch
First, install Ruby. If you’re using Linux, you’ll probably use the package manager to install Ruby and the Ruby development libraries! (Ubuntu will run sudo apt-get install ruby irb ruby-dev) OS X Tiger ships with Ruby by default, but you’ll want to install an updated version, via the Ruby one-click installer, then disable the old Ruby by using the following command:
touch ~/.bashrc && echo ‘export PATH="/usr/local/bin:$PATH"’ >> ~/.bashrc
sudo mv /usr/lib/libruby.1.dylib /usr/lib/_libruby.1.dylib
Installing Qt4 and QtRuby
First, install Qt4 by using your package manager on Linux (in Ubuntu, use the -kdecopy packages, they are more up to date), or by downloading the DMG from the Qt/Mac Open Source Edition Download page. You’ll also need MacPorts (and by proxy, the XCode tools). Also, download the Qt4 Ruby bindings source code from Rubyforge and save it to the Desktop.
Here’s the cool thing about QtRuby, and the advantage of building it from source: the build framework for QtRuby scans through whatever version of Qt you have installed, and dynamically builds the bindings. This means, there’s no waiting for new Qt features to be available in Ruby, it’s always up-to-date! Which is quite handy, because it seems like every minor version of Qt has new cool stuff.
Next, we have to do a bit of hackery – unfortunately, there’s no easy way to install QtRuby but it’s not so hard. Here’s what you’ll run:
sudo port install cmake ## CMake is a cool build system
tar -xzvf qt4-qtruby-1.4.9.tgz && cd ./qt4-qtruby-1.4.9
cmake .
make && sudo make install
Try it out!
Once you’ve got it built, try this sample code to see some of the new features in Qt 4.3 – this code will run a natively-styled wizard in Windows, Mac, and Linux without any changes! Unfortunately, this code isn’t very elegant or Ruby-like, but it’s a base that someone could write a really elegant UI framework over like RoR.
a = Qt::Application.new(ARGV)
def create_intro_page
page = Qt::WizardPage.new do |p|
p.title = "Introduction"
end
label = Qt::Label.new("This is a wizard!")
label.word_wrap = true
layout = Qt::VBoxLayout.new do |v|
v.add_widget(label)
end
page.layout = layout
page
end
wiz = Qt::Wizard.new do |x|
x.add_page(create_intro_page())
x.set_window_title("Test Wizard")
x.show
end
a.exec
![]() On Mac OS X |
![]() On Linux |
In summary:
- Install a Ruby that doesn’t suck, and hack your environment so it works right
- Install Qt and MacPorts
- Build QtRuby and install it
- Make UIs for all 3 platforms without hating your life


