Me in Denmark
June 23rd, 2008
On Wednesday I will be flying out to Copenhagen to attend the Reboot conference on Thursday the 26th and Friday the 27th of June.
If you’re there – or nearby – and want to meet up with me or Paul (CEO of Litmus ) then just drop me an email from my contact form – we’d love to speak to you!
You’ll spot me possibly in my black Engine Yard t-shirt or you can recognise me from my picture otherwise.
0 comments »Setting up Background Job (BJ) Properly
June 23rd, 2008
I dealt with a customer today who was a bit miffed that his Background Jobtasks were taking a while to kick off after the Rails app submitted them to the queue.
I dug a little deeper into the problem - he was using our standard configuration, moving control of the runner out to cron instead of being controlled from within the app itself.
1 |
Bj.config["production.no_tickle"] = true |
and then a cronjob such as
*/2 * * * * bj run --forever --rails_env=production --rails_root=/data/user/current
FireFox 3 triggers an OpenSSL bug
June 22nd, 2008
Secure Connection Failed
An error occurred during a connection to xyz-abe.com
SSL received an unexpected Change Cipher Spec record.
(Error code: ssl_error_rx_unexpected_change_cipher)
I’ve been seeing more and more customers report this in the lead up to FireFox 3 going live…now the release has come I think the only thing you can do is try and get your production servers upgraded to the latest OpenSSL (0.9.8h) as soon as possible. Unfortunately the only other work around involve users disabling something in about:config or disabling SSLv3 on your server.
Some background reading on the bug:
Additionally I’ve seen FireFox 3 introduce another bug related to incorrectly signed HMAC codes in SSL transactions. After some digging around I noticed that FireFox 3 supports the Camellia cipher which AFAIK isn’t widely supported amongst other browers yet. During SSL negotiation the browser seems to end up using Camellia even though it could have negotiated the more familiar AES cipher. I hacked around this in one clients nginx configuration by adding the following to their http block:
ssl_ciphers ALL:!CAMELLIA;
Hpricot Case Sensitivity
April 24th, 2008
Recently we were trying to use the awesome Hpricot to do some HTML parsing. Problem is that Hpricot doesn't easily allow you to do case insensitive searches for elements.
This means that we're missing any element where someone has placed an uppercase character in the tag we're explcitly looking for.
1 2 3 4 |
>> h.at("meta[@name=description]") => {emptyelem meta name"description" content"David Smalley, Ruby hacker based in Leeds, UK"} >> h.at("meta[@name=Description]") => nil |
This problem has been talked about on the Mofo Mailing List and even on the Hpricot challenge page - but I didn't really like the look of those solutions as downcase-ing everything would distort the original HTML.
So I devised this (horrible and hacky) bit of code that loops through all element names and attributes, downcase-ing them all without touching any innerHTML.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
def normalize(element) element.children.each do |child| if child.respond_to?(:name=) child.name = child.name.downcase if child.name end if child.respond_to?(:raw_attributes=) attribs = {} child.raw_attributes.each_pair do |key,value| attribs[key.downcase] = value.downcase if value end child.raw_attributes = attribs end normalize(child) if child.respond_to?(:children) end return element end >> h = Hpricot(open("http://davidsmalley.com")) => Hpricot.....<snip> >> normalize(h) |
Now all your element names and tags will be downcase-ed and all innerHTML will be left alone. Comments, feedback and suggestions very much welcome!
Shout - at a glance status
April 21st, 2008
Inspired by a recent 37 Signals blog post A peek at In/Out, an internal app at 37signals, we decided this would be great for the Litmus team as well. A quick glance overview of what everyone is working on at this moment in time.
Not wanting to go too overboard and create something we never went and updated, we decided to tie it into Twitter which we all use anyway. Direct Messages fit the bill perfectly as we weren’t too keen on broadcasting the inner workings of Litmus across the internet.
Merb was the framework of choice for this little web app. Using the Twitter Gem to check the direct mail of an account we set up, it then republishes the messages to a page we can all view inside our management app. Merb worked a treat, and we got the app up and running in a couple of hours, a quick style overhaul from Paul and we had the app live and in use from today.
We hooked the app into a Fluid browser and Paul knocked up a little applescript app that posts a direct message to the correct Twitter account.
We’re all really impressed with the result…

The plan is to release this app via Github once it has been cleaned up a bit and properly tested, check back here for details of its release.
I should point out that while we were playing around with this we called it “in/out” (that’s what appears in the screen shot) but obviously the fine people at 37 Signals have already used this name. Therefore our app is known as “Shout”.
2 comments »Vendor everything in Merb
April 21st, 2008
I spent an evening trying to suss out how to use merb with all the gems unpacked into the local gem folder, turns out my problem was using
gem unpack <gemname>
in a local /your/app/gems folder does not work.
Instead you need to setup an entire new gem home within your merb app, complete with /bin, /doc etc. directories that gem is expecting. To set this up you just need to do the following inside your merb app.
mkdir gems
gem install <gemname> --no-rdoc --no-ri -i /your/app/gems
Note that if you install a gem with a dependency it will by default install all the dependencies as well. This means that installing merbful_authentication for example will also likely install the merb, merb-core and merb-more gems into your app local gems directory. I am not sure how you would proceed using gems that compile for local architectures (mongrel, hpricot, eventmachine etc.) which might get dragged in as dependencies but then end up being bundled with your project. The obvious problem there is your development and production environments (and possibly different developers environments) are likely to differ so checking a platform specific binary into source control isn’t the best idea.
It is important to note the --no-rdoc and --no-ri flags as these will stop you having a doc directory of documentation generated from every gem that you install to your app. You can alternatively set up your .gitignore or svn:ignore to not check these in to source control, but I prefer to just never generate them in the first place.
Hook up to IRC when your network blocks it
April 18th, 2008
Just a quick write up for my own reference really, but hopefully some other people will find it useful.
My office is hooked up to the academic JANET network in the UK and it turns out that IRC is completely blocked. This is less than ideal for my new job at Engine Yard which uses IRC extensively for customer support and communication between staff.
Rather than fight with IT department goons I managed to quickly setup irssi to proxy my IRC access via my dedicated server and avoid network port blocks. Here are the steps I followed:
- Download and install irssi (use the—with-proxy flag on configure) – see this doc for more info
- Set up irssi to access your chosen server and various options – see this doc
- Run irssi using screen so you can start and then detach it (this means you can log out and keep it running between sessions) – see this doc
- Connect your local IRC client to the server running irssi on the port you specified
- Use IRC!
Thanks to people on the Geekup mailing list for their help and advice
0 comments »Exciting times
April 9th, 2008
This last weekend I was up at Scotland on Rails – met loads of great people and saw lots of interesting talks. Well done to the organisers for putting together a Ruby/Rails conference in the UK. It had been a long time coming since RailsConf Europe came (and went) to London a few years ago (as an aside, is this always going to happen in Berlin now? I had hoped it was going to do a grand tour of Europe).
At the conference I was offered a job with Engine Yard and I’m delighted to say that I accepted the offer and will be starting in May!
Big thanks to Jamie van Dyke for giving me the opportunity.
2 comments »Extension-less Formats in ActiveResource
March 26th, 2008
When trying to integrate Litmus with Fetch recently we came across an API that whilst appearing RESTful, didn't quite map onto ActiveResource conventions because their URLs 404'd if we included .xml as the extension.
So I quickly whipped up a little plugin to let us specify new formats that don't include extensions.
1 2 3 4 5 6 7 |
class Something < ActiveResource::Base self.site = "http://someone:password@an-app.com" self.prefix = "/api/" self.format = :xml_no_extension end |
Now, calls to
Something.find(:all) |
Perfect!
You can grab the code from the ExtensionlessFormat GitHub repository
iTunes Podcast Auto Delete
March 26th, 2008
Despite setting my iTunes preferences to only keep unplayed episodes and trying to set auto delete on all my subscribed podcasts I noticed that iTunes was keeping all the old podcasts I’d already listened to and never removing them. Today I found out how to fix that and it turns out its a combination of iTunes fault and mine (technically just my fault really…but iTunes could improve to help me).
The problem as I discovered is that I tend to abandon podcasts once the talking is over and it cuts to the outro music, this has been made all the easier with the skip track/pause button on my iPhone headphones. When I went back and checked all the podcasts in iTunes which hadn’t auto deleted it turns out they all had 20 – 5 seconds of play time left on them (iTunes remembers where you listened to).
To remedy my auto delete problem I first selected all the podcasts in the list with Apple-A, then right clicked to get the context menu up and selected ‘Allow Auto Delete’ (if they are all already set to auto delete then the option will say ‘Do Not Auto Delete’). Then I had to click through all the remaining podcasts and drag their time left down to about 2 seconds and let them play until they finished completely. When I then clicked ‘refresh’ (having set my podcast retention preferences to ‘keep unplayed’) iTunes proceeded to auto delete all my old podcasts.
Frustrating, but I can see why iTunes does have to do it this way. Perhaps with their gapless playback analyser they use on normal music tracks they could develop a way to find out if there is any talking left on a podcast that has been listened to, or maybe a cut off to simply count any podcast with less than 20 seconds remaining as finished. That last option might lead to unexpected behaviour so probably isn’t ideal, however in my case it is exactly what I need.
Use Applescript to post to Pastie
March 7th, 2008
Using the same code as my last post I’ve been trying to create an Applescript I can use to post to pastie using TextExpander.
Trouble is, as I’m very short on time and not an Applescript developer I’ve not been able to find out how to post to Pastie and preserve line breaks so the formatting comes out incorrectly (often all on one line).
If anyone would care to glance over this script its in dire need of some proper encoding, and obviously something to grep out the actual pastie number and construct a URL to return from the script.
Check out some loose code I’ve been playing with over at Pastie
Use TextExpander to create a TinyUrl
March 7th, 2008
I’m a big TextExpander user, so much so that I always find myself typing strange key combinations to do things even when I’m not on my own machine. Whilst I do appreciate that unix has a perfectly good alias command that could be used instead, I like that my text shortcuts work even when I’m ssh’d into a remote machine (TextExpander is just watching your keyboard input and converting it as you type).
Recently I’ve found myself doing a lot of TinyUrl links (mainly because of Twitter) and decided to knock up an Applescript to instantly convert whatever is on my clipboard into a tiny url as I type.
Go and check out the code on pastie – once you’ve got this its just a case of creating a new Applescript snippet in TextExpander and pasting in this code.
Update: I got linked from the SmileOnMyMac Blog (developers of TextExpander) – thanks guys! Glad you like the tip :) They also have a pre-packaged version of my script ready to download straight into TextExpander so head over there to get hold of it.
Another Update: Looks like Jack-Daniyel Strong devised a much nicer version of my applescript that is faster, and has error checking. Nice work! I’m now using his script :)
New Async Observer Start/Stop scripts
March 6th, 2008
I've updated the Async observer start/stop scripts that I've been using extensively for pushing off long running tasks in Litmus. Combined with a few extra cap tasks this has been working perfectly for us for several weeks now.
Lots of the code is pulled out of the ferret_server and spec_server code from the Ferret and Rspec projects respectively. Download it here async_worker.zip
and get some Cap tasks from below...1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
namespace :beanstalk do task :start, :roles => :app do run "/usr/bin/beanstalkd -d -l 127.0.0.1" end task :stop, :roles => :app do run 'killall beanstalkd' end task :restart, :roles => :app do stop start end namespace :worker do task :start, :roles => :app do run "cd #{deploy_to}/current && RAILS_ENV=#{rails_env} script/async_worker start" end task :stop, :roles => :app do run "cd #{deploy_to}/current && RAILS_ENV=#{rails_env} script/async_worker stop" end task :restart, :roles => :app do stop start end end end |
A productive morning for Litmus
March 6th, 2008
This is a somewhat self-congratulatory post today, after a few weeks of hard slog and testing we finally put the Litmus 24 hour passes live!
We’ve received lots of requests from customers for a credits based system, but we felt this didn’t fit the model of how people would use Litmus. When fixing a template bug people want to fire off lots of tests as they iteratively work through a problem without fearing how much each test is costing them. So we decided that a pass to use Litmus for 24 hours for as many tests as you care to do works perfectly. From the response we are getting from customers we know this was the right thing to do. We even got a nod from John Gruber over on Daring Fireball
That’s not all though…
In light of the growing demand for Litmus and our booming API/Whitelabel deals the current database server was taking a beating. So at 7am this morning we managed to successfully move the database over to a much more powerful server with only 20 minutes of downtime. So far the load looks to have eased and we look forward to the increased response times for our customers.
If that wasn’t enough, Matt managed to launch IE 8 Beta testing which should be available to all our customers immediately!
So if you haven’t already, swing by and give us a try – there’s a 7 day trial included in the monthly plans, or the new 24 hour pass is only €12.
Leeds Ruby Thing
February 19th, 2008
After a fantastic meet-up earlier this month, the Leeds Ruby Thing has a website and, hopefully, a regular monthly slot down at the wonderful Mr. Foley’s on The Headrow in Leeds city centre.
For some reason I am grimacing in this photo from the last meet-up.

Feed me
