Saturday, November 22, 2008

The Most Rockin' Carpool Site on the Web


This blog post marks the second launch party for, a ride sharing site so easy to use your 80 year old grandma could figure it out, and so awesome it’s going to be the talk of every college and work party.

Why ride sharing is awesome

For the past several months I’ve been actively pursuing ride sharing. My reasons are more economic than environmental (interestingly enough the two intersect here). Here’s why I think ride-sharing is awesome:

  • We (my wife and I) continue saving an extra car payment, and get along just fine with our vehicle which we’ve completely paid off
  • Save wear and tear on said vehicle
  • Lower monthly payment for auto insurance
  • Less gas money
  • The ability to be productive during my commute time (I’ve got a stomach of steel when it comes to getting car sick, my stomach is awesome!)
  • Opportunities to socialize with car-pool partners.
  • Helping to shrink government by being less dependent on government to make my transportation more cost effective. (OK, this will not be a political post)

Why I created a ride sharing site

Months ago when I was searching for a carpooling website to organize carpools in my church and community, and I found myself in Goldie Locks’ shoes, except the baby cub spit in his porridge and wet his bed. I couldn’t find a carpooling site that was “just right” – one I could recommend without any reservations. They were either difficult to figure out, or it was difficult to modify your commute once you’ve recorded it, or protect your privacy without listing your house as 5 miles away, or required WAY TOO MUCH information to sign up.

I don’t pretend to be so smart that I can create the perfect carpooling site, but I decided I was certainly going to try. I started out with these objectives in mind:

  • Any user must be able to INSTANTLY understand the tool
  • The sign up form should be as short and quick as possible (no email verifications!)
  • It should be fun
  • It should use be very visual (IE – if you can convey the information visually on a map, or control input visually without using a drop down box, do it)

How I built

I used the following libraries / gems

  • open_id_authentication (with ruby-openid) – providing services to authenticate against open id servers. This plug-in is FANTASTIC.
  • restful_authentication – very great plugin by technoweenie to handle user authentication.
  • gravatar – Does the job to display user gravatars on your site.
  • indicator – indicator helper methods and javascript.
  • recaptcha – Put recaptcha’s on your website. Worked great!
  • rspec and rspec story runner to test.
  • uber-builder – A fine form builder library. Render the same form partial as a static form and get your view for free. Supports various layout styles like tables, ul / li, etc. and does not get in your way.


  • To host, I got a Linode slice. They’ve been really great so far.
  • Bought the domain from
  • I made heavy use of rails ActiveRecord named_scopes. Man they are awesome.
  • As for Google maps, I coded straight against their JavaScript API. I wrote a resizable rectangle control for Google Maps even (contact me if you’re interested in it). Google Maps’ API is very awesome and does not need any Ruby on Rails helpers to work with maps.

Lessons Learned (so far)

User case studies are KING

I can’t tell you how important this is: after you implement any idea, find somebody who has never seen what you’ve been working on, and preferably is not well acquainted with what you have been doing. Watch them try to go through the site, take notes on what confused them, and try to see things from their point of view as they are stumbling through it. Resist the urge to help them, unless they get totally frustrated. Just sit back and quietly observe. Then, take feedback by the shovel-full.

After EXCRUCIATING user testing from my good friends and family (thanks, you guys so rock), I was able to iron out some pretty serious road blocks that would not have even been aware of otherwise.

Don’t fall in love with your own ideas

Your love affair with your ideas will almost inevitably lead to failure. Why? Because we all have blind spots, and it often takes the collaboration of several minds to get a clear picture.

When you get feedback from your user case studies, don’t be afraid to throw away code, or completely rearrange or restructure things.

For example: at first, the sign up process consisted of two parts: “search for matches” and “register your commute”. I really liked it that way – it provided flexibility. I even had the search address being stored in a session and auto-populating in the commute registration form.

When my tester got very confused, and couldn’t understand why she was being asked for her address twice, I was tempted to explain to her why it was so awesome that way. Instead, I sought to understand her point of view. Her view was more enlightened than mine, and I saw that the flexibility I as in love with was ultimately wasn’t adding value but detracting from it by complicating things. The refactoring was painful, but was also one of the greatest improvements I’d made since the first prototype of the site.

Be an information elitist

Don’t be afraid to scrap things – put every piece of information on trial, especially when you are asking your user for information: are you needed to get the job done, is your existence warranted? Persecute without mercy.

Make a clear path for the user that involves sign up.

I believe you’ve got to guide a user down a path that leads them to sign up. In my first launch attempt, I just showed a search form and let them search. Not wanting to force people to register, people got on the site, searched, and said “oh, that’s cool”. Then they missed the tiny “add your commute now!” link and closed their browser. Gone, probably never to return again.


Building has been a fun and rewarding. I hope it gets to live up to its potential and create widespread value in my community wherever it finds itself getting heavy use.

Feedback and criticism in the spirit of peer review is most welcome.

Thursday, October 2, 2008

How to has_many :through a has_many :through

So, I’ve got 3 models:

  User -< UserConversation >- Conversation -< Message

  (where -< is has many, >- is belongs to, ... etc)

I wanted, in this application, to be able to filter to all messages for a given user.


So, naturally, I first reached for this:

  class User < ActiveRecord::Base
    has_many :user_conversations
    has_many :conversations, :through => :user_conversations
    has_many :messages, :through => :conversations

  class UserConversation < ActiveRecord::Base
    belongs_to :user
    belongs_to :conversation

  class Conversation < ActiveRecord::Base
    has_many :user_conversations, :dependent => :destroy
    has_many :messages, :dependent => :destroy

  class Message < ActiveRecord::Base
    belongs_to :conversation

Which… is completly WRONG and yields results like the following:

  >> User.first.messages

  ActiveRecord::StatementInvalid: SQLite3::SQLException: no such
  column: conversations.user_id: SELECT "messages".* FROM "messages"
  INNER JOIN conversations ON messages.conversation_id =    WHERE (("conversations".user_id = 1)) 

So, apparently ActiveRecord doesn’t support joins like that. Sure, I could resort to manually specifying the finder_sql in the join and skip the has_many :through business, but then I’d lose the that cool ability to apply additional scopes after this – major FAIL.

So, I came up with a clever way to get around it.

  class User < ActiveRecord::Base
    has_many :user_conversations
    has_many :conversations, :through => :user_conversations

    def messages

  class Message < ActiveRecord::Base
    belongs_to :conversation
    named_scope :for_user, lambda { |user| user = if user.is_a?(User); { :joins => {:conversation => :user_conversations}, :conditions => ["user_conversations.user_id = ?", user]}}

And… now we can do things like:

  user.messages.matching_subject("boogy man")

etc., etc. Hurray for named_scope. So.. there's still a few issues. Namely, it's not REALLY an association - no "create" or "build" methods.

Dear web: what do think about this? Got a better way to implement the above scenario?

Saturday, August 23, 2008

Autoscroll in Safari, Firefox

The Autoscroll Bookmarklet

Bookmarklets are actually a cool little concept – make a link that runs a JavaScript command and inject code into any web-page. Brilliant! Combine this with an obsessive computer nerd with some free time on a Saturday evening (for example, me), and you get following:

AutoscrollThe Bookmarklet

Works in Safari and Firefox. If you’re lucky it might work in Opera, Camino, and Konqueror. If you’re at least as lucky as this guy, it might work in IE.


Click the really big link above to activate auto-scroll (you may want to make your window small enough to have significant scroll space

Here’s the buttons to push:

0-9 : Set scroll speed, 0 being stand-still and 9 being skim-speed
: Decrease speed
= : Increase speed
shift + – : Decrease speed quickly
shift + = : Increase speed quickly
q : Quit


If you’d like to pack this sweet action with you, drag the “Autoscroll” link to your bookmarks tool bar.

How to Daemonize Any Process

I’ve been passively looking for a tip like this for a while. Often times, I’ll need to run a command on a server that takes a good 30 minutes to run (like loading a database dump for example). Normally, I’ll run the command in the background, followed by this:

while true; do sleep 60; date; done

This has been my timeout prevention to keep commands from dying – yes it’s a pretty stinking lame solution.

Especially lame when the server drops the connection anyways.

nohup saves the day

If you need to run a REALLY long command remotely that won’t die with an SSH time out, then “nohup” is your friend.

nohup shields the commands from “HUP” signals – a signal that is sent to all child processes upon disconnecting from a terminal, that normally will stop your process (gracefully).

For example:

nohup cat the_entire_internet.sql.bz2 | bunzip2 | mysql the_internet_production &

And then, nohup will probably say something like "nohup: ignoring input and redirecting stderr to stdout", but it’s of little consequence. You’re safe to quit your terminal and your process will be safely fostered by /sbin/launchd after you take it’s parent away. Ya big mean lug.

Thursday, July 31, 2008

crontab: temp file must be edited in place

This is an error message I ran into after upgrading vim from 7.0 to 7.1, after editing a crontab file:

  crontab: temp file must be edited in place

What was weird is this error message went away if I deleted my ~/.vimrc file. If ~/.vimrc was blank, the error message was still there, so it wasn’t caused by any command in particular.

It turned out to have something to do with vim’s backup strategy. I am supposing there is a default vimrc file somewhere that gets loaded if ~/.vimrc doesn’t exist.

After some googling, I fixed it by adding the following to my ~/.vimrc file:

  set backupskip=/tmp/*,/private/tmp/*" 

VIM already defaulted this value to ”/tmp/”. I don’t know why defining my own .vimrc made vim not recognize /private/tmp/ as a temp directory any more, but I don’t care enough to find out right now.

Tuesday, July 22, 2008

VIM rocks at Textile

OK, so I am enamorated with VIM!

It so turns out editing Textile in VIM is quite awesome. Put your cursor over “h1.”, press CTRL-a, and whazam: you get “h2.” . If you use the surround.vim1 plugin, and want to bold the last three words: ‘v3bs∗’ (start selecting text, back three words, surround with ∗). If you want to turn 3 words into a link: v3es”f”a: Convert a series of lines (single spaced) into a list: <Ctrl-v>}I∗<Space><Esc>.

What is VIM lacking then? Well, how about Textile highlighting and a command to quickly preview or render your Textile you may say? Good thing there’s a TOTALLY AWESOME PLUGIN (shameless plug) for VIM to make that a thing of yesteryear!

And Now, Ladies and Gentlement, I Bring You:

Textile for VIM – Fun for the whole family!


  • Syntax highlighting (Thanks to the work of two very cool dudes, Dominic Mitchell and Aaron Bieber)
  • Preview Textile (\tp – whamo! See texile rendered in your browser! No need to save your file first)
  • Render Textile (\tr – open a new VIM tab with the rendered HTML, so you can paste it into your favorite blogging software that doesn’t support Textile, like Blogger, for example)
  • Render Textile to a file! (\tf)

1. if you use VIM and don’t have surround.vim installed, you really should DROP EVERYTHING and go install it

The vertical climb to VIM

A good friend of mine posted an article that finally inspired me to learn another editor (even though I was, and still am, quite happy with TextMate).

What resulted was a direct vertical climb up the the learning curve of VIM:

And, painful it was! There were times when I felt obligated to keep using it, even though I longed for the simpicity of TextEdit or TextMate. Why did I do it? Well, when I learned how to chain commands together I was addicted! And then there was finding out that VIM does all the things I’ve wanted an editor to do for a long time.

A few of the features I love:

  • Ability to chain commands together (d3w, di”, c/Word, g~e etc)
  • Visual block mode
  • VIM plugins
  • Complete from words in doc
  • Lots of navigation keys to get you precisely where you want to be in less than 3 key strokes
  • VIM follows me everywhere – Desktop, terminal, linux, unix, windows, OS X)
  • Multiple registers (clipboards)
  • Macros
  • The ”.” key (repeat last edit)
  • Many more

I now really fancy this old-timer VIM, and as my friend described, I can shovel around text by the shovel-full. It’s an amazing feeling! I still feel all warm inside and excited when I go to edit a bunch of text and get to hop around, move stuff around, make spelling corrections, all without moving my hands off the middle of the keyboard!

Monday, June 23, 2008

Can you find the exclusive lock?

Here's the quiz of the day: Can you find the exclusive lock in this code?


(hint: it begins on line 2, and ends on line 36)

It seemed reasonable that ActiveRecord.allow_currency would make my application be able to run concurrent queries. Well, that's what I thought :) Until I had discovered my 6 threads (which properly formed 6 new connections to the database) were still executing queries serially, instead of in parallel! When investigating what the hold up was, I found my culprit: Ruby 1.8's green threads lose control when you run native C functions, well at least Mysql#query anyways.

So, note to self and world: any time you run a native function that takes a long time, look forward to a big, exclusive lock down.

All the more reason I'm excited for Ruby 1.9's native threads

So, web, do you know if there's a way to "poll" ruby's thread scheduler while in a native C function while waiting for some other task to finish?

Saturday, June 14, 2008

Quiz of the day:

What does this wrecking ball and a developer who neglects to create and maintain an automated test suite have in common?

Thursday, June 12, 2008

Garbage collect every git repository on your machine

One of the things I really like about git is that it doesn't automatically garbage collect and compact repositories. It's kind of like how you don't clean your room and take out the garbage (or at least I don't) every time you make a mess or throw something away. If you accidently throw something away, you can pull it out of the trash before it goes to the dump. You don't have to be slowed down by a clean up operation when you're focusing on getting things done.

However, there is a draw back to this. Git repositories DO start to slow down after a while if you aren't "cleaning your room". And, they won't be as efficient in disk space utilization.

Lucky for us, since we are working with computers here, we don't have to clean our rooms by hand. The following little bash script will crawl your whole hard drive, look for any git repositories, and then garbage collect, prune, and pack them, regaining your disk space and making your repositories operate faster:

find . -type d -name .git | while read dir; do pushd "$dir"; git gc --prune; popd; done

PS: ref logs keep objects from being pruned. More on ref logs in a future post.

Tuesday, June 3, 2008

Saturday, May 17, 2008

activescaffold_sortable updated (with a delightful screencast)

After some long neglect, I finally had a reason to use the active_scaffold_sortable plugin again. Getting in to the code, I was ashamed at how broken it was. But, after about an hour of polishing and cleanup, it's good as new and ready to be used again.

Here's a screencast to show you exactly what it is:

See: activescaffold with sorted lists is fun!

Note: the urls for the repositories have been moved since this screencast was made. The new home for active scaffold repositories can be found here:

Webrat with RSpec story runner does indeed == chunky bacon

Ben Mabey, a stellar URUG member here, has posted some amazing content for the RSpec Story Runner and using Webrat:

If you haven't heard of the RSpec Story Runner or Webrat, and are interested in integration testing for your website, you really should be checking these articles out.

Webrat can be found over on the Webrat Git Repository

Friday, May 2, 2008

Mod_rails is AWESOME

Last week, as I was about to deploy a small application, I got a case of "ughh". Well, if there is such a case, I had it. Normally, I deploy with mod_fcgid, Apache, and suexec. It's an awesome solution that's difficult to set up but easier to maintain.

mod_fcgid Deployment

Roughly, here's the steps to such a deployment:

  • Download FastCGI. Compile and install it.
  • Install fastcgi ruby gem.
  • Download, compile, and install fcgid for Apache 2. Edit apache config to load the module.
  • Deploy the source code / database. Make sure it's in the directory that suexec is set to "allow".
  • Add a virtual host. Make sure you allow the .htaccess file to override. Set a user and group to run the app as.
  • Check your .htaccess file. Comment out the "cgi" line and uncomment the "fcgi" line.
  • Make dispatch.fcgi executable. Make the shebang point to a valid ruby path.
  • Make dispatch.fcgi not publicly writable.
  • Make public not publicly writable.
  • Make your app not publicly writable.
  • Add these steps to your capistrano deploy script to make sure this is always the case.
  • apachectl graceful.
  • Cross your fingers - didn't work.
  • Check your apache error log.
  • Oh crud... I forgot to do such and such.
  • Fix it.
  • apachectl graceful.
  • Try again.
  • See another error screen.
  • Check your apache error log.
  • Ugh, forgot that too.
  • Fix that.
  • apachectl graceful.
  • Repeat several times until application starts.
  • Enjoy!

You can imagine why I dreaded doing that for one tiny non-mission-critical application with one controller.

Mongrel Cluster with HTTP Proxy Deployment

The Mongrel Cluster / HTTP proxy is a great solution, perhaps the most popular now. I've never been a huge fan. Why? Well... I'll tell you (he's going to tell, he's going to tell... @ 7:30)

  • It's one more thing to make sure is running.
  • When you restart your cluster and don't redirect all the requests to a "we're down" page, Apache gets backlogged and all your users get a nice "Service not available" screen.
  • Sometimes mongrels don't restart.
  • Sometimes one doesn't come back up.
  • Mongrels never cycle through in their life span, so if your app has a memory leak, you're memory is going to creep.
So, it's a great option, but more work than I'd like to do, and I'd still prefer to set up mod_fcgid because I'm much better at it than mongrel, and I just really like having Apache start my application servers.

Passenger (mod_rails) to the rescue

So I heard some buzz recently about Passenger (aka mod_rails): something about rails deployment as easy as uploading your application. That sounded really good. I didn't care about benchmarks for this app, but as it turns out, passenger is about on par with "thin", and is faster than mongrel! Sweet lovin'.

After 2 minutes of going through the setup instructions and deploying my code, I was incredulous. "Watch, I'm going to start the application up, and everything will just fall apart." I was pleasantly proven wrong!

Here's a summary of the install steps for mod_rails (Passenger)

  • Gem install passenger.
  • Passenger-install-apache-module.
  • Copy and paste the 3 lines of apache config.
  • Deploy your app source code / set-up db.
  • Set up your virtual host (in 4 lines of code).
  • apachectl graceful.
  • That's it! Really!

And, I was pleasantly shocked to discover that it intelligently ran the rails processes as the user I deployed the application as. It checks config/environment.rb, and runs as the owner of that file. Hot stuff! And to reboot the server, just type "touch tmp/restart" - You could reboot your app with scp, rsync, ssh, ftp, samba, magnetic needles, anything! No need to have sudo access. No pid files. No "killall". Hot hot hot!

How's stability? I've converted our mongrel and fcgid deployments over to mod_rails now. Things are running smoothly. There seems to be a bit of a lag if the app isn't in use for a while (I don't think it keeps a minimum pool available, which would be a nice feature). I had a few issues with slowness on version 1.0.1, but 1.0.2 and onward has been rock solid. Oh - 1.0.4 doesn't work on the default install of Apache server for OS X Server - use 1.0.3 instead.

In Conclusion...

Here's a table of deployment scenarios with strengths and weaknesses, according to me and my experience.
mod_rails fcgid Mongrel Cluster
Speed Great (enterprise edition rumoured to be much faster) Great Great
Memory usage Slightly better (enterprise edition rumoured to reduce memory consumption by 33%) Slightly better Average
Reliability Great Great Pretty good
Ease of setup Easy Difficult Moderate
Graceful restarts?
(restart app w/out dropping a single request)
Yes Yes Possible (send kill -USR2 all mongrel pids)
App restarted on apache restart Yes Yes No
Automatic process cycling Yes Yes No
Process management Allocates on demand Allocates on demand Fixed regardless of load
Ability to set minimum process count per App No Yes Yes
Set max process count per App No (... actually, yes!) Yes Yes
I'm completely converted. I'm never going to go through that deployment nightmare again! Kudos to the Phusion folks for putting such a great solution together. If you've got a small app that you need to deploy, give it a spin. You won't regret it.

Friday, April 11, 2008

MySQL, eat your food! Come on... eat it!

OK - a word to those as wise as I was previously to encountering this issue:

Do you have text blobs bigger than a few MBs that you'd like to log to the database? Guess who did? Here's a great thing to know about that:

max_allowed_packet - Maximum allowed packet size. In other words - if your query is bigger than this number, MySQL will clench it's little lips up and spit it's food back in your face (or is that my 1-year-old daughter?). This variable defaults to 1MB. You can set it up to 1GB.

Now for the fun part - since I didn't know about this value (nor that the data I was logging was going to get so big) mysql wouldn't take my 20MB+ insert query. Then, the ExceptionNotifier plugin (the helpful plugin that tells you when you have errors, and tells you what the errors were about) wanted to be kind enough to tell me about it. Not only did it try and email the failed query, but it multiplied it a few times, and spit out all kinds of other information. This ultimately sent our server into a tailspin and ate up all the cache. We had to call Rack-Space and ask them to get us back up and running again.

Moral of the story? Well, if you're gonna feed MySQL a 20MB chunk of data, make sure you set the max_allowed_packet variable higher. And, watch out for ExceptionNotifier. I've got a giant TODO on my list of things to do to go and patch ExceptionNotifier to prevent that from happening again.

Until then, may you be wiser than I was.

Thursday, April 10, 2008

Munin - "Possible attempt to put comments in qw() list"

Yesterday I set up Munin, by recommendation of a good friend of mine. It's like an EKG, only for servers, and produces charts like the following:

It can produce charts for literally any resouce you can think of (provided you have some way to get to the data via scripting). It'll produce charts for the last 24 hours, week, month, and year.

Installation Hurdles:

No packages for RHEL5!

I installed Munin on a server running RHEL5. Which, for me, meant no packages! The instructions here worked well for me.

Perl library went missing: "Can't locate in @INC"

On the host, I had to download rrdtool. Even after installation, the munin-cron process still failed to find it (even if I modified the PERL5LIB variable to include rrdtool's isolated include directory.

Cron jobs have a very bare environment. Modifying the PERL5LIB environment variable in the cron file to include the rrd-tool library did the job (hint: to edit the munin's user cron jobs, run crontab -e as the user munin).

PERL5LIB = /usr/local/rrdtool-1.2.27/lib/perl/5.8.8/i386-linux-thread-multi/
*/5 * * * * /opt/munin/bin/munin-cron # Update munin every 5 minutes

Warning spam: "Possible attempt to put comments in qw() list at /opt/munin/lib/munin-graph line 169"

Now munin was working. However, I started getting this email message every 5 minutes (since all cron system errors get directed to me):

Possible attempt to put comments in qw() list at /opt/munin/lib/munin-graph line 169

Turned out, the munin-graph perl script includes a -w flag in the shebang line. This flag tells perl to be extra-whiny (perl -h claims that the warnings are extra-useful). Removing this effectively suppressed the warning.


After I installed the nodes on both machines I wanted to monitor, and installed the master process, and hooked it into the cron job, all was working peachy king. I can watch every resource on all of our machines, and see potential problems before they happen.

But, the journey's not over! I'm going to get some plugins, either via discovery or via blazing my own trail, so we can monitor all of our rails processes - see what's running, cpu usage of each, memory usage, etc., to help us detect any problems with memory leaks or rampant processes.

Saturday, April 5, 2008

Git OS X installer is official

Between mine and Geoff's efforts, we've finally reached a point where the Git OS X Installer is deemed "stable", and has now become an official source on Git's home page. There were a few major hurdles along the way:


HURDLE: Ruby script to update PATH and MANPATH failed on some machines


  • Convert script to bash. Ruby was less than reliable, due to the inability to predict where it was installed.

HURDLE: Binaries still referencing libs from Darwin Ports, instead of the libs we've bundled with the installer.


  • Add NO_DARWIN_PORTS=1 to the top of the Makefile
  • Put LDFLAGS="-L/usr/local/git/lib,/usr/lib" in the arguments for each of the make commands

HURDLE: Package installer size was whopping 40MB download, and 89 MB to install:


  • Converted the 80+ hardlinks (git-branch, git-remote, etc.) to symlinks. The OS X PackageMaker just doesn't respect hardlinks and was treating them all as individual duplicates of a file.
  • Stripped binaries of debug symbols after compiling via "make strip"


Now, the package has worked very well on machines that don't have the developer tools installed. The download size is 3.6 MB (instead of the original 40 MB), and it takes 9 MB to install, instead of 87 MB. That's pretty great progress in my eyes! And considering the fact neither Geoff or I have built a package for OS X before, it's a reasonably great accomplishment.

There are a few minor glitches still happening:

  • On some machines, it complains about not being able to create "/". This error does not mean git wasn't installed successfully, but it may mean that you need to download this script and run it manually, yourself. (or, set PATH and MANPATH in your environment to include /usr/local/git/bin and /usr/local/git/man, respectively)
  • Unless you launch Git GUI from the shell, it fails on fetch / push / clone over the network. You can use the "Open in Git Gui" droplet to help overcome this.

Download Git for OS X

Wednesday, April 2, 2008

Fun pranks

Yesterday's April Fools day was full of fun. My favorite jokes, in the following order:

Cobol on Cogs


This was my favorite one of all :) I got hours and hours of laughter with this one! My favorite was the excerpt under "Get Excited": Audio cassettes, screen-shots, and binders full of printouts! I remember the day when we used to get magazines full of printouts of computer programs so you could go and type them in on your own (note here Gentoo users: real programmers type in their own code for their operating system :P).

GitHub's SVNHub

What was especially funny about this one was that some people apparently thought it was serious!.

Google's Virgle


Google had two pranks that I'm aware of this year. I love Google and appreciate their consistent playful nature around this time of year.

I didn't find out about virgle until after the fact, but was my favorite of their two. I got a great kick out of their quiz.

Google "Custom Time"

Not nearly as great as Last year's gag, but still got a laugh or two.


I started this one, but it wouldn't have been fun without everyone who played along and had a good laugh with me. Essentially, XCodeMate installs a lot of EASILY REMOVABLE features into TextMate, all of which assign hot-keys in TextMate that open up Rick Astley's infamous video of Never gonna give you up. See, that's a feature? I'm never gonna give up on you code.

At first I had the bundle map enter, escape, tab, ctrl-option-command-b to Rick-Rollin commands, but I decided it was probably a bit too cruel and toned it down just a tad :)

Now back to seriousness!


Tuesday, April 1, 2008

Introducing... XCode Mate

No longer is it necessary to sacrifice elegance and simplicity for the power of a robust-IDE

I bring you:

The XCodeMate bundle

More details on the project page. Enjoy!


April Fools!

Thank you everyone who played along and had fun with this. If you're discovering this bundle after the fact: it was a all a joke.

However, if you're in the mood for some harmless belated-april-fools humour, the bundle install instructions are still available and should yield you with just that :)



Monday, March 31, 2008

RubyAMP released out into the wild

My company, Lead Media Partners, being as cool as they are, has fostered and encouraged me to improve TextMate to support many of the features I missed when switching from my other favorite IDE, RadRails. Over the last 3 months, I've been adding commands here and there, and have been packaging it up into a seperate bundle. With this bundle, TextMate has now officially been promoted to my favorite editor.

To see what all the hype is about, you can grab the bundle, get more info, and see a 5-minute long screencast I produced introducing the features over at

Friday, March 28, 2008

Google is awesome

Google just granted the Git-OSX-Installer project page 50MB downloads, plus another 100MB in disk space, so we can now host the Git OS-X Install packages on Google Code. (and abandon the problematic free solution)

Thanks Google! We love you!

Now, if only, there was some way to reduce the file size of the installer. Right now, everything is compiling REALLY HUGE. The MingW guys have their package down to under 8MBs. Anyone have any suggestions?

Monday, March 17, 2008

Who ate my cookie! (and other puns about browser cookies)

Recently I learned, on accident, how to create a session cookie in JavaScript (which was causing a bug in the Campfire Growl Script).

  function setCookie(name, value) { document.cookie = (name + "=" + escape(value)); }

Here's how to NOT create a session cookie:

  function setCookie(name, value, days) { 
    expire_str = days ? ";expires="+(new Date(new Date().getTime() + days*24*60*60*1000)).toGMTString() : ""
    document.cookie = (name + "=" + escape(value)) + (expire_str); 

HINT: Specify an expiration date on the cookie

If the campfire growl script is forgetting your settings, update to the latest :)

Friday, March 14, 2008

Wicked, Wicked Piano Guitar

Holy cow this guy's got passion.

Thursday, March 13, 2008

Campfire Growl Got "Sticky"

Sometimes, when two other people are conversing in campfire, I tend to watch the little growl bubbles fly by and not give them much attention. Then, when they ask for my input, I'll usually keep going on about my day, without even noticing.

This is part of the reason why my Adium chat logs are full of messages like: "Hey Tim, you get my CF message"?

Not DRY.

So, a new feature was born. Growl at everything and "stick" when your name was said (meaning, show the growl message FOREVER... or at least until you click it). Having it growl only when your name is said is still an option.

To upgrade: uninstall the script (In the Menu: "UserScripts" -> "Manage Userscripts" -> Select Script -> "Uninstall this Script"). Repeat the install instructions again. Or, get fancy, if you have the fancy smarts.

Here's the script. Enjoy!

Wednesday, March 12, 2008

Git installer for MacOSX Leopard (intel only)

We've switched to git almost entirely. After running into some rather painful overhead with getting everyone on Git (especially our designers, who generally don't have Developer Tools installed already), I set out to create an installer. Here are the fruits of that endeavor:

Download Git for OS X

It's worked well on several Leopard machines. It ships with it's dependencies, and will handle updating your environment variables in ~/.MacOSX/environment.plist, ~/.profile, and ~/.bash_profile for you. Isn't that nice? Everything is installed cleanly into the directory /usr/local/git, so removal is easy. See, git is your friend now.

If you've got another installation of Git, you may want to remove it first before switching over to the package distribution

Want to build your own package for Git and OSX? Head on over here, for the source and instructions used to create the package.

Update: The original release was 40MB and took up 85MB of hard disk space! After some optimization tips from Pieter and Johannes Schindelin, it's now weighing in at 3.2MB download, ~8MB installation size. Much better!

Tuesday, March 11, 2008

New version of Campfire script out!

Lots has happened with the campfire growl script since it's release. Thank you for everyone who has supported me with positive feedback! You keep the open source community thriving!

Briefly, here's the news:
  • Todd Ditchendorf contacted me about including the campfire script in the next release of Fluid. The Fluid script bundle is here.

  • Technoweenie (Rick Olsen) extended the script to growl only when your name was said. What an awesome idea! I wanted more flexibility since I'm in several rooms that require different levels of attention. So, I added a configuration pane:

    • Growl only when someone says your name:

    • Want to watch multiple words? Use a regular expression! Kapow!

    • It's configurable per room

    • Settings are stored in a cookie

  • Also, Robby Russel posted some detailed instructions on how to install the campfire growl script. He did an awesome job, and I've got to add in, Robby is one cool cat. Initially, a lot of people got the impression that it was Robby's script (because his blog gets so much coverage than mine). When I wrote him about it, he quickly fixed it. Also, Todd is a stud too. He wrote up an article on his blog clarifying the matter. Thanks Todd! It's people like Robby and Todd that make open-source development fun and fulfilling.

Monday, March 10, 2008

Git Textmate Bundle 1.1.1 released

After being in the forge for quite some time, the Git textmate bundle version 1.1.1 (and 1.1.0) has been released out of the shoots

This release includes several bugfixes and updates to make it more compatible with Git (the current latest version of git). Backwards compatibility for Git 1.5.3.x has been maintained.

The code has been completely reorganized into a mini-mvc templating framework, with a JavaScript library making it easy interact with the controllers and do some Ajax-like stuff. The end result is MUCH easier coding and less code duplication (it's no longer necessary to write custom gateway scripts to interact with git). The bottom line: easier to make it feature rich and intelligently interactive.

To see a full list of changes, refer to the CHANGELOG

Also, a list of what's planned can be accessed here: TODO

Please send comments, questions, support requests, etc. to the Git-tmbundle google group


Saturday, March 1, 2008

Growl Notifications for Campfire / FluidApp

37 Signals' campfire users: If you haven't heard of Todd Ditchendorf's "Fluid" for MacOSX yet, it's a fantastic piece of software that allows you to embed your favorite web-applications into a site specific browser. Recently, release 0.7 of FluidApp included a JavaScript API which allows you to set Badge icons and Growl messages.

37 Signals has been excellent on getting campfire integrated with FluidApp and adding badge icons to campfire for Fluid.

I wanted a bit more functionality, so I whipped up a GreaseKit script which adds growl messages:

Free Image Hosting at

Click here for installation instructions on how to get growling on campfire

Tim the Enchanter

I've been putting this off for a long time. It's sad to say that for me, the largest impediment to undertaking a blog was lack of a name I could get excited about. When I found out the domain "" was available... I got all jittery inside and I jumped on it! After all, had I procrastinated but a few minutes longer, such a golden opportunity to capitalize on my name being in a favorite movie of mine might have been lost. I'll channel my updates, discoveries, and thoughts through this channel. Thanks for reading!