<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-29194345</id><updated>2011-11-27T16:47:29.643-08:00</updated><category term='Backpack'/><category term='MovableType'/><category term='Portland'/><category term='Performance'/><category term='web-services'/><category term='Amazon'/><category term='fonts'/><category term='JohnNack'/><category term='Oregon'/><category term='storage'/><category term='eBay'/><category term='mind mapping'/><category term='RubyOnRails'/><category term='Apple'/><category term='coworking'/><category term='House'/><category term='Sparkle'/><category term='DealBase'/><category term='Integrity'/><category term='presentation'/><category term='Testing'/><category term='Photoshop'/><category term='bike'/><category term='Flash'/><category term='travel'/><category term='RSpec'/><category term='Perforce'/><category term='git'/><category term='Slicehost'/><category term='TextMate'/><category term='Mac'/><category term='Flex'/><category term='Hudson'/><category term='Apache'/><category term='Litespeed'/><category term='recipes'/><category term='laptop'/><category term='Indi'/><category term='Adobe'/><category term='LoadBalancing'/><category term='Adobe Air'/><category term='business'/><category term='jQuery'/><category term='MySQL'/><category term='PDF'/><category term='ContinuousIntegration'/><category term='Rails'/><category term='RailsConf07'/><category term='synchronization'/><category term='Gmail'/><category term='Photography'/><category term='screensaver'/><category term='packs'/><category term='Eugene'/><category term='cloud'/><category term='Marche'/><category term='HomeTheater'/><category term='Nuvo'/><category term='networking'/><category term='Versioin Control'/><category term='Drupal'/><category term='bookmarklets'/><category term='iPhone'/><category term='Rocklin'/><category term='GPS'/><category term='CruiseControl'/><category term='ShipFu'/><category term='Visionary'/><category term='JavaScript'/><category term='Capistrano'/><category term='cooking'/><category term='Virtual Desktops'/><category term='Twitter'/><category term='podcast'/><category term='Pandora'/><category term='Pivotal Tracker'/><category term='Espresso'/><category term='RailsConf08'/><category term='Photos'/><category term='ActionScript'/><category term='Thin'/><category term='environment'/><category term='wine'/><category term='.Mac'/><category term='GoogleEarth'/><category term='sync'/><category term='Leopard'/><category term='RubyCocoa'/><category term='TiVo'/><category term='Moving'/><category term='CSA'/><category term='green'/><category term='RSpactor'/><category term='Bring Light'/><category term='Mozilla'/><category term='consulting'/><category term='cycling'/><category term='Facebook'/><category term='Social Networking'/><category term='restaurants'/><category term='HDTV'/><category term='Mobile'/><category term='meme'/><category term='RainsConf'/><category term='Mongrel'/><category term='REST'/><category term='ajax'/><category term='Office'/><category term='RailsConf'/><category term='WordPress'/><category term='Nginx'/><category term='startup'/><category term='Jobs'/><category term='music'/><category term='monitoring'/><category term='Sinatra'/><category term='Java'/><category term='kitchen'/><category term='Jelly'/><category term='OpenSource'/><category term='cameras'/><category term='GTD'/><category term='TextDrive'/><category term='Ruby'/><category term='food'/><category term='Linux'/><category term='Flickr'/><category term='Cocoa'/><category term='Authentication'/><category term='coffee'/><category term='Ubuntu'/><category term='skiing'/><category term='Passenger'/><category term='WiFi'/><category term='Books'/><title type='text'>Code Intensity</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default?start-index=101&amp;max-results=100'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>226</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-29194345.post-5126289693020547466</id><published>2009-10-02T09:25:00.000-07:00</published><updated>2009-10-02T09:43:03.633-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DealBase'/><title type='text'>DealBase Now With RSS Feeds For Hotel Deals</title><content type='html'>I've been extremely busy with DealBase work, so have lagged on blogging, but have some interesting things coming up and hope to post more soon.  Recently I added RSS feeds to all of the city/destination and hotel pages on &lt;a href="http://www.dealbase.com"&gt;DealBase&lt;/a&gt;.  This is just one more way for you to keep up to date with all the deals we add to the system.  Our other primary way, aside from browsing the site of course, is to sign up for &lt;a href="http://www.dealbase.com/alerts/new"&gt;personalized alert emails&lt;/a&gt;.  This lets you follow one or more cities, and set criteria like class of hotel (i.e. you only want to see 4 and 5 star hotels), maximum price, and so on.  You can set a schedule for how often you want the emails (once a week, twice a week, daily, etc.).  We'll send you up to the best 10 deals that match your criteria.  You can also simply &lt;a href="http://www.dealbase.com/alerts/new_email"&gt;subscribe by just supplying your email address&lt;/a&gt; and nothing else and we'll set your initial preferences for our top 10 destinations.  We'll continue to enhance this alert service, and I'd love to hear any suggestions people have for additions, changes, etc.&lt;br /&gt;&lt;br /&gt;Development of the alert emails has been interesting.  One of the most useful tools throughout has been &lt;a href="http://litmusapp.com/"&gt;Litmus&lt;/a&gt;' email testing service.  It's pretty slick.  They cover quite an array of email clients, both web hosted (Gmail, Yahoo, Hotmail, etc.), as well as desktop (Outlook, Apple Mail, Notes, etc.).  They also do spam testing.  When you begin a test, they supply you an email address specific for that particular test run, and then you just email them the real email you want tested.  You can also paste in an email, but I prefer to do the sending approach to as closely mimic the real thing as possible.  I have my IRB and various other bits configured to make it a single command to fire off test cases to a Litmus supplied email address, and the whole process works great, and is truly worth Litmus' cost.&lt;br /&gt;&lt;br /&gt;I started off mentioning RSS, and back to that...  The RSS does work differently than the email alerts (obviously), and to some degree the web page.  It is like selecting the "Most Recently Posted" sort on a page (see below image).  Deals are supplied to the RSS feed as they're posted, just like a blog would do.  Just one more way to stay on top of deals.  Oh, and don't forget &lt;a href="http://twitter.com/hoteldeals"&gt;we're on Twitter&lt;/a&gt; too.&lt;br /&gt;&lt;br /&gt;&lt;div class="thumbnail"&gt;&lt;a href="http://skitch.com/chrisrbailey/nbwy1/las-vegas-strip-hotel-deals-find-a-cheap-las-vegas-strip-hotel"&gt;&lt;img src="http://img.skitch.com/20091002-pqjtqxxmjkjwiw3nutt1e9ui77.preview.jpg" alt="Las Vegas Strip Hotel Deals - Find a Cheap Las Vegas Strip Hotel" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family: Lucida Grande, Trebuchet, sans-serif, Helvetica, Arial; font-size: 10px; color: #808080"&gt;Uploaded with &lt;a href="http://plasq.com/"&gt;plasq&lt;/a&gt;'s &lt;a href="http://skitch.com"&gt;Skitch&lt;/a&gt;!&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-5126289693020547466?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/5126289693020547466/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=5126289693020547466' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5126289693020547466'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5126289693020547466'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2009/10/dealbase-now-with-rss-feeds-for-hotel.html' title='DealBase Now With RSS Feeds For Hotel Deals'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-1498274407509808765</id><published>2009-08-20T14:28:00.001-07:00</published><updated>2009-09-01T10:00:57.917-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Hudson'/><category scheme='http://www.blogger.com/atom/ns#' term='Integrity'/><category scheme='http://www.blogger.com/atom/ns#' term='ContinuousIntegration'/><title type='text'>Further Continuous Integration travels: Hudson, and Back to Integrity</title><content type='html'>&lt;span style="font-style:italic;"&gt;[Update: I resolved the Git issue, and have now switched to using Hudson.  The advantages of it's in-progress display, ability to more closely monitor and/or kill a build, and my impression of it being more stable, won the day.]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;After switching our CI server to Integrity, there were a few blips, one of which is that we were hitting swap (memory).  Hitting swap is not surprising and I'm surprised it hasn't been a problem sooner, since memory is our #1 battle.  I figured if I was going to up the memory on our CI server, I might also try Hudson, as that was the main reason for not trying it previously.  &lt;br /&gt;&lt;br /&gt;The short story is that I tried it, and we're back to Integrity, but I learned some interesting things.  The following is both some notes on installation, as well as some reasons why it didn't work out...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Installing Hudson&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Our CI box is a slice at Slicehost, running Ubuntu 8.04 LTS, and I'd just upped it from 256MB RAM to 1GB.  Also of note, I've built and install Git 1.6.4 for this system.  The following are brief notes on getting Hudson going as it wasn't quite as simple as most folks made it out to be...&lt;br /&gt;&lt;br /&gt;First, I followed the directions on the Hudson site for &lt;a href="http://wiki.hudson-ci.org/display/HUDSON/Installing+Hudson+on+Ubuntu"&gt;installing Hudson from the Ubuntu package&lt;/a&gt;.  This amounts to adding the package repository, updating apt-get, and then doing:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;sudo apt-get install hudson&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This installs all the Java 1.6 stuff you need (and mine seems fine with 64bit Java), and other dependencies.  After the install, Hudson is running, on default port 8080.  Next up I added a server block/configuration in Nginx for Hudson (and unlinked/removed Integrity).  I then went to Hudson in my browser.  What I got was an error message about the xstream library.  Fixing that was easy, as it turned out: downloaded the latest (1.320 at the time) hudson.war from the Hudson site, and replaced &lt;code&gt;/usr/share/hudson/hudson.war&lt;/code&gt; with it.  Restarted Hudson, and voila, now it was up and running.&lt;br /&gt;&lt;br /&gt;Also, Hudson runs as the user "hudson", so I needed to add an SSH key for that user, and then add the public key to GitHub.  And, setup a ~hudson/.gitconfig as needed.  Finally, as I found later, do a git clone or an SSH to github so that you get past the whole SSH authenticity question when you first SSH to an unknown server.  Note, the Hudson user is not an interactive user, i.e. you can't directly login as that user, so to gen the SSH key, you'll need do something like su to root and do, &lt;code&gt;sudo -u hudson ssh-keygen -t dsa&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Configuring Hudson&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Before adding a project, I needed to config some plugins.  I went to the Manage page, clicked on Installed, and turned off the Subversion plugin and restarted.  Next was going back in to manage plugins, and installing the Git, Github, and Rake plugins, and again restarting.  Both restarts showed an Nginx bad gateway error, but simply refreshing got it back (probably just needed more time for Hudson to restart).&lt;br /&gt;&lt;br /&gt;Then to configure a build, from the main Hudson page after a fresh install, click the "create new jobs" link.  In the ensuing form, enter a project name, and select "Build a free-style software project".  &lt;br /&gt;&lt;br /&gt;Next:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;checked "Discard Old Builds" which then shows you options (so you can put in keep for X days, or X number of builds)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Added URL for Github project, http://github.com/yourproject/yourproject&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Select Git as the SCM, and entered by git@github.com:yourproject/yourproject.git URL for the repository&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Turned on merge after build option.  This will supposedly add tags for the build to your code base and then merge them back in.  More on this in a bit.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Next I configured the build steps for my project.  All I really did here was take the same build &lt;a href="http://codeintensity.blogspot.com/2009/08/setting-up-integrity-for-continuous.html"&gt;steps I used for Integrity&lt;/a&gt;, and added them as individual shell and rake tasks.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;At this point, I fired off a build (truth be told, I started with just a single build step to vet it), and things worked, with the exception of the very last step, where I push the Git tags back to GitHub.  This is what I saw:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;[workspace] $ /bin/sh -xe /tmp/hudson1444107192962944065.sh&lt;br /&gt;+ /usr/bin/git push --tags&lt;br /&gt;XML error: syntax error&lt;br /&gt;error: Error: no DAV locking support on https://github.com/dealbase/dealbase/&lt;br /&gt;error: failed to push some refs to 'https://github.com/dealbase/dealbase'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I've now been searching for answers to this, and haven't yielded anything.  I've tried the git push directly from a shell, with the same result.  If I do this as a different user (e.g. under my user) it works fine.  This git push is attempted both as part of a rake task (the ci_tag task), as well as I tried making it just a straight shell command in Hudson.&lt;br /&gt;&lt;br /&gt;After a lot of googling, and asking, and no resolution in sight, I've gone back to Integrity...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Comparisons and Notes&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;First off, I think Hudson looks pretty stellar.  There are a TON of plugins for it, and it seems quite mature and polished.  The essentially 100% configuration via the GUI is slick.  Install, despite a few hoops above, was actually pretty painless.  So, here's just a few notes/opinions:&lt;br /&gt;&lt;h3&gt;Hudson&lt;/h3&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;You will need some memory to run Hudson, more than with Integrity or CruiseControl.rb.  From what I can tell, you probably want a system with 1GB or more.  Various other folks I talked to all had 2GB or more systems, and their Hudson processes were taking 1.5GB or more.  This is partly just a Java thing.  It should be noted, the others were running more than one build with Hudson, and mine seemed to work fine on a 1GB total memory system (didn't seem to hit swap).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Hudson allows you to kill a build while it's running (nice!).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Hudson works with CCMenu/CCTray out of the box.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The git integration has more options in terms of picking branches, doing merging, and various more involved operations, but doesn't have GitHub post-receive hook support out of the box (there are plugins up on GitHub for it, but not listed in the standard plugin list).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Hudson runs as user "hudson", which is a user that has no shell.  You could change this, although the idea is you shouldn't have to.  However, this complicates setting up SSH keys and various things.  And, of course, I had the issue with Git as mentioned above.  I could probably change this to run as my user and so on, but part of all this for me is not having to change a lot of defaults and start messing with core configurations/designs of the system.  In part, I just don't have time to do that, and to maintain it (these kinds of changes often cause problems when you upgrade versions, etc. - also known as you may forget to redo these changes if an upgrade undoes them :).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The UI and web app itself is quite nice, understandable, well done in general for something like this.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Also, thanks to the &lt;a href="http://blog.mattwynne.net/2009/04/21/goodbye-cruisecontrolrb-hello-hudson/"&gt;Tea-Driven blog&lt;/a&gt; for motivating me to try Hudson (and for some tips on Testjour - more on that in another post).&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Integrity&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;I really only have one main complaint about Integrity, and that has to do with indication of a build in progress.  It essentially doesn't indicate it - it says it hasn't been built yet, but a build may actually be running.  The CCMenu/integritray plugin will show you that a build is running, so this mostly solves my problem, but this seems like a core failure.  I may have to look at fixing this.  And that is a win for Integrity in that it's Ruby, and thus I'll be more apt to go fix this (while I spent MANY years doing heavy Java work, I don't have interest in working in that code anymore for a task like this).&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;CruiseControl.rb&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;One thing that remains an advantage for CC.rb is that it has "build artifacts" - i.e. you can create files and such as part of your build and have those known to CC.rb, where it then links to them in the summary of your build.  You may or may not need it, but it's also very handy for simply showing you the Git tag you created on a successful build.  I just touch a file in the build artifacts dir with the name of the Git tag, and then I don't have to dig through the output of the build to find my Git tag.&lt;br /&gt;&lt;br /&gt;That's all the time I have for today, hopefully this is also helpful to others...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-1498274407509808765?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/1498274407509808765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=1498274407509808765' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/1498274407509808765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/1498274407509808765'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2009/08/further-continuous-integration-travels.html' title='Further Continuous Integration travels: Hudson, and Back to Integrity'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-303584159080497120</id><published>2009-08-17T16:09:00.000-07:00</published><updated>2009-08-17T16:10:02.104-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Integrity'/><category scheme='http://www.blogger.com/atom/ns#' term='ContinuousIntegration'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Setting up Integrity for Continuous Integration</title><content type='html'>Recently I switched the &lt;a href="http://www.dealbase.com"&gt;DealBase&lt;/a&gt; continuous integration server to use Integrity instead of CruiseControl.rb.  This happened because I'd been having some sporadic failures under CC.rb that didn't seem explainable (no code would change, and tests would fail at random), and also due to some changes in Cucumber between versions, it all conspired to switch.  &lt;br /&gt;&lt;br /&gt;It should be noted that, as you might guess, the "random" failures were not exactly random, but suffice it to say that the root cause re-inforced my notion to switch.  My main beef with CC.rb has more to do with it being somewhat in bed with Rake and wanting to run your CI build via a rake task, and some of the issues (or impurities?) that come up with that.  But I'm boring you...&lt;br /&gt;&lt;br /&gt;Anyway, Integrity... Setup is relatively easy, and is covered fairly well on &lt;a href="http://integrityapp.com/"&gt;their setup page/docs&lt;/a&gt;.  But the following is what I did, which I'm documenting for myself and anyone else who may find it useful.&lt;br /&gt;&lt;br /&gt;I setup my server to use with Nginx and Passenger.  I tried using Integrity with Nginx and Thin, but wasn't able to get Integrity to work right (similar to the results defunkt had &lt;a href="http://github.com/blog/471-continuous-integration-spring-cleaning"&gt;when they tried it at GitHub&lt;/a&gt;).  We've standardized on Nginx+Passenger, so this was good anyway.  I nuked the Nginx I had already and proceeded (all this being done on an Ubuntu Hardy VPS system at Slicehost):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;sudo gem install passenger&lt;br /&gt;sudo passenger-install-nginx-module&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I let it install Nginx, and picked the default location.  I then re-added our HTTP Basic Authentication and a few other Nginx tweaks as I had in the prior Nginx configuration.  Next up was to install some prerequisites and Integrity itself:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;sudo apt-get sqlite3 libsqlite3-dev&lt;br /&gt;sudo gem install integrity do_sqlite3 thin&lt;br /&gt;integrity install /home/ci/integrity --passenger&lt;br /&gt;cd integrity&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Next you'll want to tweak config.yml to customize the domain where you'll access your CI server.  I left the rest the same.  Then setup Integrity's database:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;integrity migrate_db /home/ci/integrity/config.yml&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I also added the "integritray" plugin, so that I could continue to use &lt;a href="http://ccmenu.sourceforge.net/"&gt;CCMenu&lt;/a&gt; to monitor my builds.  See the &lt;a href="http://github.com/jfrench/integritray/tree/master"&gt;integritray GitHub page&lt;/a&gt; for simple install.&lt;br /&gt;&lt;br /&gt;Now point Nginx/Passenger at your install, by adding the appropriate server block for a Passenger Rails app, such as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;server {&lt;br /&gt;    listen       80;&lt;br /&gt;    server_name  your.ciserver.com;&lt;br /&gt;    root /home/ci/integrity/public;&lt;br /&gt;    passenger_enabled on;&lt;br /&gt;&lt;br /&gt;    auth_basic            "Restricted";&lt;br /&gt;    auth_basic_user_file  /opt/nginx/conf/htpasswd;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finally, fire up Nginx, and surf to your CI server domain/URL.  You should see something like this:&lt;br /&gt;&lt;br /&gt;&lt;div class="thumbnail"&gt;&lt;a href="http://skitch.com/chrisrbailey/b5mhy/integrity-first-startup"&gt;&lt;img src="http://img.skitch.com/20090817-gdy8kwxgfd9uf7dxx7arxauqh1.preview.jpg" alt="Integrity first startup" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family: Lucida Grande, Trebuchet, sans-serif, Helvetica, Arial; font-size: 10px; color: #808080"&gt;Uploaded with &lt;a href="http://plasq.com/"&gt;plasq&lt;/a&gt;'s &lt;a href="http://skitch.com"&gt;Skitch&lt;/a&gt;!&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Click the "create your first project" link, and enter details about your app.  The "Git repository" field should get your GitHub or other git server URL (e.g. your clone URL).  For a build script, the following is what I used:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;rake log:clear &amp;&amp; RAILS_ENV=test rake db:reset &amp;&amp; spec --options spec/spec.opts spec/**/*_spec.rb &amp;&amp; RAILS_ENV=cucumber rake db:reset &amp;&amp; cucumber --strict -q --format pretty features &amp;&amp; rake ci_tag&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is one nice thing about Integrity - it's pretty much any command you can give it.  Sure, you might want to wrap that up in a Rake task, or a shell script or however you want to do it.  I just entered that raw so it's overly obvious exactly what it's doing.  I also found this to work better than doing it as a Rake task, as somehow I wasn't getting the environment to switch properly under Rake.  The "ci_tag" rake task is my task for tagging/labeling succesful builds in Git, etc.&lt;br /&gt;&lt;br /&gt;Next, you'll want to setup a post-commit service hook on GitHub.  You can get your Push URL by clicking the edit link for your project in Integiry:&lt;br /&gt;&lt;br /&gt;&lt;div class="thumbnail"&gt;&lt;a href="http://skitch.com/chrisrbailey/b5i6a/dealbase-integrity"&gt;&lt;img src="http://img.skitch.com/20090817-du9damc7t9xww4kje1pusq4tqk.preview.jpg" alt="DealBase | integrity" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family: Lucida Grande, Trebuchet, sans-serif, Helvetica, Arial; font-size: 10px; color: #808080"&gt;Uploaded with &lt;a href="http://plasq.com/"&gt;plasq&lt;/a&gt;'s &lt;a href="http://skitch.com"&gt;Skitch&lt;/a&gt;!&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Note, that works even with HTTP Basic Auth, just add your user credentials to the Push URL before pasting it in on GitHub.  &lt;br /&gt;&lt;br /&gt;Finally, fire off a build.  And note, one downside of Integrity is that it doesn't indicate (in the web UI) that a build is underway.  It just says it hasn't been built yet.  The integritray item and thus CCMenu will show you that it's building though.  &lt;br /&gt;&lt;br /&gt;Lastly... some have asked why not XYZ CI server?  A few notes on this:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Hudson: this looks awesome, but also somewhat overkill for our needs.  I have one project to build, and I'm doing it on a very inexpensive slice that has only 256MB of RAM - I doubt I could even start Hudson in that little RAM, being it's a Java web app, etc.  Secondarily, I'd prefer to have the app be Ruby so I can hack on it (I've made at least very minor tweaks to every CI server I've used to date).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;cruisecontrol.rb - this is what we were using, and it worked well, with minor exception to some random failures and the Rake-oriented build process.  I'd really say this is minor though, and would suggest folks try it out.  You can of course refer to &lt;a href="http://codeintensity.blogspot.com/2008/04/setting-up-cruisecontrolrb-withfor-git.html"&gt;my previous writeup on setting up CruiseControl.rb&lt;/a&gt; :)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://github.com/defunkt/cijoe"&gt;CI Joe/cijoe&lt;/a&gt; - this is actually what I started with when I looked at exploring alternatives.  I had problems getting the build working properly, which seems odd.  In hindsight that may have wound up being due to some problems during our switch to a newer version of Cucumber.  But, one thing I didn't like is that there is no state maintained, so if you stop and start cijoe, it loses track of all its previous builds.  This may or may not matter much to you, but I didn't like that.  I also didn't want to spend time writing notifiers/CCMenu integration type stuff for our needs.  I will ay that cijoe setup/install is pretty cool.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://runcoderun.com/"&gt;Run Code Run&lt;/a&gt; doesn't have a viable plan for us yet, plus I've heard having it run custom rake tasks and such doesn't work (wrong?).  Furthermore, I didn't really want our private code on their servers and didn't see a need to outsource this.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;others... either hadn't heard of them, they didn't work well with Rails, or whatever - upshot, Integrity worked, got it up and running fairly fast, and didn't need to spend any more time on this.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-303584159080497120?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/303584159080497120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=303584159080497120' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/303584159080497120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/303584159080497120'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2009/08/setting-up-integrity-for-continuous.html' title='Setting up Integrity for Continuous Integration'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-8659038905377048524</id><published>2009-06-16T13:51:00.000-07:00</published><updated>2009-06-17T11:15:51.387-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='synchronization'/><category scheme='http://www.blogger.com/atom/ns#' term='web-services'/><category scheme='http://www.blogger.com/atom/ns#' term='sync'/><category scheme='http://www.blogger.com/atom/ns#' term='cloud'/><title type='text'>Moving Further Into the Cloud</title><content type='html'>A little bit ago, I went back to using multiple computers again.  For a while I'd just done everything with a MacBook Pro, which was nice - only a single machine to maintain, always had everything in one spot.  But alas, twas time for more performance, so I got a Mac Pro, which is now my primary work machine, with the laptop relegated to basically iCal and Things for the bulk of the day (as my 3rd monitor), and then any portable needs, or working on the couch or deck, etc.&lt;br /&gt;&lt;br /&gt;Anyway, my main thing against multiple machines, after having spent many years with anywhere between 2 and 5 machines (mostly while working for Adobe), was the maintenance and synchronization of those machines.  So, now that I'm back to 2, I am back to wanting/needing my data on whatever computer I'm using.  These days this also really extends to my iPhone to some degree as well.  It's my truly portable computer.  So, with all the "cloud" computing/services these days, this is to some degree easier.  I'm not that big a fan of Google having all my data, but I will use the services that are the best in class, or best for my needs, and no doubt some of that is Google, but there are many others.  &lt;br /&gt;&lt;br /&gt;I have not gotten all my data truly available on all the computers I want it on, or as well as I'd like yet, but I'm getting closer.  Also, I agree with Al3x in that if the data is important, only having it on a free cloud service is not wise.  I haven't fully followed that, but that is part of my plan.  Here's some notes on what I've done so far...&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Email&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;This one is easy.  I use Gmail for all my email accounts (about 15 if you count across various domains and so on).  Right off, this is one case where this is the only place my data/email lives, so I'm only solving the accessible from anywhere issue.  But, I'm also of the mind that I could pretty much lose all my email and be fine.  If there are truly important things in it, that data tends to wind up getting put in somewhere else (EverNote, etc., see below) as appropriate.  Gmail is so much better than any other Email.  I even use it for some non-traditional things, like all our recipes are stored in a Gmail account.  Makes it easy to trade recipes amongst friends and family, great for searching, and again, I can get to it from anywhere I can access the web.&lt;br /&gt;&lt;br /&gt;Further, I use &lt;a href="http://mailplaneapp.com"&gt;MailPlane&lt;/a&gt; as my actual mail client.  It is a very rare day that I use a web browser to view Gmail.  On the iPhone I just use the regular iPhone mail client, which has some drawbacks, but for my needs is ok.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Notes and Misc Data&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;This is the place that recently changed and has become an outstanding solution.  I used to use 37signals &lt;a href="http://backpackit.com/"&gt;Backpack&lt;/a&gt;, but now use &lt;a href="http://www.evernote.com/"&gt;EverNote&lt;/a&gt;.  EverNote is really quite amazing.  I hadn't noticed the Notebooks before, and that's been a great feature for me to do high level organization.  Then, the searching is quite good (and of course Backpack essentially didn't even have searching).  But, what really swung this over was their desktop client, web storage, and then iPhone client.  This gives me great desktop performance, but then access from any web browser, as well as iPhone, AND I get the data stored locally and off-site (i.e. on the web).  Furthermore, it sync's across computers.  So, I feel like the data I have here is very safe (since it's in at least 3 places).  Even better, this allowed me to stop paying for Backpack (my use of EverNote is nowhere close to their paid account).  I don't mind paying for software at all, but I had felt that I wasn't getting the solution I wanted from Backpack, so didn't want to pay for that any longer.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Code&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://github.com"&gt;GitHub&lt;/a&gt; and Git.  Do I need to say more?&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Bookmarks&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Two things here: .Mac and Delicious.  I use Safari as my primary browser, and leverage it's Bookmark Bar for common stuff, so sync that across machines and iPhone with .Mac.  Delicious gets all the other bookmarks.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;RSS/News Feeds&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Another recent change was to stop using NetNewsWire which I've used forever, and switch to Google Reader.  Specifically what made this work well was creating a Fluid app with the &lt;a href="http://www.helvetireader.com/"&gt;Helvetireader&lt;/a&gt; styling.  NNW had sync via NewsGator, but it really just didn't work well.  It didn't seem to keep the list of feeds in sync, and then it's sync during feed download just didn't seem to cut it.  So now, with the fluid app, and then just plain Reader (via browser) on the iPhone seems to solve this all nicely.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Documents&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;So far this is a mix of using &lt;a href="http://www.getdropbox.com/"&gt;DropBox&lt;/a&gt; and Google Docs.  DropBox is awesome for keeping files in sync across machines, and then also available on the web.  I've been ramping up my use of DropBox.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Things that Aren't sufficiently solved yet&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Calendar and &lt;strikethrough&gt;Address Book&lt;/strikethrough&gt;&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Update: I'm now using .Mac to sync Address Book, seems to work great.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'm using iCal and Address Book.  Primarily this is due to the super easy sync with the iPhone.  I can sync two computers with BusySync or some other things, but haven't seen a great solution yet, as well as haven't investigated that much.  Even with .mac I think you still have to have a primary calendar and you're publishing to the other, etc.  &lt;br /&gt;&lt;br /&gt;I've used Google Calendar in the past, but didn't like it that much, and part of all this is ensuring sync is brain dead easy and solid.  My wife and I sync calendars with BusySync, but that has been spotty.  The various Google/iCal sync things I've tried have been iffy in the past.  And, the real key is, how well will it sync Google cal to the iPhone calendar?  An area I need to learn more about.&lt;br /&gt;&lt;br /&gt;Address Book, not sure of my options here either.  Sync's nicely with iPhone, and .Mac so far.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Music and Photos&lt;/h2 &gt;&lt;br /&gt;&lt;br /&gt;I've yet to see an iTunes sync thing that works really well.  We tried TuneRanger but it was not good when dealing with two existing libraries.  Also, we have a lot of music, so keeping it backed up on S3 or similar actually starts to cost real money.  Of course these days, the primary need for this is to sync to my iPhone.  Most of the time at home I'm listening to Pandora or some similar thing.  I use Pandora a lot on the iPhone, but I also listen to various podcasts, and then there are times when Pandora isn't feasible (crappy/no signal, or I'm needing to use another app on the phone while listening to music).&lt;br /&gt;&lt;br /&gt;These same issues hold true for photos/Lightroom libraries.  With Lightroom so far, for each calendar year, I have a Lightroom catalog, and then at the end of those years, I burn DVD's with the photos.  Of course, the DVD's are just sitting in our house right now, not in a safe deposit box, etc. (we used to do that, but haven't since we moved to Oregon - lazy).  But my bigger concern here is that I'd like my Lightroom library to stay in sync across my two machines, so I can use the burly Mac Pro when working at home, but then have my MBP when on the road.&lt;br /&gt;&lt;br /&gt;I guess that's it for now.  What solutions do you like?  What are people doing for large data (GB's or TB's of music, photos, video, etc.)?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-8659038905377048524?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/8659038905377048524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=8659038905377048524' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8659038905377048524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8659038905377048524'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2009/06/moving-further-into-cloud.html' title='Moving Further Into the Cloud'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7439675306493821796</id><published>2009-05-12T15:01:00.001-07:00</published><updated>2009-05-12T15:02:48.985-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='Passenger'/><category scheme='http://www.blogger.com/atom/ns#' term='Nginx'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Passenger Fails to Regenerate Cached/Aggregate Assets for Rails</title><content type='html'>At &lt;a href="http://www.dealbase.com/"&gt;DealBase&lt;/a&gt;, we've been testing &lt;a href="http://modrails.com/"&gt;Nginx with Passenger&lt;/a&gt;, and have mostly had good results.  There are two issues that have come up, hopefully only one of which may broadly affect others.&lt;br /&gt;&lt;br /&gt;The first issue, which likely affects anyone using this, is that it appears that if you combine and cache CSS or JavaScript via tags like this in Rails:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  &amp;lt;%= stylesheet_link_tag :standard, :cache =&gt; 'standard' %&amp;gt;&lt;br /&gt;  &amp;lt;%= javascript_include_tag :jquery, :cache =&gt; 'jquery_all' %&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The ":standard" and ":jquery" symbols are expansion symbols for multiple CSS/JavaScript files defined in a Rails initializer.  On the first request Rails gets, it's supposed to combine all the files as per the expansion symbol definition, and then produce a "cache" file, so you have a single file that is included in your HTML.&lt;br /&gt;&lt;br /&gt;This worked fine for us under Mongrel, but it didn't seem to regenerate under Passenger after doing a deploy, even with a restart to Passenger.  We had to do a second restart of Passenger, and then hit the server at least twice, if not more to see it get picked up.&lt;br /&gt;&lt;br /&gt;Thanks to a tip from Engine Yard, one &lt;a href="http://overstimulate.com/articles/deploy-rails-missing-stylesheets"&gt;solution can be found on the overstimulate blog&lt;/a&gt;, where they detail how you can add a rake task that you call during deploy to regenerate those cache files.  This is really even a nicer solution under Mongrel and others, as it will mean it doesn't occur during your first request.&lt;br /&gt;&lt;br /&gt;The second problem seems confined to my MacBook Pro laptop (no problem on my MacPro tower).  That is, I simply cannot get Nginx+Passenger to work.  It installs fine, Nginx runs, but I get some odd permissions problem from Passenger:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;2009/05/12 11:57:52 [alert] 19611#0: could not create /var/folders/7m/7m7ezMSTHdiBHz5bzVyNDE+++TI/-Tmp-//passenger.19596/control_process.pid (13: Permission denied)&lt;br /&gt;2009/05/12 12:01:19 [crit] 19611#0: *1 connect() to unix:/var/folders/7m/7m7ezMSTHdiBHz5bzVyNDE+++TI/-Tmp-//passenger.19596/master/helper_server.sock failed (13: Permission denied) while connecting to upstream, client: 127.0.0.1, server: dealbase.dev, request: "GET / HTTP/1.1", upstream: "unix:/var/folders/7m/7m7ezMSTHdiBHz5bzVyNDE+++TI/-Tmp-//passenger.19596/master/helper_server.sock:", host: "dealbase.dev"&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The first line of those two lines occurs when I start Nginx.  The second happens when I try to surf to a page from my app in my browser (which makes sense given the first error :)  If anyone has any suggestions on this one, let me know!&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7439675306493821796?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7439675306493821796/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7439675306493821796' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7439675306493821796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7439675306493821796'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2009/05/passenger-fails-to-regenerate.html' title='Passenger Fails to Regenerate Cached/Aggregate Assets for Rails'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-6059281230373602020</id><published>2009-03-11T09:49:00.001-07:00</published><updated>2009-03-11T09:49:02.320-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='DealBase'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='Jobs'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Front End Rails Developer Job at DealBase.com</title><content type='html'>&lt;p&gt;At DealBase, we have an opening for a part-time front end Rails developer at &lt;a href="http://www.dealbase.com"&gt;DealBase.com&lt;/a&gt;.  The opening is for US residents only, and for individuals, no agencies or recruiters please.  Most likely you'd be working remotely/telecommuting.  The job posting, which is posted in several places, such as &lt;a href="http://jobs.rubynow.com/jobs/show/2919"&gt;Rubynow&lt;/a&gt;, &lt;a href="http://workingwithrails.com/opportunity/1433-front-end-rails-developer-needed"&gt;Working With Rails&lt;/a&gt;, and &lt;a href="http://railsjobs.in/jobs/80"&gt;Rubyjobs.in&lt;/a&gt;, covers all the details, but I'll relist it here for ease:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-left: 2em;"&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.dealbase.com"&gt;DealBase.com&lt;/a&gt;, a startup hotel deals site, is looking for a stellar front end web developer who will adapt our current look/feel to new features, leverage JavaScript for useful and fun features, and is eager to apply their skills to  enhance the user experience of our site. We're looking for you to share your knowledge and make an impact, be passionate about your work, and up-to-date on the latest technologies.  If this is you, and you enjoy working with a small, distributed, agile team, then we'd love to talk with you.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Requirements for this position:&lt;/h3&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Deep knowledge of XHTML and CSS&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Familiarity with browser capabilities and restrictions for all major browsers&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Solid JavaScript skills&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Experience with/demonstrated use of Git&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You use and demand MacOS X as your primary development environment&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Comfortable at the command line&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Basic skills for image editing and optimization for the web&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Exposure to and basic knowledge of Ruby on Rails&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Great communication skills&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Attention to detail&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Ability to work both independently and on a team&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Eagerness to share ideas and problem-solve creatively&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Experience working on consumer oriented web applications/consumer focus&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Quick learner, and good at digging in to problems&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Agile development practices&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You are based in the US.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Individuals only (no multi-person firms, agencies, etc.)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Nice to have:&lt;/h3&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;jQuery experience&lt;/li&gt;&lt;br /&gt;&lt;li&gt;GitHub experience&lt;/li&gt;&lt;br /&gt;&lt;li&gt;MySQL experience&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Use of test frameworks, TDD, and BDD&lt;/li&gt;&lt;br /&gt;&lt;li&gt;experience with Linux&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;If you'd like to work with us at DealBase.com and think you're a good fit for this position, send us a resume and sample work, or let us know where we can see your resume and work/code, by emailing jobs@dealbase.com.  Please note, we are only considering candidates based in the US.&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I'm excited to find a great developer to work with.  DealBase has been an awesome company and app to work on, and we're already experiencing great success.  We have some pretty cool features planned, and it'd be ideal to get some real CSS and JavaScript ninja skills making those features even better.  So, if this is you, please do get in touch, making sure to send email to the right email address as outlined in the job description.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-6059281230373602020?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/6059281230373602020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=6059281230373602020' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6059281230373602020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6059281230373602020'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2009/03/front-end-rails-developer-job-at.html' title='Front End Rails Developer Job at DealBase.com'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-6423105615270366592</id><published>2009-03-02T22:20:00.001-08:00</published><updated>2009-03-02T22:20:46.791-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Capistrano'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Deploying per-server crontabs with Capistrano</title><content type='html'>&lt;p&gt;There's been a couple cool writeups/solutions to deploying your crontab files when you deploy with Capistrano, which I think is great.  I can't find the first one I saw (mention in comments and I'll update), but on GitHub, javan has the &lt;a href="http://github.com/javan/whenever/tree/master"&gt;whenever&lt;/a&gt; gem that is really more about allowing you to define crontabs with Ruby/Rails' time methods so you don't have to remember the crontab file syntax which none of us ever seems to be able to remember.  You can of course integrate this with Capistrano (and that's covered in his Readme).  The point of all this: no more having to remember to go put in or uncomment a crontab entry once you deploy a certain build, and keeping your crontabs under version control.  However, for us, none of the solutions out there worked quite right, and I just use what I find to be a simpler setup.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;First, we have multiple servers with different crontabs per server.  Also, we have some environment variables that get defined within the crontab so that they work properly on our Engine Yard slices.  I just found that, while yes, I sometimes don't remember all the crontab syntax perfectly, I also don't do this often enough for that to be an issue, and would rather just have the real deal right there, so I knew exactly what I was going to install on my server.  Lastly, I didn't really want to have yet another gem dependency for something pretty straight forward like this (IMHO).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So, get on with it you say, what's the solution?  Two pieces.  First, I create a &lt;code&gt;crontab&lt;/code&gt; directory within my Rails app's config directory.  In that I store crontab files named by the hostname of the server - the same thing you'd get by doing a &lt;code&gt;hostname&lt;/code&gt; on the server.  You could add an extension or whatever you want, but the hostname is what makes this work easily, so you want that somewhere in your file naming convention.  We only have a couple servers and I know them well, so I just went with pure hostname for now.  The contents of each file are exactly what you'd see in the crontab file on the server, for the user you set it up under.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Second, a simple Capistrano task to affect the given crontab file on the server, with an after hook to run it:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;task :write_crontab, :roles =&gt; :app do&lt;br /&gt;  puts "Installing server-specific crontab."&lt;br /&gt;  run("cd #{deploy_to}/current/config/crontab; crontab `hostname`")&lt;br /&gt;end&lt;br /&gt;after "deploy:restart", "write_crontab"&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;That's it.  You can obviously tweek this for your own setup, for example, maybe you need to run it on all roles, or different roles, or what not.  Your run command might need to be more robust (or run a shell script or rake task) for example if not all servers have crontabs or you have something more dynamic.  But, as you can tell, setting this kind of thing up is pretty straight forward, and it's great to keep your crontab setups in version control.  Thanks to you guys that stimulated the idea in the first place.&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-6423105615270366592?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/6423105615270366592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=6423105615270366592' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6423105615270366592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6423105615270366592'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2009/03/deploying-per-server-crontabs-with.html' title='Deploying per-server crontabs with Capistrano'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7992566518172871599</id><published>2009-02-04T17:53:00.001-08:00</published><updated>2009-02-04T17:53:14.703-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySQL'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>MySQL Performance Issues and acts_as_versioned</title><content type='html'>&lt;p&gt;Recently we ran into an interesting performance issue with MySQL.  We have an automated process we run at night a few nights a week that does data harvesting for hotel rates and such.  This data is versioned so that we can look at historical values.  However, this script had begun to really crawl.  Originally it took a couple hours to run.  But it had gotten to the point where it could take almost a day.&lt;/p&gt; &lt;br /&gt;&lt;br /&gt;&lt;p&gt;I tracked this down to being a SQL MAX call used by acts_as_versioned to determine the next version for one of these records.  The problem is that it had to sift through nearly 10 million records.  In testing this on my local machine, just one of these SQL queries could take 45 seconds!  Think about doing this across oh say 100,000 hotels, ya, not good.&lt;/p&gt;  &lt;br /&gt;&lt;br /&gt;&lt;p&gt;The good folks at &lt;a href="http://github.com/blog/328-database-troubles"&gt;GitHub ran into this same thing&lt;/a&gt; (with a table of 36M records) on nearly the same day.  Their approach is similar to the approach I'll be taking on another table (which isn't currently affecting us this way, but will have different benefits), which was to split it into two tables, one with older data.  I could have done this, and would have, but the reality was that we simply didn't need to keep these versions, as we weren't using the data.  So, luckily, I was able to just no longer version this particular model, and throw out that table.  After doing that, I ran the script and it took just over an hour.  Yea!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So, this is something to note if you use acts_as_versioned with models that have frequent changes and a decent number of those models to begin with (think multipliers).  One of the things I'll be looking into in the future is whether that MAX needs to get done, or whether acts_as_versioned can be smarter about how it does it.  On first glance you'd think you could just use the version number on the original model itself, but that number isn't guaranteed to be the latest number, since you can rollback versions and so on.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7992566518172871599?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7992566518172871599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7992566518172871599' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7992566518172871599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7992566518172871599'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2009/02/mysql-performance-issues-and.html' title='MySQL Performance Issues and acts_as_versioned'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-8444962367625098482</id><published>2009-01-13T23:52:00.001-08:00</published><updated>2009-01-13T23:52:16.192-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='DealBase'/><title type='text'>Renaming a GitHub Account and Forked Repository</title><content type='html'>&lt;p&gt;Today I finally bit the bullet and renamed the &lt;a href="http://www.dealbase.com"&gt;DealBase&lt;/a&gt; GitHub account and repository because it was previously named after an early incarnation of the business name (before we'd actually decided on a name).  I had expected this to be a bit tedious.  In particular, I had started the original repository under my own GitHub account, and then forked it into the company account.  Being a private repo, you can't delete the original repository without it deleting any forks (and back in the day ;-) you couldn't even delete repos on GitHub).  But, as it turned out, it was pretty easy and didn't take long or involve that much fixing or things that use the code base.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I did ask the GitHub folks for some tips, so these steps factor that info in.  Also, before you do any of this, you should of course heed the typical disclaimers, make backups, etc. That said, first, rename the account.  You can do this in your Account page on GitHub.  Look at the bottom of your account page for this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="thumbnail"&gt;&lt;a href="http://skitch.com/chrisrbailey/bbret/your-account-github"&gt;&lt;img src="http://img.skitch.com/20090114-ek558xhqq2cfi2ueqa8aj2pprn.preview.jpg" alt="Your Account - GitHub" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family: Lucida Grande, Trebuchet, sans-serif, Helvetica, Arial; font-size: 10px; color: #808080"&gt;Uploaded with &lt;a href="http://plasq.com/"&gt;plasq&lt;/a&gt;'s &lt;a href="http://skitch.com"&gt;Skitch&lt;/a&gt;!&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;You don't even need to re-clone your repo for this.  Once you've done the rename, you can simply edit your local .git/config file to fix up the account name.  Do this anywhere you have cloned the repo - for example on your continuous integration server, deployment scripts, cached copies of code on your staging and deployment servers, &lt;a href="http://github.com/chris/tracker_github_hook/tree/master"&gt;Tracker-GitHub post-receive hook&lt;/a&gt; service, etc.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now on to renaming a private forked repo.  If you just need to rename a repo, you can do that on the Edit page for a repository and then repeat the above steps:&lt;/p&gt;&lt;br /&gt;&lt;div class="thumbnail"&gt;&lt;a href="http://skitch.com/chrisrbailey/bbres/administration-for-chriss-tracker-github-hook-github"&gt;&lt;img src="http://img.skitch.com/20090114-epa7s1ci989ya15rq9bxsd62pg.preview.jpg" alt="Administration for chris's tracker_github_hook - GitHub" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family: Lucida Grande, Trebuchet, sans-serif, Helvetica, Arial; font-size: 10px; color: #808080"&gt;Uploaded with &lt;a href="http://plasq.com/"&gt;plasq&lt;/a&gt;'s &lt;a href="http://skitch.com"&gt;Skitch&lt;/a&gt;!&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;But, if you have forked a private repo, it's slightly more involved, but don't fear!&lt;/p&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;First, make sure you (and anyone else working on the project) have no work in progress, or that you somehow save off that work outside of the repo.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Do a pull from GitHub so you have the most up to date codebase.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;On GitHub, delete the original repository (not your forked copy, but from the location you forked it from).  This will cascade and delete your forked copy as well.  You'll find this right below where you can rename it on the repo's Edit page:&lt;br /&gt;&lt;div class="thumbnail"&gt;&lt;a href="http://skitch.com/chrisrbailey/bbreh/administration-for-chriss-tracker-github-hook-github"&gt;&lt;img src="http://img.skitch.com/20090114-r3yg447bhwj4nfmwu7sf8n9ydx.preview.jpg" alt="Administration for chris's tracker_github_hook - GitHub" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family: Lucida Grande, Trebuchet, sans-serif, Helvetica, Arial; font-size: 10px; color: #808080"&gt;Uploaded with &lt;a href="http://plasq.com/"&gt;plasq&lt;/a&gt;'s &lt;a href="http://skitch.com"&gt;Skitch&lt;/a&gt;!&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Optionally rename the directory, on your local machine, of the codebase/repo.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Now create a new repository, with your new choice of name, on GitHub.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Then, follow the instructions to import an existing repository.  In doing so, on your local machine, go into your codebase, and use that.  This will preserve the full Git history and everything from the repository, pushing it up to GitHub just as it was before, but under the new name and rooted at the [new] account.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Fix up all things that use the GitHub account, as mentioned above, like CI servers, deployment scripts, and so on.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;That's it, you're done.  Pretty straight forward and shouldn't take much time.  Thanks again to GitHub for making life so much better in source control land!&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-8444962367625098482?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/8444962367625098482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=8444962367625098482' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8444962367625098482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8444962367625098482'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2009/01/renaming-github-account-and-forked.html' title='Renaming a GitHub Account and Forked Repository'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-2546296668348281508</id><published>2009-01-05T22:20:00.001-08:00</published><updated>2009-01-05T23:53:00.462-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='Espresso'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='ContinuousIntegration'/><category scheme='http://www.blogger.com/atom/ns#' term='Gmail'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='RSpactor'/><category scheme='http://www.blogger.com/atom/ns#' term='CruiseControl'/><category scheme='http://www.blogger.com/atom/ns#' term='Nuvo'/><category scheme='http://www.blogger.com/atom/ns#' term='Pivotal Tracker'/><category scheme='http://www.blogger.com/atom/ns#' term='laptop'/><category scheme='http://www.blogger.com/atom/ns#' term='DealBase'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='TextMate'/><category scheme='http://www.blogger.com/atom/ns#' term='environment'/><category scheme='http://www.blogger.com/atom/ns#' term='Office'/><title type='text'>My Setup and Software</title><content type='html'>&lt;p&gt;I too read &lt;a href="http://al3x.net/2009/01/02/waferbaby-interview.html"&gt;Al3x's interview&lt;/a&gt; the other day, and like &lt;a href="http://railstips.org/2009/1/5/my-setup-and-software"&gt;John Nunemaker&lt;/a&gt;, figured I'd share my setup, as I enjoy reading what others use and often can pick up a few interesting tools or tidbits.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Unlike Mr. Nunemaker, my desk is too messy, IMHO, to photograph right now :)  However, many similarities aside from that. On with it...&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I use a 17" MacBook Pro with 4GB RAM as my only machine these days.  Like Alex and John, I really like having just a single machine, and I no longer work for a corporation where I'd worry about that.  &lt;a href="http://www.dealbase.com"&gt;DealBase&lt;/a&gt; is cool and wouldn't try to make some wacko claim to some work not relevant (and we've explicitly discussed my use of a single machine, etc.).  I have my MBP open on a laptop arm from &lt;a href="http://www.ergotron.com/"&gt;Ergotron&lt;/a&gt;, and then my primary monitor is a &lt;a href="http://accessories.us.dell.com/sna/products/Monitors/productdetail.aspx?c=us&amp;l=en&amp;cs=19&amp;sku=222-7175"&gt;30" Dell&lt;/a&gt;.  Really love the big monitor.  I do my main work o the 30", and then the laptop screen has &lt;a href="http://www.tweetdeck.com/"&gt;TweetDeck&lt;/a&gt;, iChat, &lt;a href="http://culturedcode.com/things/"&gt;Things&lt;/a&gt;, some &lt;a href="http://fluidapp.com/"&gt;Fluid&lt;/a&gt; apps, and other things that I tend to more glance at, and aren't primary work items.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Further, I use a wireless Apple keyboard, and like John, I just love this thing.  I can't tell you how long I'd been looking for a keyboard that was just a keyboard (but with arrow keys).  I hate normal keyboards that take up so much extra space on the right side (my mouse side) with stuff I rarely use - which only exacerbates problems with having my arm/elbow canitlevered further out to use the mouse, sometimes causing arm strain after long days of coding.  I use &lt;a href="http://www.logitech.com/index.cfm/mice_pointers/mice/devices/130&amp;cl=US,EN"&gt;Logitech MX Revolution cordless mouse&lt;/a&gt;, which I like quite a lot.&lt;/p&gt;  &lt;br /&gt;&lt;br /&gt;&lt;p&gt;Transitioning to music...  I use &lt;a href="http://www.jbl.com/home/products/product_detail.aspx?prod=creaTUREIIWHT"&gt;JBL Creature speakers&lt;/a&gt;, and listen to a variety of things, or nothing.  Pandora, via a Fluid app, iTunes (my own playlists, or various Ambient "radio" stations), etc.  Either that, or we have a whole-house &lt;a href="http://www.nuvotechnologies.com/concerto.htm"&gt;NuVo Concerto&lt;/a&gt; audio system, so sometimes I have that on either with XM satellite radio, or to a playlist from the iPod we have hooked into it.  The NuVo setup is nice because it fills my office with sound a bit better (via in-ceiling speakers), but I have more variety via the computer.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;As with Alex and John, I am absolutely in love with my iPhone 3G.  It is even better than expected.  It has essentially replaced my 80GB iPod in the car, typically because it's more up to date, and I like it's UI better; I can remotely work on servers if I have to via &lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=287765826&amp;mt=8"&gt;iSSH&lt;/a&gt;, play games if I'm bored, use &lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=288545208&amp;mt=8"&gt;InstaPaper&lt;/a&gt; to read things I've set for reading later, sync with Address Book and iCal, and of course Twitter, via &lt;a href="http://linktoapp.com/tweetie"&gt;Tweetie&lt;/a&gt;.  So, yes, I use Apple's Address Book and iCal, for great sync, simplicity, etc.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ok, onto dev stuff.  My primary work is on Rails-based web-apps, although I dabble with other things as well.  &lt;a href="http://www.dealbase.com"&gt;DealBase&lt;/a&gt; is my day job, and I'm also involved with &lt;a href="http://www.bringlight.com"&gt;Bring Light&lt;/a&gt;. &lt;/p&gt; &lt;br /&gt;&lt;br /&gt;&lt;p&gt;Yet again, like Alex and John, I spend the bulk of my time in &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt;, &lt;a href="http://iterm.sourceforge.net/"&gt;iTerm&lt;/a&gt; (a better Terminal, IMHO), and Safari.  And actually, I do my development testing in &lt;a href="http://nightly.webkit.org/"&gt;nightly builds of WebKit/Safari&lt;/a&gt;, and all my other browsing in standard Safari.  I do pull up Firefox for testing, and to use &lt;a href="http://developer.yahoo.com/yslow/"&gt;YSlow&lt;/a&gt; and sometimes Firebug (although I've been finding the dev tools in WebKit nightlies work well).  I've used Emacs - did so for about a year when working with Linux as my desktop.  I ditched it back then in favor of Visual SlickEdit, but these days TextMate just rules.  I don't get the Emacs passion - why do you want to press two keys for everything, especially the most common things?  Yes, I know, you can setup different bindings, etc., but come on the most basic things like saving, opening, copy, paste, etc. should be "single" key (and by single I mean some meta+key) strokes by default.  I do fire up vi all the time at the command line on remote servers, and even occasionally on my MBP for some real quick edit.  Also, I spend the bulk of my day in my text editor, so yes, appearance matters, and TextMate kills others.  I've also used a lot of IDE's in the past, from IDEA, to Eclipse, to Visual Studio.  Visual Studio is actually quite good if you have to suffer in that world, but I find Eclipse just plain crappy.  IDEA was great for Java, and their Ruby setup will be something to keep an eye on, but generally, the setup I have now works well.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I have all my code for nearly everything I do (e.g. both private and open source/public) on &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt;, and truly love it.  Git has been a huge win, and gives me the best of, as well as improving SVN and Perforce.  I'm using &lt;a href="http://gitx.frim.nl/"&gt;GitX&lt;/a&gt; for most of my commits and history browsing these days.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I use &lt;a href="http://github.com/rubyphunk/rspactor/tree/master"&gt;RSpactor&lt;/a&gt; for continuously running our RSpec suite, and we also use RSpec stories (but haven't converted to Cucumber yet).  I recently added &lt;a href="http://codeintensity.blogspot.com/2008/12/speech-talking-results-for-rspactor.html"&gt;speech output to RSpactor&lt;/a&gt;, and that is my preferred notification instead of Growl.  We use &lt;a href="http://www.pivotaltracker.com/"&gt;Pivotal Tracker&lt;/a&gt; for tasks/stories/features as well as bug tracking.  We used to use Lighthouse, but having it all in one place was nicer, and Tracker wins big time in my opinion.  If you want &lt;a href="http://github.com/chris/tracker_github_hook/tree/master"&gt;GitHub post-receive hook for Tracker&lt;/a&gt;, I recently whipped that up, and its been a real nice addition.  We too use &lt;a href="http://hoptoadapp.com/welcome"&gt;Hoptoad&lt;/a&gt; for exception notification, and really like it.  Also, New Relic is in use at DealBase.  I also like viewing Google Analytics with &lt;a href="http://www.aboutnico.be"&gt;Analytics Reporting Suite&lt;/a&gt;, a slick AIR app.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I really like &lt;a href="http://www.navicat.com/"&gt;Navicat&lt;/a&gt; as a GUI for database stuff.  It's proprietary/pay software, but honestly, it's worth it to me.  I can do all this stuff command line fine, but the GUI simply makes it a heck of a lot faster to view the results, quickly re-sort on a column, mess around with queries, etc.  Also, it has great SSH support, so I can tunnel into all my server's DB's with ease.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I have &lt;a href="http://github.com/benburkert/cruisecontrolrb/tree/master"&gt;CruiseControl.rb&lt;/a&gt; setups for all my Rails apps, and make use of &lt;a href="http://ccmenu.sourceforge.net/"&gt;CCMenu&lt;/a&gt; for a nice little status menu item showing me what's going on with those.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I pretty much can't live without &lt;a href="http://www.obdev.at/products/launchbar/beta.html"&gt;LaunchBar&lt;/a&gt;.  Same goes for &lt;a href="http://agilewebsolutions.com/products/1Password"&gt;1Password&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Skitch is quite handy for showing sharing and annotating screen shots, and we use Google Docs and Gmail.  Speaking of email, I am a huge fan of &lt;a href="http://mailplaneapp.com/"&gt;Mailplane&lt;/a&gt;, which is a Mac app for Gmail.  Integration is superb, and I can quickly switch around my 15 or so Gmail accounts with ease.  I find it superior to a Fluid app for Gmail, since the integration is better and it handles multiple accounts.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I host most of my own web apps on &lt;a href="http://www.slicehost.com/"&gt;Slicehost&lt;/a&gt;, and DealBase is at &lt;a href="http://www.engineyard.com/"&gt;EngineYard&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I also use Backpack some, although not nearly as much as I used to, and access it about 99% of the time via &lt;a href="http://infinitenil.com/packrat/"&gt;Packrat&lt;/a&gt;.  &lt;a href="http://www.red-sweater.com/marsedit/"&gt;MarsEdit&lt;/a&gt; is my blog authoring tool of choice. &lt;a href="http://www.newsgator.com/INDIVIDUALS/NETNEWSWIRE/"&gt;NetNewsWire&lt;/a&gt; is my RSS reader.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;All of my photography and photo processing, etc. are done in Adobe Lightroom.  I use the &lt;a href="http://regex.info/blog/lightroom-goodies/flickr"&gt;Flickr plugin&lt;/a&gt; for it as well.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Various other bits:&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;TextPander&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.alwintroost.nl/?id=52"&gt;WeatherDock&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://codesorcery.net/pukka"&gt;Pukka&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Flickr&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Del.icio.us&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://iconfactory.com/software/xscope"&gt;xScope&lt;/a&gt; - a great screen ruler app&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Photoshop CS3 (look for my name in the about box too :)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;JungleDisk - I do some backups with this&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.shirt-pocket.com/SuperDuper/SuperDuperDescription.html"&gt;SuperDuper!&lt;/a&gt;  Still my favorite backup, although I use TimeMachine too&lt;/li&gt;&lt;br /&gt;&lt;li&gt;CSS Edit and XyleScope sometimes&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Last.fm - is running all the time, but I really don't actually make use of it, kinda silly.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Acrobat Pro and Reader&lt;/li&gt;&lt;br /&gt;&lt;li&gt;XCode (or TextMate) if I'm working on an Objective-C/Cocoa app.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;iStat menus&lt;/li&gt;&lt;br /&gt;&lt;li&gt;YouControl Tunes&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;p.s.  One other bit I can't live without but really isn't computing hardware/software, is my espresso setup.  I use an &lt;a href="http://www.wholelattelove.com/Expobar/brewtus.cfm"&gt;Expobar Brewtus II&lt;/a&gt; machine, &lt;a href="http://www.chriscoffee.com/products/home/grinders/mc4"&gt;Macap MC4 stepless doserless grinder&lt;/a&gt; and a variety of cups (mostly &lt;a href="http://www.espressoparts.com/product/021_BLACK/Demitasse_Espresso_Cup_Saucer_Set_6_Black__Nuova_Point_Italian_Tulip_Shaped.html"&gt;Nuova Pointe&lt;/a&gt; and Illy).  I use only totally fresh beans from a variety of places (favorites include &lt;a href="http://bluebottlecoffee.net/"&gt;Blue Bottle&lt;/a&gt;, &lt;a href="http://www.eccocaffe.com"&gt;Ecco Caffe&lt;/a&gt;, &lt;a href="http://www.ptscoffee.com/"&gt;PT's&lt;/a&gt;, &lt;a href="http://www.49thparallelroasters.com/"&gt;49th Parallel&lt;/a&gt; (unfortunately not often, since shipping from Canada makes it a bit cost prohibitive), etc.).  Coffelab tamper and Bumper stand and knock box.  &lt;a href="http://flickr.com/photos/chrisrbailey/sets/72157601979329896/"&gt;My espresso bar&lt;/a&gt; is kept clean (unlike my desk).  The pictures are a bit older, so don't show bottomless portafilter in use these days.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Whew, that's more than plenty.  What's your setup?&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-2546296668348281508?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/2546296668348281508/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=2546296668348281508' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2546296668348281508'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2546296668348281508'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2009/01/my-setup-and-software.html' title='My Setup and Software'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-6494347783731364301</id><published>2008-12-30T09:28:00.001-08:00</published><updated>2008-12-30T17:05:23.793-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RSpactor'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='RSpec'/><category scheme='http://www.blogger.com/atom/ns#' term='ContinuousIntegration'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyCocoa'/><title type='text'>Speech / Talking Results for RSpactor</title><content type='html'>After discovering that autospec was taking up a lot of CPU while it was "idle", I looked for alternatives.  I found &lt;a href="http://github.com/rubyphunk/rspactor/tree"&gt;RSpactor&lt;/a&gt;, which doesn't take as much CPU, and is better since it's a dedicated window with nice GUI results and so.  My only gripe was that I'd gotten used to the &lt;a href="http://codeintensity.blogspot.com/2008/06/have-autotest-speak-to-you.html"&gt;spoken results output I'd rigged up for Autospec&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;I really prefer the spoken results because it is not visually distracting, and doesn't require me to be paying attention to the area of the screen where they pop up (I use a 30" monitor, plus the 17" laptop monitor, so I'm not always looking at the right spot for the Growl notices, and I don't like the monitor-wide growls).  Lucky for me, RSpactor is open source and is up on GitHub.  &lt;br /&gt;&lt;br /&gt;I thought it was an Objective-C Cocoa app, but as it turns out it's a RubyCocoa app.  I'd built RubyCocoa apps before, so was familiar with that, plus of course know Ruby.  It wouldn't have mattered either way (I'm fine working in ObjC as well), but this did make things a slight bit faster.&lt;br /&gt;&lt;br /&gt;Anyway, did a quick bit of work and got a new preferences panel for Speech added, and then rigged that up to test results, so that I now have my desired spoken results.  A slight improvement comes along in that it (optionally) speaks the number of passing/failing/pending tests - just insert a question mark in the string/phrase you want spoken for each and it'll say the number at that spot.  &lt;br /&gt;&lt;br /&gt;&lt;del&gt;I've sent a pull request to RubyPhunk, but no guarantees it will get added to the main line.  In the mean time, if you're interested, grab it from &lt;a href="http://github.com/chris/rspactor/tree/master"&gt;my RSpactor fork on GitHub&lt;/a&gt;.&lt;/del&gt; &lt;em&gt;Update: RubyPhunk integrated my changes into the main RSpactor code.&lt;/em&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-6494347783731364301?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/6494347783731364301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=6494347783731364301' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6494347783731364301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6494347783731364301'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/12/speech-talking-results-for-rspactor.html' title='Speech / Talking Results for RSpactor'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-8098495690006560381</id><published>2008-12-29T11:24:00.001-08:00</published><updated>2008-12-29T11:24:15.429-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DealBase'/><title type='text'>DealRank™, Similar and Nearby Hotels and Deals, and "Interesting" Deals</title><content type='html'>Over the last couple weeks, we've built some cool new features on DealBase.com.  Three in particular...&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Interesting Deals Pages&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;This is fairly simple, but one of my favorites.  There is a list of these pages on the home page in the right hand column, under "Interesting Deals".  You can find the cheapest deals, the best deals at 5 star hotels, and so on.  But, my favorite to check out is the &lt;a href="http://www.dealbase.com/list/expensive-hotel-packages"&gt;Most Expensive Deals&lt;/a&gt; page.  This is where we list the most expensive hotel packages, and you can get a glimpse of what the uber-rich might plunk down for.  Deals currently as as much as $110,000/night, yes per night.  But go take a look and check out what those deals include.  Things like private jet for transportation, $40,000 in jewelry, and so on.  Oh, how about it includes a trip to Russia, and you know, to make it extra cute, a "Presidential Puppy"!  Crazy.&lt;br /&gt;&lt;br /&gt;This page is just a lot of fun to explore and see what some of the hotel's come up with.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;DealRank™&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;DealRank™ is our new way of ranking deals to show you the best value.  This is an algorithmic/mathematical determination based on various criteria for deals.  It factors in the nightly rate, percentage savings, and various other aspects.  We expect this to be one of the best ways to sort deals and help you evaluate what is truly a great deal.  Each person looking at hotels has different reasons and criteria for evaluating deals.  Some want the absolutely best price, some want the best overall value, some are looking to get the biggest savings, or the most extras thrown in, and so on.  DealRank™ should help provide a more holistic view on this.  We've done a lot of testing and tweaking here, and will continue to do so as the site evolves, but I am pretty darn happy with the results so far.  We still have many other ways to sort deals (see the sort menu in the upper right of any deal listing page), but this is our new default.&lt;br /&gt;&lt;br /&gt;Check this out on say the &lt;a href="http://www.dealbase.com/New-York-City-hotel-deals-discounts-47"&gt;New York City hotel deals&lt;/a&gt; page, where previously the most economical deals didn't always rise to the top (percentage savings wise, NYC tends to have the best deals at more expensive hotels).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Similar and Nearby Hotels and Deals&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Another quite useful feature is the list of similar and nearby hotels or deals (depends on the what kind of page you're on) listing at the bottom of some pages.  This factors in various criteria, but one thing for sure is that all of the listed hotels/deals are always within a 50 mile radius.  I personally used this when looking for deals on a trip I took the other weekend.  &lt;br /&gt;&lt;br /&gt;An example is similar and nearby hotels on, one of my favorites, the &lt;a href="http://www.dealbase.com/Seattle/W-Seattle-Hotel-deals-805"&gt;W hotel in Seattle&lt;/a&gt;.  Amazon put me up in this hotel.  If you've never stayed at a W, they're pretty cool.  While working for Adobe for many years, I stayed at the &lt;a href="http://www.dealbase.com/Seattle/Fairmont-Olympic-Hotel-Seattle-deals-802"&gt;Fairmont Seattle&lt;/a&gt; a ton, and you'll see that listed as the second hotel in the list of nearby hotels.  But, the W is more edgy, they tend to have cool bars, upscale, swank rooms, etc.  Seattle is a favorite place of mine to travel to.&lt;br /&gt;&lt;br /&gt;I'm working on a particularly cool feature right now, that I can't wait to get out there.  Will take a bit longer as we want to get the UI right and make it of utmost use, but I think it will be something of great value to everyone.  Stay tuned.  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-8098495690006560381?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/8098495690006560381/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=8098495690006560381' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8098495690006560381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8098495690006560381'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/12/dealrank-similar-and-nearby-hotels-and.html' title='DealRank™, Similar and Nearby Hotels and Deals, and &amp;quot;Interesting&amp;quot; Deals'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-8858425638496362646</id><published>2008-12-11T16:43:00.001-08:00</published><updated>2008-12-11T16:43:17.048-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='ContinuousIntegration'/><title type='text'>Browser Testing Services (BrowserCam, CrossBrowserTesting, etc.) - What I Really Want</title><content type='html'>When testing web apps for a general/wide-ranging audience, one must test across a slew of different browsers and operating systems (and different versions of each).  This is a real pain, even if you have an army of testers at hand (which most of us don't).  I employ various tools to help me with this (&lt;a href="http://crossbrowsertesting.com/"&gt;CrossBrowserTesting.com&lt;/a&gt;, &lt;a href="http://www.browsercam.com"&gt;BrowserCam&lt;/a&gt;, VM Ware with different VM setups, etc.).  But, the reality is that I don't feel like these really stack up to what I need.  More specifically, BrowserCam, and its competitors do not.  CrossBrowserTesting is actually pretty awesome and does what it advertises quite nicely, it's a favorite tool right now.&lt;br /&gt;&lt;br /&gt;What I'm after is a way to see what a survey of pages on my site look like on different browsers and OS's.  This is by no means a definitive test of a site, but more of a quick visual inspection of appearance, without having to fire up a dozen different pages across maybe 30 different browsers/OS configurations.  We use an automated test suite to test the bulk of other things, but appearance can't be tested that way.&lt;br /&gt;&lt;br /&gt;BrowserCam helps, but honestly I find it quite lacking as a tool in this arena.  Note, I'm picking on BrowserCam, as that's the one I use, but the others (&lt;a href="http://browsershots.org/"&gt;BrowserShots&lt;/a&gt;, &lt;a href="http://litmusapp.com/"&gt;Litmus&lt;/a&gt;, etc.) all seem to suffer some or all of these problems, and further, they don't seem to have projects or ways to establish a standard suite of tests.  Getting on with it, all of this really boils down to two primary things:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Ability to edit the settings on a project's images.  As far as I can tell, once you select the URL's, image size, browsers, etc. for a project, there is no way to change any of that!  What if I just want to change the window size?  Can't, I have to create a new project (or add new images to the existing one, replicating all my previous work.  This seems like an obvious hole.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Automation.  I want to be able to automate regeneration of the project.  I'd like something like a simple URL/HTTP API to do this, so that I can, from a command line, use curl or similar to issue a single HTTP request that will regenerate a project's images.  Thus, the API would need to use HTTP authentication or similar, and specify which project to regenerate.  With this, I would be able to automate requesting a regeneration of the project as part of/after deploying my application.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;I'm currently looking into creating my own script to drive the automation, but it's looking non-trivial due to the way BrowserCam's pages work: everything winds up on the same URL, actions/links are all JavaScript that post forms, with a lot of params and a bunch of params that will take some time to ascertain if a) they're required, and b) all the info in the parameter is needed, etc.  If someone's already done this, let me know!  Also, suggestions for tools to drive the automation?  I've used the Ruby Mechanize library in the past for things like this, and this may work if I can determine the params, etc., and if Mechanize can even drive the JavaScript links (not sure it can - anyone?).  I can't use something like Selenium or Windmill because this needs to work from a script/command line, and not rely on a browser.&lt;br /&gt;&lt;br /&gt;Finally, if anyone knows of a service similar to BrowserCam that solves these, even if it supports a few less browsers, do let me know.  At very minimum it would need to handle Internet Explorer and Firefox, preferably also Safari, and cover Windows XP, Vista, MacOS X 10.5, and one popular Linux flavor.  Nice to haves would include Opera and various others.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-8858425638496362646?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/8858425638496362646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=8858425638496362646' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8858425638496362646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8858425638496362646'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/12/browser-testing-services-browsercam.html' title='Browser Testing Services (BrowserCam, CrossBrowserTesting, etc.) - What I Really Want'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4228143552659948577</id><published>2008-12-02T16:23:00.001-08:00</published><updated>2008-12-02T16:23:02.743-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pivotal Tracker'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Sinatra'/><title type='text'>GitHub Post-Receive Hook for Pivotal Tracker</title><content type='html'>Over the holiday, I whipped up a quick GitHub Post-Receive Hook for use with &lt;a href="http://www.pivotaltracker.com"&gt;Pivotal Tracker&lt;/a&gt;.  This is just a small web service, implemented in &lt;a href="http://sinatra.rubyforge.org/"&gt;Sinatra&lt;/a&gt;.  It was my first time using Sinatra, so any suggestions on improvements are of course welcome (as are they in general, this is open source).  I've put the code up on GitHub in the somewhat painfully named &lt;a href="http://github.com/chris/tracker_github_hook/tree/master"&gt;tracker_github_hook&lt;/a&gt; repo.&lt;br /&gt;&lt;br /&gt;The service supports multiple GitHub repos and Tracker projects, so you can run a single service that integrates multiple projects.  The service will figure out which commits go to which projects based on a config file on the server that associates a GitHub repo URL (make sure to use the http version of the URL, not https), to a Tracker project ID.  For example:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;tracker_github_hook:&lt;br /&gt;  github_url: http://github.com/chris/tracker_github_hook&lt;br /&gt;  tracker_api_token: a1234b56789c0defa12b3c4def56a78b&lt;br /&gt;  tracker_project_id: 123&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You will need to take care of running the service within your particular server setup.  I'm personally running it via Thin/Rack, behind Nginx.  I have it setup on the same server that runs our continuous integration system, so these two are differentiated by subdomain.  &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;It should be noted, I will not claim this thing is secure.  You run it at your own risk, etc. &lt;/strong&gt; &lt;br /&gt;&lt;br /&gt;Aside from getting the service running on your own server, you'll need to add the URL to it as a GitHub post-receive hook for each project you want to integrate.  To do that, go to the Admin tab of your GitHub repo, and then the Services tab.  At the top you'll see where you put the URL in.  The URL is just the root of the service.  Also see &lt;a href="http://github.com/guides/post-receive-hooks"&gt;GitHub's docs on post-receive hooks&lt;/a&gt; as it illustrates just how I built this, how to set it up, etc.&lt;br /&gt;&lt;br /&gt;Hopefully others find this useful.  Or, what I really hope is that the Pivotal guys get with the GitHub guys and add a standard integration service, where it's automatically configured on the Tracker side, and you just need to turn it on on the GitHub side much like the other service integrations.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4228143552659948577?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4228143552659948577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4228143552659948577' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4228143552659948577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4228143552659948577'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/12/github-post-receive-hook-for-pivotal.html' title='GitHub Post-Receive Hook for Pivotal Tracker'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-5887554398120563281</id><published>2008-11-19T15:22:00.001-08:00</published><updated>2008-11-19T15:42:22.417-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Using View Helpers and Controller Actions from Rails' script/runner</title><content type='html'>Recently I coded up a controller and view that produces a large data file.  It was done this way because it needs to generate the proper URL's and take into account a fair bit of stuff at the view level in our application (like pagination, and the custom URL's we have, so extensive use of our URL helpers and other things at this level).  The action takes a long time to run (about 3 minutes), so of course I page cache it.  However, 3 minutes breaks the web server and/or Mongrel timeouts in our environment, so won't get served up in production and staging environments.&lt;br /&gt;&lt;br /&gt;The solution, and I'd love to hear other ways, as I certainly won't claim this is the best way, was to create a small script/runner script that simply executed this route within our app.  However, script/runner doesn't normally give you controller and view layer access, plus it doesn't have the context of a web request, so it won't know say the host it's being run against and so on.  However, one can leverage an Integration::Session and manually set the host to get that.  Thus, the script becomes as simple as:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;#!script/runner&lt;br /&gt;&lt;br /&gt;require 'action_controller/integration'&lt;br /&gt; &lt;br /&gt;session = ActionController::Integration::Session.new&lt;br /&gt;session.host = 'www.yourdomain.com'&lt;br /&gt; &lt;br /&gt;session.get_via_redirect '/controller/action'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Note, I'm using get_via_redirect here because the particular action I call does a redirect after it expires the cached page of the action it's redirecting to.  If you don't have a redirect going on, then you can just call &lt;code&gt;get&lt;/code&gt; instead.  This does not output anything of course, but for us, just caches the resulting page, which is exactly what we want.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-5887554398120563281?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/5887554398120563281/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=5887554398120563281' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5887554398120563281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5887554398120563281'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/11/using-view-helpers-and-controller.html' title='Using View Helpers and Controller Actions from Rails&amp;#39; script/runner'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-8612021867456573054</id><published>2008-11-18T23:10:00.001-08:00</published><updated>2008-11-18T23:10:16.955-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='travel'/><category scheme='http://www.blogger.com/atom/ns#' term='DealBase'/><category scheme='http://www.blogger.com/atom/ns#' term='presentation'/><title type='text'>Video of DealBase CEO's Demo/Presentation at PhoCusWright Show</title><content type='html'>Sam Shank, the CEO of &lt;a href="http://www.dealbase.com"&gt;DealBase&lt;/a&gt;, the &lt;a href="http://www.dealbase.com"&gt;hotel deals&lt;/a&gt; site I work on, unveiled the site officially at PhoCusWright 2008.  The video of his presentation (as well as all the others) is now available.  Go &lt;a href="http://www.phocuswright.com/the_phocuswright_conference_2008_travel_innovation_summit_demonstrators"&gt;here&lt;/a&gt;, and then if you hover your mouse over the video you'll see a slide/icon for each company that presented along the top - scroll to the right until you find DealBase, and then click it to watch.  Presentation is about 5 minutes, and is nearly all demo and discussion of our advantages, strengths, how the site works, and business model aspects, etc.&lt;br /&gt;&lt;br /&gt;I think the demo went great, and I've continued to hear tons of praise and useful feedback.  The demo was completely live, no smoke-and-mirrors; Sam was not kidding when he told the audience to go check out the deal he just posted during the demo.&lt;br /&gt;&lt;br /&gt;We somehow (I'm truly surprised, but of course I am a bit biased) didn't get picked as a top 6 for the show, but for example, others disagreed as well.  Tim Hughes, author of &lt;a href="http://tims-boot.blogspot.com/"&gt;The Business of Online Travel blog&lt;/a&gt;, listed DealBase.com in his &lt;a href="http://tims-boot.blogspot.com/2008/11/phocuswright-travel-innovation-summit.html"&gt;Top Six pick of 2008 PhoCusWright Travel Innovation Summit finalists&lt;/a&gt;.  Regardless, interest has been outstanding, and we're really excited.  We're still cranking away with new features, and various other improvements.  It's a lot of fun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-8612021867456573054?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/8612021867456573054/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=8612021867456573054' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8612021867456573054'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8612021867456573054'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/11/video-of-dealbase-ceo-demopresentation.html' title='Video of DealBase CEO&amp;#39;s Demo/Presentation at PhoCusWright Show'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4877135608416878568</id><published>2008-11-14T12:24:00.001-08:00</published><updated>2008-11-14T12:26:10.693-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DealBase'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>DealBase - Check out the new features</title><content type='html'>Since doing our initial public access to the &lt;a href="http://www.dealbase.com"&gt;DealBase.com&lt;/a&gt; site, you know, the web site that has the most &lt;a href="http://www.dealbase.com"&gt;hotel deals&lt;/a&gt; on the web (50x more than anyone else), we've been working hard on improving the experience for users.  Today we rolled out the latest major revision to the site, which includes some pretty cool stuff.  First, let me list these things out, and then I'll cover a few interesting technical bits that occurred along the way.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;New home page&lt;/strong&gt;: yes, a brand new, much nicer home page.  This really helps tell you what's great about the site.  It also has a new search box that I call the "omniscient search" - a single search field that auto-completes on our deal locations and hotels, which is much nicer than the separate search boxes we had before.  This same search box is also used everywhere else on the site.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Deal filtering&lt;/strong&gt;: this was a big one.  Seems fairly simple on first blush, but lots of interesting stuff going on in the background.  You can now filter deals on any deal listing page, by various criteria.  You can combine filters too.  So, for example, you can narrow down the deal listing by dates, prices, and hotel ratings, allowing you to, for example, look for 4 star hotel deals valid from April through August of 2009, in a certain price range, for a given city.  Very handy.  Here, take a look at the &lt;a href="http://www.dealbase.com/Hawaii-hotel-deals-discounts-28"&gt;deals for Hawaii&lt;/a&gt; page as an example.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Deal sorting&lt;/strong&gt;: in addition to the filtering, you can now sort the deal listing a myriad of ways, from most percent savings or most dollar savings to high or low rates, or most recently posted, etc.  Combining this with filters allows you to really narrow down what deals are best for you.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Various UI/visual improvements&lt;/strong&gt;.  Meagan, our talented designer, has done a lot of work here.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Speed improvements&lt;/strong&gt;.  Various database queries and other operations for the site have been sped up, sometimes in small amounts, sometimes in extremely drastic ways.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;More deals&lt;/strong&gt;: we should probably have about 10,000 deals on the site by the time you read this.  This is very exciting for us, and shows how serious we are.  These are all very real deals, no link bait, no BS.  These are true deals, checked by our team of editors.  This gives us about 50x more deals than any other hotel deals site.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Comments! &lt;/strong&gt; You can now comment on deals.  No login required (just like the rest of the site).  Comments do get reviewed, and we'll be watching for spam and so forth, but this is a great way to tell other people about a good deal or a hotel you like, etc.  Comment box is at the bottom of a deal's page.  For example, check out this wild personal fireworks show &lt;a href="http://www.dealbase.com/New-York-City/Ritz-Carlton-Battery-Park-hotel-deals/Cant-TryWith-Personal-Fireworks-1613"&gt;deal at the Ritz-Carlton in New York&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Chrome browser support&lt;/strong&gt;.  DealBase works and looks great in Chrome.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;And now, since this is a geek blog anyway, a few technical bits...&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;We're running Rails 2.1.2, which is the latest release of Rails as of this writing.  We try to stay up to date regardless, but this was a key release, as it fixed some tricky ActiveRecord named_scope issues when using SQL JOINs.  Our filtering and other work requires various JOINs and the fixes here prevented us from having to explicitly hand craft a bunch of queries.  Thanks Rails team.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;My current favorite gem is Ryan Bates' &lt;a href="http://github.com/ryanb/scope-builder/tree/master"&gt;scope-builder&lt;/a&gt;.  This is just so nice for building up big, conditionally chainged named_scopes.  As you can imagine this is heavily used in building up combined filtering and sorting of deals.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;More jQuery goodness.  I continue to love jQuery, and use it extensively.  It is used heavily in the filtering features, pulling in some nice slider UI elements, and also using it for the "updating" status and dimming effects when the AJAX filtering operations are running.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;One issue we ran into with Chrome was using the :cache feature of Rails' javascript_include_tag.  If we used this to combine and create a cache file of a bunch of separate JavaScript files, Chrome failed to properly load/parse the resulting JavaScript file.  This broke pretty much everything JavaScript wise in Chrome, but the simple fix was to not use :cache to achieve this.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;As a helpful, and economical testing tool, we've been using &lt;a href="http://www.crossbrowsertesting.com/"&gt;CrossBrowserTesting.com&lt;/a&gt; to give us VM's of a slew of different OS and browser combinations.  I tend to run VMWare Fusion and do a lot that way, but it's also a pain to keep up a bunch of different VM images, or have to fire that up for a quick test, etc.  We're also using &lt;a href="http://www.browsercam.com"&gt;BrowserCam&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Finally, another shout-out to the &lt;a href="http://hoptoadapp.com"&gt;Hoptoad&lt;/a&gt; service/folks.  This continues to be an outstanding service for us.  It works really really well, and it's free, so to me it is the winner amongst the competitors.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;We've done a fair number of modifications to our tagging plugin (acts_as_taggable_on_steroids), although they're all particular to our app, so not sure if any will get contributed back.  Things like enforcing all our rules about tag naming and so on.  The same goes for the will_paginate plugin. But in this case, I'm hoping to contribute these back as soon as I can properly contribute the patches and ensure they'll work in any app.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;I'm sure there's more, but that's what I can think of for the moment.  It's been a busy couple weeks, and I'm really excited about the state of the site these days.  We've been getting some great feedback, and I've had a few friends book deals they've found on the site (one friend saved $800 on a trip!).  If you have feedback, don't hesitate to add a topic or question in our &lt;a href="http://www.dealbase.com/contact"&gt;Get Satisfaction feedback system&lt;/a&gt;.  This tells us what things you'd like to see, or any problems you're finding, etc.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4877135608416878568?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4877135608416878568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4877135608416878568' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4877135608416878568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4877135608416878568'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/11/dealbase-check-out-new-features.html' title='DealBase - Check out the new features'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-8928152734987669782</id><published>2008-11-04T10:14:00.001-08:00</published><updated>2008-11-04T10:14:17.610-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Speed Up and named_scope acts_as_taggable_on_steroids Finds</title><content type='html'>I use the acts_as_taggable_on_steroids plugin for tagging.  I've been happy with it, but recently have been adding a lot of searching, sorting, filtering, etc. functionality to an app, and needed the find by tag functionality to work as a named_scope, so that I can have it within a chain of many named_scope finders.  &lt;br /&gt;&lt;br /&gt;This turned out to be trivially easy to do (without having to copy the SQL and put that into my named_scope).  To add a "tagged_with" named_scope to your model that is already acts_as_taggable, you can just do this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;  named_scope :tagged_with, lambda { |tags| YourModel.find_options_for_find_tagged_with(tags) }&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I've been doing a lot of benchmarking and performance improvements to our SQL as well, and decided to see if this was any different in performance compared to just doing YourModel.find_tagged_with that acts_as_taggable_on_steroids adds.  As it turns out, the named_scope version, which is really identical at the core, is faster, especially if called more than once (per thread/Rails request)!  Here's the benchmarks to prove it:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Single query/1 Iteration:&lt;br /&gt;           user     system      total        real&lt;br /&gt;named_scope       0.040000   0.000000   0.040000 (  0.045085)&lt;br /&gt;find_tagged_with  0.020000   0.010000   0.030000 (  0.108233)&lt;br /&gt;&lt;br /&gt;10 Iterations:&lt;br /&gt;           user     system      total        real&lt;br /&gt;named_scope       0.030000   0.000000   0.030000 (  0.040282)&lt;br /&gt;find_tagged_with  0.420000   0.030000   0.450000 (  2.040245)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I repeated these multiple times and got the same/similar results each time.  So, for a single query, it's only about 2x faster, but if you start issuing this same find multiple times per request then I believe it's the Rails query caching that kicks in with named_scope, but apparently not with the generic find with all the options (I'd love to hear some commentary on this from someone who knows the details).&lt;br /&gt;&lt;br /&gt;Regardless, using a named_scope is nice because now you can more easily chain a tag find together with other named_scope items.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-8928152734987669782?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/8928152734987669782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=8928152734987669782' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8928152734987669782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8928152734987669782'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/11/speed-up-and-namedscope.html' title='Speed Up and named_scope acts_as_taggable_on_steroids Finds'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7240795789318691387</id><published>2008-09-16T15:28:00.001-07:00</published><updated>2009-08-04T14:04:36.070-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='RSpec'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><title type='text'>Mocked by Default, but Unmocking in Some Cases with RSpec</title><content type='html'>Uh, ya, another great blog title, but we'll get over it.  We use geocoding in our app, and that's a relatively costly operation time wise, especially when you may be doing it hundreds or thousands of times when your test suite runs.  I can't stub out the objects that use it in many cases, so I wanted to stub out the actual &lt;code&gt;geocode&lt;/code&gt; call unless I truly needed real geocoding (which is only when I'm testing the actual geocoding itself, and thus is a very small part of the test suite).&lt;br /&gt;&lt;br /&gt;We use RSpec Specs and Stories and I wanted to mock out the geocoding by default, but unmock it in a few places.  I asked about this on the mailing list, Googled and so on, but didn't find a solution that was working.  So here is what I wound up doing...&lt;br /&gt;&lt;br /&gt;In my &lt;code&gt;spec_helper.rb&lt;/code&gt; file, I added:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Spec::Runner.configure do |config|&lt;br /&gt;  config.before(:each) do&lt;br /&gt;      # Setup fake geocoding unless told not to&lt;br /&gt;      unless @do_not_mock_geocoding&lt;br /&gt;        fake_geocode = OpenStruct.new(:lat =&gt; 123.456, :lng =&gt; 123.456, :success =&gt; true)&lt;br /&gt;        GeoKit::Geocoders::MultiGeocoder.stub!(:geocode).and_return(fake_geocode)&lt;br /&gt;      end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What this does is mock the geocoding unless a test has set the &lt;code&gt;@do_not_mock_geocoding&lt;/code&gt; variable to &lt;code&gt;true&lt;/code&gt;.  One caveat, at least from what I've found, is that you need to set that to true in a &lt;code&gt;before(:all)&lt;/code&gt; block in your tests, so that it happens before the &lt;code&gt;before(:each)&lt;/code&gt;.  This is minor, as you can just have something like:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;describe "with real geocoding" do&lt;br /&gt;  before(:all) do&lt;br /&gt;    @do_not_mock_geocoding = true&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  # your tests that want real geocoding&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The impact this has had on our test suite is tremendous.  I had already had some partial mocking of the geocoding in place, but was sweeping the system to put it in because the time it took to run our test suite was out of hand at about 13 minutes!  Now that I've got this in, it runs in 2 minutes!  Geocoding is used in two of our most core objects, which is why it has such a big impact on the test suite.  This is one place mocking has really proved to be a massive value!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7240795789318691387?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7240795789318691387/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7240795789318691387' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7240795789318691387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7240795789318691387'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/09/mocked-by-default-but-unmocking-in-some.html' title='Mocked by Default, but Unmocking in Some Cases with RSpec'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7886211065193150586</id><published>2008-09-13T00:57:00.001-07:00</published><updated>2008-09-13T00:59:30.432-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><title type='text'>Use the Lighthouse API for Mass Ticket Changes</title><content type='html'>&lt;a href="http://lighthouseapp.com/"&gt;Lighthouse&lt;/a&gt; is a nice issue tracker/bug database.  We're using at at &lt;a href="http://www.dealbase.com"&gt;DealBase&lt;/a&gt; and some of my other projects.  However, one thing it doesn't have, is a way to set the state of a bunch of tickets at once, or assign a slew of tickets to a certain user, etc.  I need to do this regularly, as anytime we do a deploy to our staging environment, I need to go mark any bugs that were set to 'fixed' to now have a state of 'deployed', and then assign them to someone else to be verified.  &lt;a href="http://lighthouseapp.com/api"&gt;Lighthouse API&lt;/a&gt; to the rescue...&lt;br /&gt;&lt;br /&gt;You can whip up a quick Ruby script to automate operations like this.  The following is the script (tweaked to protect the innocent) I use to mark all tickets that are set to "fixed" to now be "deployed" and assign them to another user for verification.  Obviously you can change this pretty easily to affect various other changes.  I recommend playing with the Lighthouse API in IRB to see what the attribute names are for Tickets and so on.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/10571.js"/&gt;&lt;br /&gt;&lt;em&gt;It appears Blogger is messing with the GitHub Gist formatting, so click the "&lt;a href="http://gist.github.com/raw/10571/046e25a8ba7b3cb75b86c2aa285924a7b532d9ae"&gt;view raw&lt;/a&gt;" link for a more readable version.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Replace the various values as indicated, and you're off and running.  Note, the Lighthouse API is not a RubyGem or such, so you need to just clone it or download it and then store it somewhere and adjust the require at the top of the script accordingly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7886211065193150586?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7886211065193150586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7886211065193150586' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7886211065193150586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7886211065193150586'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/09/use-lighthouse-api-for-mass-ticket.html' title='Use the Lighthouse API for Mass Ticket Changes'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4141937073671663968</id><published>2008-09-02T10:56:00.001-07:00</published><updated>2008-09-02T10:56:50.195-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DealBase'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='Jobs'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>We're Hiring for a Rails or Similar Developer</title><content type='html'>The startup I work for, &lt;a href="http://www.dealbase.com"&gt;DealBase&lt;/a&gt;, is in need of another developer.  This is pretty exciting for us, and the business is quite exciting as well!  We're looking for someone with Rails experience, as well as MySQL, Git, TDD (BDD is good too), agile development practices, and so on.  You can read all the details in &lt;a href="http://gigs.37signals.com/gigs/4277"&gt;our posting on the 37signals Gig Board&lt;/a&gt;.  Please make sure you respond to the ad, as opposed to sending me email (or asking via a blog comment).  You can mention in your email though that you found it via my blog entry.&lt;br /&gt;&lt;br /&gt;One thing I want to specifically note, you don't have to be a "Rock Star"!  Sure, we want the best people, but I too am sick of this "Rock Star" designation.  I'd like to see someone who's passionate about software development, web apps, technology, TDD, JavaScript, and so on.&lt;br /&gt;&lt;br /&gt;Another thing to note, we're a partially distributed team.  I myself live in Eugene, Oregon, others are in the Bay area, one person Boston.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4141937073671663968?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4141937073671663968/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4141937073671663968' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4141937073671663968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4141937073671663968'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/09/we-hiring-for-rails-or-similar.html' title='We&amp;#39;re Hiring for a Rails or Similar Developer'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-2857027197042012687</id><published>2008-08-29T13:43:00.001-07:00</published><updated>2008-08-29T17:15:07.454-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Slicehost'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><category scheme='http://www.blogger.com/atom/ns#' term='Nginx'/><category scheme='http://www.blogger.com/atom/ns#' term='WordPress'/><title type='text'>WordPress, Nginx, Subdirectories, and Separate Server Proxying</title><content type='html'>Ok, first, apologies for the title of this entry, there wasn't exactly a concise way to title what this is about :)  So, here's a better description of what this entry is about...&lt;br /&gt;&lt;br /&gt;I needed to setup a &lt;a href="http://wordpress.org/"&gt;WordPress&lt;/a&gt; blog for a client, but they needed the blog to be located as a subdirectory of their primary domain name, as opposed to its own domain name or a subdomain.  Furthermore, we use Nginx for all our web servers, and so needed to be able to configure Nginx both on the main domain name serving infrastructure, as well as the machine that would host the blog.  There were some other writeups on the web, but none quite covered this case - basically the complication of proxying to it, as well as WordPress being in a "subdirectory" in terms of the path.  So, here's how I got it working.&lt;br /&gt;&lt;br /&gt;But first, a quick intermission.  This was made possible by the fine support folks at &lt;a href="http://engineyard.com/"&gt;EngineYard&lt;/a&gt;, in particular David S, but others as well.  They provided the solution to the final problem we ran into, as well as a few tips along the way.  Our primary servers and testing/staging systems are hosted at EngineYard, but the WordPress blog is actually on a Slicehost slice, so double thanks to them, as even though part of it involved their systems, part did not.  As so many others have said, EngineYard is really superb, and absolutely worth the price.  Getting on with it...&lt;br /&gt;&lt;br /&gt;I'm going to do this not precisely in the order I did it, but the idea is to cut out my missteps and just give you (and me for future reference) a recipe for this.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Setup the Wordpress Server&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;For me this was an Ubuntu 8/Hardy machine, using MySQL as the DB, and WordPress 2.6.1, with Nginx as the web server.  Presuming you have a base Ubuntu install, you may or may not need all these steps (e.g. you may already have PHP):&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Install PHP CGI, and PHP MySQL components:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo aptitude install php5-cgi php5-mysql&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Install Lighttpd to get the spawn-fcgi program&lt;/strong&gt; that will take care of handling PHP FastCGI requests, but then stop Lighttpd and remove its daemon service:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;sudo aptitude install lighttpd&lt;br /&gt;sudo /etc/init.d/lighttpd stop&lt;br /&gt;sudo rm /etc/init.d/lighttpd&lt;br /&gt;sudo update-rc.d lighttpd remove&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Next, setup the spawn-fcgi program to run as a daemon.  You need to pick a port you'll use, in my case I happened to choose 53987 (at random).  The following daemon script should be placed in &lt;code&gt;/etc/init.d/spawn-fcgi&lt;/code&gt; or a name you like.  Note that this is somewhat specific to Ubuntu, but likely works on similar distros or can be adapted for RedHat-based ones, etc.:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;#! /bin/sh&lt;br /&gt;&lt;br /&gt;### BEGIN INIT INFO&lt;br /&gt;# Provides:          nginx&lt;br /&gt;# Required-Start:    $all&lt;br /&gt;# Required-Stop:     $all&lt;br /&gt;# Default-Start:     2 3 4 5&lt;br /&gt;# Default-Stop:      0 1 6&lt;br /&gt;# Short-Description: starts FastCGI for PHP&lt;br /&gt;# Description:       starts FastCGI for PHP using start-stop-daemon&lt;br /&gt;### END INIT INFO&lt;br /&gt;&lt;br /&gt;PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin&lt;br /&gt;DAEMON=/usr/bin/spawn-fcgi&lt;br /&gt;NAME=spawn-fcgi&lt;br /&gt;DESC=spawn-fcgi&lt;br /&gt;DAEMON_OPTS="-f /usr/bin/php-cgi -a 127.0.0.1 -p 53987"&lt;br /&gt;&lt;br /&gt;test -x $DAEMON || exit 0&lt;br /&gt;&lt;br /&gt;set -e&lt;br /&gt;&lt;br /&gt;case "$1" in&lt;br /&gt;  start)&lt;br /&gt;        echo -n "Starting $DESC: "&lt;br /&gt;        start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \&lt;br /&gt;                --exec $DAEMON -- $DAEMON_OPTS&lt;br /&gt;        echo "$NAME."&lt;br /&gt;        ;;&lt;br /&gt;  stop)&lt;br /&gt;        echo -n "Stopping $DESC: "&lt;br /&gt;        start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \&lt;br /&gt;                --exec $DAEMON&lt;br /&gt;        echo "$NAME."&lt;br /&gt;        ;;&lt;br /&gt;  restart|force-reload)&lt;br /&gt;        echo -n "Restarting $DESC: "&lt;br /&gt;        start-stop-daemon --stop --quiet --pidfile \&lt;br /&gt;                /var/run/$NAME.pid --exec $DAEMON&lt;br /&gt;        sleep 1&lt;br /&gt;        start-stop-daemon --start --quiet --pidfile \&lt;br /&gt;                /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS&lt;br /&gt;        echo "$NAME."&lt;br /&gt;        ;;&lt;br /&gt;  reload)&lt;br /&gt;      echo -n "Reloading $DESC configuration: "&lt;br /&gt;      start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/$NAME.pid \&lt;br /&gt;          --exec $DAEMON&lt;br /&gt;      echo "$NAME."&lt;br /&gt;      ;;&lt;br /&gt;  *)&lt;br /&gt;        N=/etc/init.d/$NAME&lt;br /&gt;        echo "Usage: $N {start|stop|restart|reload|force-reload}" &gt;&amp;2&lt;br /&gt;        exit 1&lt;br /&gt;        ;;&lt;br /&gt;esac&lt;br /&gt;&lt;br /&gt;exit 0&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;You can download/get the above script &lt;a href="http://gist.github.com/7999"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Then make it a daemon by doing:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;cd /etc/init.d&lt;br /&gt;sudo update-rc.d spawn-fcgi defaults&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Now install the WordPress files and setup the database&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://wordpress.org/download/"&gt;Download the latest tarball&lt;/a&gt;, and unpack it where you want it to be.  In my case, this was in /var/www/wordpress/blog.  Note the sort of double directory there.  That is because the subdirectory within the path that the blog is accessible at is "blog", i.e. http://www.example.com/blog.  &lt;strong&gt;The key here is that the directory name that WordPress ultimately lives in, needs to be the same as the subdirectory in the path of the URL.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Follow &lt;a href="http://codex.wordpress.org/Installing_WordPress"&gt;steps 1-5 of the WordPress install guide&lt;/a&gt;, where you setup the database, etc.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Install and Configure Nginx:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo aptitude install nginx&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;My configuration file for Nginx, which lives in &lt;code&gt;/etc/nginx/sites-available/blog&lt;/code&gt;, and is symlinked from &lt;code&gt;/etc/nginx/sites-enabled/blog&lt;/code&gt;, looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;server {&lt;br /&gt;  listen 80;&lt;br /&gt;  server_name blog.example.com;&lt;br /&gt;&lt;br /&gt;  root /var/www/wordpress;&lt;br /&gt;  index  index.php;&lt;br /&gt;&lt;br /&gt;  access_log /var/log/nginx/blog.access.log;&lt;br /&gt;  error_log /var/log/nginx/blog.error.log notice;&lt;br /&gt;&lt;br /&gt;  location / {&lt;br /&gt;    root /var/www/wordpress;&lt;br /&gt;    index index.php;&lt;br /&gt;&lt;br /&gt;    # this serves static files that exist without running other rewrite tests&lt;br /&gt;    if (-f $request_filename) {&lt;br /&gt;      expires 30d;&lt;br /&gt;      break;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    # this sends all non-existing file or directory requests to index.php&lt;br /&gt;    if (!-e $request_filename) {&lt;br /&gt;      rewrite ^(.+)$ /index.php?q=$1 last;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  location ~ .php$ {&lt;br /&gt;    include /etc/nginx/fastcgi_params;&lt;br /&gt;    fastcgi_pass 127.0.0.1:53345;&lt;br /&gt;    fastcgi_index index.php;&lt;br /&gt;&lt;br /&gt;    fastcgi_param SCRIPT_FILENAME /var/www/wordpress$fastcgi_script_name;&lt;br /&gt;&lt;br /&gt;    root /var/www/wordpress;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;You can download this file &lt;a href="http://gist.github.com/8005"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;In the above configuration file, if you didn't locate your WordPress install at &lt;code&gt;/var/www/wordpress/blog&lt;/code&gt;, then you need to edit the various &lt;code&gt;/var/www/wordpress&lt;/code&gt; paths you find.  Also, adjust the port number as needed, and any of the paths to log files, etc.&lt;br /&gt;&lt;br /&gt;To explain this config file, you have an initial location directive that has two parts within it.  The first says that if the request is for a static file, just serve it up and ignore any further rules.  The second says that if it doesn't find a static file, then rewrite it to an &lt;code&gt;index.php&lt;/code&gt; based URL, and continue.  This leads to the second location directive which processes PHP requests, sending them to the fastcgi processor, which is setup via the SCRIPT_FILENAME setting, as well as the common settings in the included fastcgi_params (which is part of a base Nginx install).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;WordPress Install and Testing&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Now we can fire everything up on the WordPress server, get it installed (WordPress wise), and make sure it's working, before moving on to setting up the proxying from the other server that handles the domain.  The below depends some on how you access your WordPress server directly (e.g. via IP or subdomain, etc.).  I was doing it by IP while waiting for the DNS for the blog.example.com part to be working.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Start up the spawn-fcgi, and Nginx daemons&lt;/strong&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;sudo /etc/init.d/spawn-fcgi start&lt;br /&gt;sudo /etc/init.d/nginx start&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Proxy/Domain Server Setup&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;On the server(s) that host your domain, you need to setup the proxying in Nginx to send requests to the /blog path over to your WordPress server.  To do that, I added the following to my Nginx configuration:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;location /blog {&lt;br /&gt;  proxy_set_header X-Real-IP $remote_addr;&lt;br /&gt;  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;&lt;br /&gt;  proxy_set_header Host $http_host;&lt;br /&gt;  proxy_redirect false;&lt;br /&gt;  proxy_pass  http://&lt;IP ADDRESS&gt;;&lt;br /&gt;  }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This file is availble &lt;a href="http://gist.github.com/8027"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Note that you need to insert the IP Address of your WordPress server where indicated (or use the subdomain - I don't have that going yet, as I'm still waiting for my subdomain DNS to percolate through).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;WordPress Installer and Config&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Now surf over to the WordPress installer at:&lt;br /&gt;&lt;br /&gt;http://&lt;em&gt;IP ADDRESS&lt;/em&gt;/blog/wp-admin/install.php&lt;br /&gt;&lt;br /&gt;This should fire up the WordPress installer and off you go.  Now, big caveat here, as this isn't quite how I did it, so I can't say for certain that this install phase will work properly.  To diverge for a minute, incase this happens to you, I initially had WordPress installed directly in &lt;code&gt;/var/www/wordpress&lt;/code&gt;.  I then hit http://IP ADDRESS/wp-admin/install.php, and did the install.  Once installed, I went into the "Settings" tab of WordPress's admin area, and changed the site URL and home page URL's to be &lt;code&gt;http://www.example.com/blog&lt;/code&gt;.  And then, I moved the actual WordPress files from &lt;code&gt;/var/www/wordpress&lt;/code&gt; to &lt;code&gt;/var/www/wordpress/blog&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Back to the suspect way to use...  You will want to ensure in the Settings panel of the WP admin to set your blog URL's (site URL and homepage) to be &lt;code&gt;http://www.example.com/blog&lt;/code&gt;.  This is so that WordPress will generate URL's that look like that (instead of looking like one with the IP address in it, or however you originally accessed the installer).&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-2857027197042012687?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/2857027197042012687/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=2857027197042012687' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2857027197042012687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2857027197042012687'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/08/wordpress-nginx-subdirectories-and.html' title='WordPress, Nginx, Subdirectories, and Separate Server Proxying'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4917783491657386450</id><published>2008-07-11T10:22:00.001-07:00</published><updated>2008-07-11T21:15:52.320-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Fork of acts_as_versioned to provide version diffs and more</title><content type='html'>&lt;em&gt;Update: Added the &lt;code&gt;earliest?&lt;/code&gt; and &lt;code&gt;latest?&lt;/code&gt; methods, see below.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;On my current project, I've recently begun using Technoweenie's &lt;a href="http://github.com/technoweenie/acts_as_versioned/tree/master"&gt;acts_as_versioned&lt;/a&gt; (I also looked at simply_versioned which also looks great - you'll need to evaluate for your own needs).  This project has some particular needs around versions that aren't covered by the existing plugin, so of course &lt;a href="http://github.com/chris/acts_as_versioned/tree/master"&gt;I forked it on GitHub&lt;/a&gt; and have been adding my enhancements to &lt;a href="http://github.com/chris/acts_as_versioned/tree/master"&gt;my fork&lt;/a&gt;.  These are publicly available.&lt;br /&gt;&lt;br /&gt;Right now there are two enhancements that may be of interest to others:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;For each version, there is now an &lt;code&gt;updated_attributes&lt;/code&gt; field that stores an Array of the attribute names that were changed in the creation of this version.  This is essentially the same array provided by the &lt;code&gt;changed&lt;/code&gt; method from ActiveRecord (requires 2.0 (or 2.1?) or later for the "dirty" handling stuff).  This provides a nice way of being able to show what changed between versions, without having to compute that yourself (as well as compute it each time you need to display it).  Since the data is right there when making the version, I just store it off in a serialized column.  This will not record "non-versioned columns".  This obviously requires another column in your DB table, and I've amended the migration method, but if you already are using acts_as_versioned, you'd need to manually add the &lt;code&gt;updated_attributes&lt;/code&gt; column (of type "text").&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A small tweak, but the &lt;code&gt;revert_to!&lt;/code&gt; method now has an optional second parameter that, if set to true, will remove all &lt;em&gt;newer&lt;/em&gt; versions.  In our workflow, when you do a revert/rollback, you no longer want the newer versions, so we delete them.  You can achieve this in your app without deleting them, but it just seems cleaner in our case.  You can also do this manually by calling the same method that &lt;code&gt;revert_to!&lt;/code&gt; uses, &lt;code&gt;delete_newer_versions&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Added the &lt;code&gt;earliest?&lt;/code&gt; and &lt;code&gt;latest?&lt;/code&gt; methods to the model's Version object as well, so that you can call these on an individual version instance - very convenient for me at least.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;I have only tested this under Rails 2.1 and MySQL and SQLite (all the unit tests for acts_as_versioned use SQLite).  I have not sent Rick a pull request, because a) I've only been using this for a few days, and I'd like to have it in use a bit longer to be sure of the approach and quality.  For example, to really be ideal for the mainline distro, I suspect that adding an option to &lt;code&gt;acts_as_versioned&lt;/code&gt; when you define it in your model, would be best for the updated_attributes storage aspect, e.g. making this part optional.  It's never optional for my needs, so I haven't spent the time to do this.  If you use my fork and do that, please send me a pull request.&lt;br /&gt;&lt;br /&gt;The next piece I'm looking at is supporting versioning of associated models.  This will be a bit more involved.  There is &lt;a href="http://github.com/rlivsey/acts_as_versioned_association/tree/master"&gt;acts_as_versioned_association&lt;/a&gt;, but it says it is not maintained and doesn't work with Rails 2.x.  However, I may be able to fork that and bring it up to speed for the latest Rails and acts_as_versioned...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4917783491657386450?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4917783491657386450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4917783491657386450' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4917783491657386450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4917783491657386450'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/07/fork-of-actsasversioned-to-provide.html' title='Fork of acts_as_versioned to provide version diffs and more'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-8726125595002780377</id><published>2008-07-01T17:01:00.001-07:00</published><updated>2008-07-01T17:08:19.483-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Update on Rails, jQuery, autocomplete</title><content type='html'>Today I changed my &lt;a href="http://github.com/chris/auto_complete_jquery"&gt;auto_complete_jquery&lt;/a&gt; plugin (which I blogged about &lt;a href="http://codeintensity.blogspot.com/2008/06/rails-jquery-auto-complete-and-new.html"&gt;previously&lt;/a&gt;) to work with a different jQuery autocomplete plugin (that's not confusing is it?!).  Previously, I'd been using the "jquery-autocomplete" plugin, but had been having problems with it always being case sensitive, and with it being pretty darn slow.  To solve that, I wound up switching to &lt;a href="http://www.dyve.net/jquery/?autocomplete"&gt;Dylan Verheul's jquery autocomplete&lt;/a&gt; plugin, which is fantastic!  So, I had to update my plugin (literally &lt;a href="http://github.com/chris/auto_complete_jquery/commit/d2d287fcd36959ee5058ff2ca208d25c50ab4272"&gt;changed two lines&lt;/a&gt;, along with the readme and some comments).&lt;br /&gt;&lt;br /&gt;So, what does it all mean?  First, things are no longer case-sensitive (although you can tweak that if you need it, see the &lt;a href="http://www.dyve.net/jquery/autocomplete.txt"&gt;docs&lt;/a&gt; for DV's jquery plugin).  Second, the speed is near instant, and if it's taking any time at all, there's now a CSS style you can set to show an indicator while the AJAX call is running (nice!).    Further, there are a slew of options you can set, but one of the coolest things is the ability to set a formatter JavaScript function to adjust the display of the returned results, but without affecting the actual value that is placed in your text field.  This is really cool for providing further information about a given matched item.  For example, I use it to display, on a line below the matched name, the location of the item.  There's an interactive example of this on Dylan Verheul's site.&lt;br /&gt;&lt;br /&gt;I highly recommend updating all around on this.  For those that might be using my prior version, the changes you'd need to make are:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Change your JavaScript calls that make a HTML input into an auto-complete from this format:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$("input#post_title").autocomplete({ ajax: "auto_complete_for_post_title" })&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;to this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$("input#post_title").autocomplete("auto_complete_for_post_title")&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Update to the HEAD of my plugin.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Remove the old &lt;code&gt;jquery.ui.autocomplete*.js&lt;/code&gt; files, and install Dylan's single &lt;code&gt;jquery.autocomplete.js&lt;/code&gt; file, updating your JS includes accordingly.  Same goes for the stylesheet.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Note, to do the cool 2nd line output of auto-complete items, you will need to write your own auto-complete Rails action, which means you don't need my plugin :)  I may update my plugin at some point so you can pass a block in to the autocomplete function to create this same scenario, but this is pretty specific stuff, so we'll see.  As a very brief set of instructions to do this, you can essentially copy-paste the auto-complete method that gets defined by my plugin, and then update what you return as text.  To do the 2nd line bit, you want to return items in the format, "item|2nd line stuff", (so use the pipe symbol to separate the two lines).  Then, you can use a simple JavaScript formatter function like:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;function formatAutocompleteItem(row) {&lt;br /&gt;	return row[0] + "&amp;lt;br&amp;gt;&amp;lt;i&amp;gt;" + row[1] + "&amp;lt;/i&amp;gt;";&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then, update your call to the jQuery autocomplete that sets up a field as autocomplete to be:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$("input#post_title").autocomplete("auto_complete_for_post_title", { formatItem:formatAutocompleteItem })&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-8726125595002780377?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/8726125595002780377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=8726125595002780377' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8726125595002780377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8726125595002780377'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/07/update-on-rails-jquery-autocomplete.html' title='Update on Rails, jQuery, autocomplete'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-83279738304560518</id><published>2008-06-17T21:46:00.001-07:00</published><updated>2008-06-17T21:46:59.386-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>RSpec View Testing Problems</title><content type='html'>I've been using RSpec exclusively on my latest project.  I'd say I'm still fairly new to it, but it has won me over for the time being.  However, the view testing has been a real problem.  You can test views quite easily and nicely with RSpec, however, when you do something subtly wrong, it can cause RSpec to fail without any visible error!  In fact, Autotest doesn't report a failure at all, and the only way I know it is failing is either I pay close attention to the number of examples it said it ran, or more likely, my cruisecontrol.rb CI server will actually fail (because it detects the commands exit status).&lt;br /&gt;&lt;br /&gt;For example, while Autotest says everything is fine, the CI server will show something like this (note for easier reading I've trimmed this a bit):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/widgets/index.html.erb&lt;br /&gt;- should render list of widgets&lt;br /&gt;&lt;br /&gt;/bobbles/index.html.erb&lt;br /&gt;&lt;br /&gt;Finished in 4.977586 seconds&lt;br /&gt;&lt;br /&gt;175 examples, 0 failures&lt;br /&gt;rake aborted!&lt;br /&gt;Command /usr/bin/ruby1.8 -I"/var/cruisecontrolrb/projects/myproject/work/vendor/plugins/rspec/lib"  "/var/cruisecontrolrb/projects/myproject/work/vendor/plugins/rspec/bin/spec" "spec/controllers/bobbles_controller_spec.rb" ... --options /var/cruisecontrolrb/projects/myproject/work/spec/cruisecontrol_rcov.opts failed&lt;br /&gt;&lt;br /&gt;(See full trace by running task with --trace)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see, RSpec is reporting &lt;strong&gt;0 failures&lt;/strong&gt;, yet rake fails.  This is because in reality RSpec is returning an exit code of 1 instead of 0.  But, looking at the output, it's certainly not revealing.  Running with &lt;code&gt;--trace&lt;/code&gt; is of no help either.&lt;br /&gt;&lt;br /&gt;What I now know to pay attention to in situations like this is the fact that that last spec it ran, the &lt;code&gt;/bobbles/index.html.erb&lt;/code&gt; one has no examples listed under it.  That is thus the culprit (you can also argue that it's the last thing to "run" and then rake fails, so it's likely in this, etc.). &lt;br /&gt;&lt;br /&gt;The real pain comes when you try to figure out what the heck is causing this.  You have zero feedback, and no way that I know of to somehow debug or inspect the test to see what's failing.  In my experience to date with these, it boils down to some problem in your mocks and stubs, but this can be difficult to figure out.  I admit, the one that prompted me to write this blog entry is one I've still yet to figure out, and finally just punted on.&lt;br /&gt;&lt;br /&gt;I've been hearing a lot about not testing views, or testing very little of the views.  I agree in general on this, and am now looking into using &lt;a href="http://github.com/brynary/webrat/tree/master"&gt;Webrat&lt;/a&gt; to do integration testing to really test "view" functionality, and leave the rest of my view testing mostly to testing my helpers, controllers, and models.  Here are a couple of blog entries related to all this:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Err the blog (via comments) &lt;a href="http://errtheblog.com/posts/66-view-testing-20"&gt;discussion&lt;/a&gt; on view testing techniques.  This is a good read.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Rubby Russell's &lt;a href="http://www.robbyonrails.com/articles/2007/08/02/spec-your-views"&gt;blog entry&lt;/a&gt; on testing your views with RSpec.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.chariotsolutions.com/slides/pdfs/ete2008-IntegrationTestingWithRSpec.pdf"&gt;Integration Testing in Ruby with RSpec's Story Automation Framework&lt;/a&gt; by David Chelimsky (PDF)&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-83279738304560518?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/83279738304560518/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=83279738304560518' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/83279738304560518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/83279738304560518'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/06/rspec-view-testing-problems.html' title='RSpec View Testing Problems'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-8101168882309345726</id><published>2008-06-17T12:50:00.001-07:00</published><updated>2008-06-17T14:38:47.748-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><title type='text'>Have Autotest speak to you</title><content type='html'>&lt;em&gt;Update: the first .autotest I had in here was bogus, sorry about that.  The .autotest file contents below work properly with Rspec tests at least.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I make extensive use of ZenTest's Autotest to constantly watch my test suite and ensure my app's tests are passing on my dev box/during development.  Historically I've used Growl/growlnotify to get little popup notices indicating if my tests passed or failed.  That's nice, and I've done the enhancements that add graphics and style it nicely, etc.  But, in reality, I'm not always looking and sometimes don't see the messages.  Plus, they can be somewhat distracting.&lt;br /&gt;&lt;br /&gt;So, I've switched to using the handy &lt;code&gt;say&lt;/code&gt; tool on the Mac (on Linux I think you could use "espeak", no clue on Windows, but then, uh, well, why are you doing dev work on Windows?! ;-)&lt;br /&gt;&lt;br /&gt;The speaking is nice - I hear it, but don't get visually distracted.  I use different voices for tests passed vs. failed too.  This may not work great if you work in a cube farm, or even a cafe, but here at home, or in your own office, I think it's great.  Here's my &lt;code&gt;.autotest&lt;/code&gt; file as an example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;require 'autotest/redgreen'&lt;br /&gt;&lt;br /&gt;module Autotest::Growl&lt;br /&gt;  def self.growl(title, msg, img, pri=0, stick="")&lt;br /&gt;    system "/usr/local/bin/growlnotify -n autotest --image #{img} -p #{pri} -m #{msg.inspect} #{title} #{stick}" &lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  Autotest.add_hook :ran_command do |at|&lt;br /&gt;    results = at.results.last&lt;br /&gt;&lt;br /&gt;    unless results.nil?&lt;br /&gt;      output = results[/(\d+)\s+examples?,\s*(\d+)\s+failures?(,\s*(\d+)\s+pending)?/]&lt;br /&gt;      if output&lt;br /&gt;        failures = $~[2].to_i&lt;br /&gt;        pending = $~[4].to_i&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      if failures &gt; 0&lt;br /&gt;        `/usr/bin/say -v Zarvox "you broke the code"`&lt;br /&gt;      elsif pending &gt; 0&lt;br /&gt;        `/usr/bin/say -v Alex "Tests passed, with some pending"`&lt;br /&gt;      else&lt;br /&gt;        unless at.tainted&lt;br /&gt;          `/usr/bin/say -v Victoria "all tests passed"`&lt;br /&gt;        else&lt;br /&gt;          `/usr/bin/say -v Victoria "tests passed"`&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To see what voices your system has available, open the Speech system preference pane, pull down "System Voice" and select "Show More Voices" to see the full list.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-8101168882309345726?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/8101168882309345726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=8101168882309345726' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8101168882309345726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8101168882309345726'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/06/have-autotest-speak-to-you.html' title='Have Autotest speak to you'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7949105118597419524</id><published>2008-06-11T16:13:00.001-07:00</published><updated>2008-06-23T18:45:43.111-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='Capistrano'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='ContinuousIntegration'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Changelogs and Deployment Notification for Capistrano and Git</title><content type='html'>Early warning: this is a hack, which doesn't mean it's bad, just that it's not polished.  However, I am documenting my solution for myself thus far, as well as figured others might find it useful...&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Update: Added my shell command for doing deploys (see end of this post).&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I wanted a way to automate a few things around deployments, and integrate this a bit with my continuous integration server.  I use CruiseControl for the CI server, and previously blogged about setting up CC.rb with Git.  The goals for this next task, and subject of this blog post are:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Tag the code on successful deploys.  My CI server already tags the code anytime it does a successful build, but since I didn't cover that previously, I'll mention it here as well.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Notify a list of people via email whenever a new deploy happens.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Generate a changelog, based on Git commit messages (better make sure they're suitable reading for whoever gets your deploy notices!), and include this changelog in the deploy emails.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Have the CI tag I want to deploy as the only required piece of info/parameter when issuing a deploy command.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Tagging&lt;/h3&gt;&lt;br /&gt;First, I tag the code on any successful CI run.  This tag is what I can then use as the Git tag to deploy.  Capistrano supports this via the &lt;code&gt;branch&lt;/code&gt; variable (set its value to the tag name).  As you can guess, you can use pretty much any Git ID/tag/branch name for this.  To do this, add a task to your cruise.rake file (or similar - wherever you define your custom CruiseControl command), and then ensure you run that task during a CruiseControl session.  Here's my task:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;desc "Tag the code on successful CI build"&lt;br /&gt;task :ci_tag do&lt;br /&gt;  timestamp = Time.now.strftime("%Y%m%d%H%M%S")&lt;br /&gt;  tag_name = "CI_#{timestamp}"&lt;br /&gt;  # Create an empty file with our tag name, so we can easily go grab the tagname&lt;br /&gt;  # from the CI output page and do deploys, etc.&lt;br /&gt;  system("touch #{File.join(ENV['CC_BUILD_ARTIFACTS'], tag_name)}")&lt;br /&gt;  system("git tag -a -m 'Successful continuous integration build on #{timestamp}' #{tag_name}")&lt;br /&gt;  system("git push --tags")&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;From the above, you can see that I'll get tags of the form: CI_timestamp.  Next up, I want to tag a successful deploy to indicate which commit/tag actually got deployed and when.  This is handled via an after task in my Capistrano deploy.rb:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;after "deploy:restart", "tag_last_deploy"&lt;br /&gt;task :tag_last_deploy do&lt;br /&gt;  set :timestamp, Time.now&lt;br /&gt;  set :tag_name, "deployed_to_#{rails_env}_#{timestamp.to_i}"&lt;br /&gt;  `git tag -a -m "Tagging deploy to #{rails_env} at #{timestamp}" #{tag_name} #{branch}`&lt;br /&gt;  `git push --tags`&lt;br /&gt;  puts "Tagged release with #{tag_name}."&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This will create tags like, &lt;code&gt;deployed_to_staging_1213223458&lt;/code&gt;, and works for both staging and production (or any environment you're targeting - note the use of the &lt;code&gt;rails_env&lt;/code&gt; variable - you may need to use something else).  One thing to pay particular attention to, is that this tag is actually tagging another tag, as defined by the &lt;code&gt;branch&lt;/code&gt; variable (mentioned above).  In order for this to work though, you need to ensure that your tags are up to date locally.  Thus, somewhere in your workflow you'll need to do a &lt;code&gt;git pull --tags&lt;/code&gt;, if like me, your CI server is elsewhere and is generating those tags.&lt;br /&gt;&lt;br /&gt;Ok, we're all tagged up, let's move on...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Notification&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;It turns out there's a nifty new plugin called &lt;a href="https://github.com/relevance/cap_gun/tree"&gt;Cap Gun&lt;/a&gt; that will take care of emailing a list of folks on deploy.  Setup is covered in their README, but the one bit they don't mention, is that you can include a comment in the email message that goes out.  I wanted to include a changelog in these emails, so I tapped into this comment attribute, setting it to the text of my changelog.  To use the comment, you can either set it via &lt;code&gt;-s comment="my lovely comment"&lt;/code&gt; on your Capistrano deploy command, or you can set the &lt;code&gt;comment&lt;/code&gt; variable in your Capistrano deploy.rb or included script.  More on that in a minute.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Changelogs&lt;/h3&gt;&lt;br /&gt;My changelog, so far, is very simple, it just pulls the comments for the Git commits that occurred since the last deploy (for the appropriate target), up to the tag specified (which in this case will be the CI tag you are about to deploy).  To handle this, I use a small Ruby script, combined with the great &lt;a href="http://github.com/mojombo/grit/tree"&gt;Grit&lt;/a&gt; gem that lets one manipulate Git via a nice Ruby API.  The script simply spits out a simple chunk of text that will be what gets put into the &lt;code&gt;comment&lt;/code&gt; Capistrano variable for our deployment notifications.  This is in particular where the "hack" comes into play.  This script is not robust, does essentially no error checking, etc, etc.  Use at your own risk! And with that, here it is:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;#!/usr/bin/env ruby&lt;br /&gt;&lt;br /&gt;require 'rubygems'&lt;br /&gt;require 'mojombo-grit'&lt;br /&gt;include Grit&lt;br /&gt;&lt;br /&gt;unless ARGV.length == 2&lt;br /&gt;  puts "Usage: changelog.rb staging|production &amp;lt;commit-or-tag&amp;gt;"&lt;br /&gt;  puts "  where commit-or-tag is the commit ID or tag you are planning to deploy"&lt;br /&gt;  exit -1&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;repo_location = File.expand_path(File.dirname(__FILE__) + '/..')&lt;br /&gt;target = ARGV[0]&lt;br /&gt;about_to_deploy_commit = ARGV[1]&lt;br /&gt;repo = Repo.new(repo_location)&lt;br /&gt;&lt;br /&gt;# Find the tag for the last deployed&lt;br /&gt;tags = repo.tags.collect {|tag| tag.name }&lt;br /&gt;tags.delete_if {|tag| !(tag =~ /^deployed_to_#{target}_/)}&lt;br /&gt;tags.sort!&lt;br /&gt;last_deployed_tag = tags[-1]&lt;br /&gt;&lt;br /&gt;commits_for_changelog = repo.commits_between(last_deployed_tag, about_to_deploy_commit)&lt;br /&gt;commits_for_changelog.reverse!&lt;br /&gt;&lt;br /&gt;puts "Changes since last release:"&lt;br /&gt;commits_for_changelog.each do |commit|&lt;br /&gt;  puts " "&lt;br /&gt;  puts "  #{commit.message}"&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To run through it briefly, it takes two parameters (and clearly, you can change this for your own deployment targets, etc.): a deployment target, and a tag (which can actually be a tag, a commit ID, branch, etc.).  It sets up a &lt;code&gt;repo&lt;/code&gt; variable for your Git repository using Grit, and then proceeds to find the last deployed tag for that deployment target.  After that, it gets all the commits between that last deployed tag and the tag you specified as the second script argument, and prints out the commit messages.&lt;br /&gt;&lt;br /&gt;To integrate this, I added this line to my Capistrano deploy.rb:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;set :comment, `script/changelog.rb staging #{branch}`&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;As you can see, that one is specific to my staging environment, and lives inside my "staging" task in deploy.rb.  Same, appropriately edited version goes for production.  &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Deployment Command&lt;/h3&gt;&lt;br /&gt;Lastly, I define a simple shell function to do my deploys, which ensures I have done a &lt;code&gt;git pull&lt;/code&gt; so I have all the tags, and makes the command easier to remember and get right, etc:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;stagemyproject () {&lt;br /&gt;        git pull&lt;br /&gt;        cap -s branch=$1 staging deploy:migrations&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You would thus have a command line to do a deploy like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;stagemyproject CI_20080612052417&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That's it, and if you've managed to read this far, congrats, and if you've not only managed to read this far, but payed attention and got value out of it, well, cool.&lt;br /&gt;&lt;br /&gt;For anyone who uses/adapts this, please do let me know improvements you make, or suggestions, or tweaks/changes, and so on.  I've been using this for all of about a half dozen deploys so far.  If (more like when) I make improvements, I'll update.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7949105118597419524?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7949105118597419524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7949105118597419524' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7949105118597419524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7949105118597419524'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/06/changelogs-and-deployment-notification.html' title='Changelogs and Deployment Notification for Capistrano and Git'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4392075632411009446</id><published>2008-06-06T21:19:00.001-07:00</published><updated>2008-06-06T21:19:29.992-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CruiseControl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perforce'/><title type='text'>Perforce for CruiseControl.rb now on GitHub</title><content type='html'>After getting another request for my Perforce implementation for CruiseControl.rb, I've put it up on GitHub (&lt;a href="http://github.com/chris/cruisecontrolrb_perforce"&gt;cruisecontrolrb_perforce&lt;/a&gt;), and also updated my &lt;a href="http://codeintensity.blogspot.com/2007/06/perforce-implementation-for.html"&gt;previous blog entry&lt;/a&gt; on the subject.&lt;br /&gt;&lt;br /&gt;Just note, I haven't used this since August 2007, so use at your own risk :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4392075632411009446?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4392075632411009446/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4392075632411009446' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4392075632411009446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4392075632411009446'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/06/perforce-for-cruisecontrolrb-now-on.html' title='Perforce for CruiseControl.rb now on GitHub'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-6021292758807962561</id><published>2008-06-04T13:36:00.001-07:00</published><updated>2008-07-01T17:02:29.148-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Rails, jQuery, auto-complete, and a New Plugin</title><content type='html'>&lt;em&gt;Update: I've switched which jQuery autocomplete plugin I use for this, see my &lt;a href="http://codeintensity.blogspot.com/2008/07/update-on-rails-jquery-autocomplete.html"&gt;newer blog entry&lt;/a&gt;.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;The other day, I made a whole switch from Prototype &amp; Scriptaculous to &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt;.  I've had the bug to do this for a while, and this is a new project, so I went for it.  I don't have anything against Prototype, so my main impetus for this was a move towards &lt;a href="http://en.wikipedia.org/wiki/Unobtrusive_JavaScript"&gt;Unobtrusive JavaScript&lt;/a&gt;, and also the speed aspect (the site I'm currently working on, if things go accordingly to plan, will do some pretty serious traffic).  But, the unobtrusive JavaScript was the key, and really, my switch is more of a philosophy of approach rather than say a dislike for Prototype, etc.  And, of course, it's something new to play with :)&lt;br /&gt;&lt;br /&gt;Before I go any further, I'll state right now, I am not a JavaScript expert, and I've been using jQuery now for all of a couple hours.  &lt;br /&gt;&lt;br /&gt;One of the results of my switch however, was that I hacked DHH's auto_complete Rails plugin, to work for jQuery.  Simple change.  I tweaked the controller macro, and then gutted the JS helpers, as you just don't need those when using jQuery in this way.  It does require the &lt;a href="https://github.com/ReinH/jquery-autocomplete/tree"&gt;jquery-autocomplete&lt;/a&gt; plugin for jQuery.  I've published my Rails plugin for this on GitHub as &lt;a href="http://github.com/chris/auto_complete_jquery"&gt;auto_complete_jquery&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;Circling back around, here's what I did to get all this going.  I did run into one issue (see step 10 below) that I'm still tracking down (easy solution in the interim, but I'd like to understand what's happening, so if you have comments, please let me know):&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Removed the Prototype and Scriptaculous JS files from the public/javascripts dir of my Rails app.  You don't have to do this, but I am no longer using them, so saw no need to keep them there, and it helps ensure I don't mistakenly use something from them or include them in the view.  This includes: &lt;code&gt;prototype.js, controls.js, dragdrop.js, and effects.js&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Removed the prototype-based Rails auto_complete plugin from &lt;code&gt;vendor/plugins&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Installed the &lt;a href="http://jquery.com/"&gt;latest minified jQuery&lt;/a&gt; file in &lt;code&gt;public/javascripts/jquery&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Installed the JS files for the jquery-autocomplete plugin, and its dependencies: &lt;code&gt;jquery.templating.js, and jquery.ui.autocomplete.js&lt;/code&gt;. (see the &lt;a href="http://github.com/ReinH/jquery-autocomplete"&gt;jquery-autocomplete plugin&lt;/a&gt; for these files).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Added the &lt;code&gt;jquery.ui.autocomplete.css&lt;/code&gt; file to &lt;code&gt;public/stylesheets&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Installed my &lt;a href="http://github.com/chris/auto_complete_jquery"&gt;auto_complete_jquery&lt;/a&gt; plugin.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Put the proper includes for the CSS file and the JS files in my application layout file:&lt;br/&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  &amp;lt;%= stylesheet_link_tag 'jquery.ui.autocomplete' %&amp;gt;&lt;br /&gt;  &amp;lt;%= javascript_include_tag 'jquery/jquery.min', 'jquery/jquery.templating', 'jquery/jquery.ui.autocomplete.ext', 'jquery/jquery.ui.autocomplete', :cache =&gt; 'jquery' %&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Note that I keep my jQuery JS files in a subdir for organizational purposes, but you can modify as needed.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Changed my existing auto-complete text fields that used the Rails Prototype based auto_complete plugin's helpers to just be plain old text fields, such as:&lt;br /&gt;&lt;code&gt;&amp;lt;%= coffee.text_field :drink, :autocomplete =&gt;"off" %&amp;gt;&lt;/code&gt;&lt;br /&gt;This is doing an auto-complete for the "drink" attribute of the Coffee model.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I can simply leave any auto_complete_for calls that existed in my controller, as that works the same.  If you had custom versions that were based on the code from the Prototype-based Rails plugin, just go look at the code in my plugin to see the differences, it's a simple change.&lt;/li&gt;&lt;br /&gt;&lt;/li&gt;Add the JavaScript that sets up the auto-complete for the given text field.  This will typically look like:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$(document).ready(function() {&lt;br /&gt;  $("input#coffee_drink").autocomplete({ ajax: "auto_complete_for_coffee_drink" })&lt;br /&gt;});&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Where does this go?  It depends.  What I've been liking is using the &lt;a href="http://blog.media72.net/2008/05/13/javascript-auto-include-rails-plugin/"&gt;JavaScript auto-include plugin&lt;/a&gt;, which creates a Rails-style convention for JavaScript files that pertain to individual actions, or are controller-wide.  So in my case, this code would get placed in &lt;code&gt;public/javascripts/views/coffees/new.js&lt;/code&gt;, or likely one directory up, as simply coffees.js (so that I can use it in any CoffeesController action that needs to auto-complete on &lt;code&gt;coffee.drink&lt;/code&gt;.  Without that plugin, you just put it in whatever JS file is appropriately included for the view you're using it in, etc.  You can of course put it directly into the view in a script block, but then you aren't doing the whole Unobtrusive JavaScript thing as rigidly.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Finally, what I found is that I had to add a route for this.  This is the issue I mentioned above.  It sort of makes sense, but what I'm unclear on is, why the prior standard/Prototype-based Rails auto_complete plugin didn't require a route.  They both seem to use a GET, define the action the same way, and so on.  I'm hoping I'm just missing something obvious.  So, the route I added is:&lt;br /&gt;&lt;code&gt;map.connect ':controller/auto_complete_for_coffee_drink', :action =&gt; 'auto_complete_for_coffee_drink', :format =&gt; 'json'&lt;br /&gt;&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;A bunch of steps, but pretty simple work.  The app I'm doing this on is all of a few days old, so I hadn't gotten into use of much else in Prototype and so on, thus making the wholesale switch easy.&lt;br /&gt;&lt;br /&gt;If you'd like to learn more about any of these things, and as a comprehensive set of links:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://jquery.com"&gt;jQuery site&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="https://github.com/ReinH/jquery-autocomplete/tree"&gt;jquery-autocomplete plugin on GitHub&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://plugins.jquery.com/project/jq-autocomplete"&gt;jquery-autocomplete plugin on jQuery plugins site&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Unobtrusive_JavaScript"&gt;Unobtrusive JavaScript&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;DHH's &lt;a href="http://github.com/rails/auto_complete"&gt;auto_complete Rails plugin&lt;/a&gt; for use with Prototype&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://blog.media72.net/2008/05/13/javascript-auto-include-rails-plugin/"&gt;JavaScript auto-include plugin&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;My &lt;a href="http://github.com/chris/auto_complete_jquery"&gt;auto_complete_query&lt;/a&gt; Rails plugin&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Update: I removed the jQuery Dimensions JS file and include for it in my layout, as this is now included in the latest jQuery JS file itself.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Update 2:&lt;/em&gt; I don't know how the standard auto_complete plugin manages to do without routes, but here is a generic route for all auto-complete actions across controllers:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;map.auto_complete ':controller/:action', &lt;br /&gt;                  :requirements =&gt; { :action =&gt; /auto_complete_for_\S+/ },&lt;br /&gt;                  :conditions =&gt; { :method =&gt; :get }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;I hesitate to put this into the plugin, as routes can be quite tricky in more complex apps, and I wouldn't want to auto-hose someone :)&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-6021292758807962561?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/6021292758807962561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=6021292758807962561' title='21 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6021292758807962561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6021292758807962561'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/06/rails-jquery-auto-complete-and-new.html' title='Rails, jQuery, auto-complete, and a New Plugin'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-772239523471571254</id><published>2008-06-02T14:56:00.001-07:00</published><updated>2008-06-02T14:56:56.786-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='Capistrano'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Fixing Capistrano 2.3.0 and Git Deploy Problem</title><content type='html'>If you upgrade to Capistrano 2.3.0, and are doing deploys from a Git repository, you may find that all of a sudden you can no longer deploy.  This is the case if you have no tags in your Git repo.  Cap 2.3.0 changed one of the Git commands it uses and that apparently doesn't work right if you don't have tags.  So, to solve the problem, you can simply create a single tag in your Git repository.  The tag does not have to relate to your build at all, you only need one tag in the repo (not one per build or anything like that), etc.  Once you create the tag, you can now deploy again.&lt;br /&gt;&lt;br /&gt;To create a tag in Git, or, I think the "cooler" kind of tag, an annotated tag, you can do:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;git tag -a &lt;em&gt;tag_name&lt;/em&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Replace "tag_name" with your tag name of course.  The "-a" option says to make it an annotated tag, which lets you enter a comment about the tag.  You can put whatever you want in there.  I'm liking this potential use with my continuous integration server when it makes tags on successful builds.  Lots of possibilities.&lt;br /&gt;&lt;br /&gt;Finally, if you deploy from a remote repo, or if you have a remote repo (say on GitHub), you will need to push your tag.  This does not automatically occur on a push, you need to add "--tags" option to git-push to include your tags:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;git push --tags&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now you'll have your tags on your remote repo, and listed under the "all tags" tab on GitHub.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-772239523471571254?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/772239523471571254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=772239523471571254' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/772239523471571254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/772239523471571254'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/06/fixing-capistrano-230-and-git-deploy.html' title='Fixing Capistrano 2.3.0 and Git Deploy Problem'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-8482337899768145586</id><published>2008-05-28T17:14:00.001-07:00</published><updated>2008-05-28T17:14:49.769-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='travel'/><category scheme='http://www.blogger.com/atom/ns#' term='RailsConf'/><category scheme='http://www.blogger.com/atom/ns#' term='RailsConf08'/><category scheme='http://www.blogger.com/atom/ns#' term='Portland'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>I'm at RailsConf 2008 This Week</title><content type='html'>I'll be at RailsConf this week.  Looking forward to it, and to time in Portland which I always like.  Already scouting out places to eat, which it appears I'll have to watch the time on given there are many BoF's and other sessions in the evenings that sound good.  See you there...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-8482337899768145586?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/8482337899768145586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=8482337899768145586' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8482337899768145586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8482337899768145586'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/05/i-at-railsconf-2008-this-week.html' title='I&amp;#39;m at RailsConf 2008 This Week'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7422861438826693861</id><published>2008-05-23T10:31:00.001-07:00</published><updated>2008-05-23T10:31:14.291-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='coworking'/><category scheme='http://www.blogger.com/atom/ns#' term='Jelly'/><title type='text'>Jelly - work at my house</title><content type='html'>Jelly, what is it?  It's not something you spread on toast, or not this kind anyway.  &lt;a href="http://www.workatjelly.com/"&gt;Jelly&lt;/a&gt; is "casual coworking".  It's popping up in different cities, and what it really boils down to is, someone opens up their house/apartment/some space, and folks get together to work.  They aren't collaborating (although they could), it's just a way to get that social interaction for folks (like me) who work at home.  You get to meet and interact with other interesting folks in your area, maybe do a bit of work, and get that social interaction you miss while working at home.&lt;br /&gt;&lt;br /&gt;To learn more, check out this &lt;a href="http://blog.coworking.info/2008/05/22/coworking-on-nprs-marketplace/"&gt;video&lt;/a&gt; that NPR did, or Amit Gupta's (who started Jelly) &lt;a href="http://www.vimeo.com/246107"&gt;video&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This is pretty interesting to me, and I'm actually thinking I might do it here in Eugene.  I'll have to consider whether I want to invite a bunch of strangers (as great as you all might be (hopefully ;-) to overrun my house for the day or not, but it seems pretty interesting.  I always have to think about balancing this with privacy and having a bunch of random folks that I'm not directly aquanted with knowing my house/where I live, and so on.  I consider it a bit different than say the 20-something single person living in a random apartment in a city.  This is my house, and where my family (wfie &amp; kids) live, etc.  Still, it intrigues me.  Plus, I have the space, WiFi/net, etc. to do it, and the tech folks (shout out to the Django group) I've met here in Eugene are all cool so far.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7422861438826693861?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7422861438826693861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7422861438826693861' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7422861438826693861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7422861438826693861'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/05/jelly-work-at-my-house.html' title='Jelly - work at my house'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-3929504052257506015</id><published>2008-05-21T21:42:00.001-07:00</published><updated>2008-05-21T21:44:04.413-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mongrel'/><category scheme='http://www.blogger.com/atom/ns#' term='monitoring'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Monitoring Mongrels on an F5 BigIP</title><content type='html'>Almost a year after I raised the issue of problems monitoring Mongrel instances on an F5 BigIP, I still get occasional emails asking whether I got it working and how, etc.  So, firing off this blog entry to hopefully provide a more findable solution for folks (the mailman mongrel-users archive seems broken, and clearly people find my initial query on the subject, but not the response with the solution).&lt;br /&gt;&lt;br /&gt;So, if you need to monitor Mongrel instances with an F5 BigIP, and are doing so with an HTTP monitor health check, you want to set your Send String to be along the lines of the following:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;GET /heartbeat/index HTTP/1.1&lt;br /&gt;\r\n&lt;br /&gt;\r\n&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The key point here is to have the "\r\n" lines (the "\r" is what I was missing and many folks seem to get tripped up by the proper way to specify the line breaks needed for the HTTP request).&lt;br /&gt;&lt;br /&gt;Here's a &lt;a href="http://rubyforge.org/pipermail/mongrel-users/2007-August/003871.html"&gt;link to the solution&lt;/a&gt; provided by Jason Hoffman of Joyent, on the mongrel-users maiing list.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Note that I haven't worked with F5's since September 2007, so likely can't answer any further questions.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-3929504052257506015?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/3929504052257506015/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=3929504052257506015' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3929504052257506015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3929504052257506015'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/05/monitoring-mongrels-on-f5-bigip.html' title='Monitoring Mongrels on an F5 BigIP'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7633671441764181780</id><published>2008-05-08T00:14:00.001-07:00</published><updated>2008-05-08T00:14:41.375-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cameras'/><title type='text'>Webcam Recommendations</title><content type='html'>I'm back to needing recommendations for a webcam.  On the site (&lt;a href="http://basecampsilverton.com"&gt;Basecamp Silverton&lt;/a&gt;), we will only show images/stills taken from the camera, probably at some interval in the "minutes" range. The camera will be pointed at the local mountain from a house in town (the mountain is pretty darn close, but still, it's a mountain/in the distance, as compared to say a security or other similar application). We're looking for a camera that can automatically upload images to a server via FTP/SSH/SCP at regular intervals. &lt;br /&gt;&lt;br /&gt;Our criteria are the following, and I was hoping folks could make some recommendations: &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Requirements:&lt;/strong&gt; &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;video doesn't matter, must be able to produce still images of "reasonable" quality&lt;/li&gt;&lt;br /&gt;&lt;li&gt;lens and such must be sufficient to shoot a pretty high depth of field to maximize focus across long-ish range (I will explain that it'll be pointing at a nearby mountain from house in town, etc.)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Must do automated image upload via FTP and/or SSH/SCP.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Controllable interval on automated upload (nothing too fancy, but we may want as fine as say every 2 minutes or every 5 minutes?)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Wireless/WiFi (in case we want to mount it outside, or just to make it easier inside)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;web/browser based configuration, or configurable via a Mac (we do not have a Windows machine)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;$500 or less. We may have some flexibility here, if for example it includes the outdoor enclosure/is weatherproof.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Really prefer not to have any separate software solution, other than what's in the camera, but if that is the best way to get the FTP/SCP upload, because we won't have a machine to dedicate to running it.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Nice to haves: &lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Ability to be mounted in an outdoor enclosure, or weatherproof itself. This will be in Silverton, Colorado where they routinely see temperatures below zero, and have snow, etc.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;user adjustable zoom&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;We already had one camera, a TrendNet TV-IP201W, which was nice and cheap, but the thing appears to just have up and stopped working.  Plus, we had a lot of problems with it's FTP upload (and weird limitations on length of user login names and so on). Also, this camera seemed to just "crash"/need reboot every so often (often enough that it was annoying).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7633671441764181780?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7633671441764181780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7633671441764181780' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7633671441764181780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7633671441764181780'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/05/webcam-recommendations.html' title='Webcam Recommendations'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-607442124885782512</id><published>2008-05-06T09:42:00.001-07:00</published><updated>2008-05-06T09:42:58.829-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='Bring Light'/><title type='text'>Bring Light's New Facebook App</title><content type='html'>At &lt;a href="http://www.bringlight.com"&gt;Bring Light&lt;/a&gt;, we recently released a &lt;a href="http://apps.facebook.com/bringlight/"&gt;Facebook application&lt;/a&gt; to serve as a companion to our &lt;a href="http://www.bringlight.com"&gt;main site&lt;/a&gt;.  You can now use the Facebook application to show what projects you've contributed to, what your favorites are, what groups you're in, and tell the world about your philanthropic activities on Bring Light.  &lt;br /&gt;&lt;br /&gt;If you're already a Bring Light user, you can get to the Facebook application two ways.  If you're logged into &lt;a href="http://www.bringlight.com"&gt;www.bringlight.com&lt;/a&gt;, there is now a Facebook link in the upper right.  Or, you can go directly to the app on Facebook, by going to &lt;a href="http://apps.facebook.com/bringlight/"&gt;http://apps.facebook.com/bringlight/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here's a look at what the wide profile box on Facebook looks like after you add the app:&lt;br /&gt;&lt;br /&gt;&lt;div class="thumbnail"&gt;&lt;a href="http://skitch.com/chrisrbailey/k7kr/facebook-chris-bailey"&gt;&lt;img src="http://img.skitch.com/20080506-n6cge8jsf21w9ixdkw2xha51cq.preview.jpg" alt="Facebook | Chris Bailey" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family: Lucida Grande, Trebuchet, sans-serif, Helvetica, Arial; font-size: 10px; color: #808080"&gt;Uploaded with &lt;a href="http://plasq.com/"&gt;plasq&lt;/a&gt;'s &lt;a href="http://skitch.com"&gt;Skitch&lt;/a&gt;!&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-607442124885782512?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/607442124885782512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=607442124885782512' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/607442124885782512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/607442124885782512'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/05/bring-light-new-facebook-app.html' title='Bring Light&amp;#39;s New Facebook App'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-2709727362252491602</id><published>2008-05-05T09:59:00.001-07:00</published><updated>2008-05-05T09:59:47.817-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Thin'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='ShipFu'/><title type='text'>Announcing ShipFu!</title><content type='html'>Have you ever needed to quickly compare UPS and USPS shipping rates, and just wanted a simple web page/app to do it?  If so, check out my new &lt;a href="http://shipfu.com"&gt;ShipFu&lt;/a&gt; app.  It's incredibly simple.  No gratuitous web decoration, no hidden motivation behind it to promote some other product or shipping service, etc., just a simple calculator.  Enter your package origin and destination, and dimensions and weight, and voila, you'll be presented with all the rates available for that from the two services.&lt;br /&gt;&lt;br /&gt;I built &lt;a href="http://shipfu.com"&gt;ShipFu&lt;/a&gt; to address a need of my own, and the fact that I just didn't seem to like any other solutions out there - seemed to be too many hidden agendas or ungainly UI's, etc.  Also, I built this as a bit of an experiment with a few technology aspects.  It's a Rails app, and is running on the new-ish Thin server, etc.  I plan to have a blog post that goes into a lot more depth on some of the fun things that occurred as part of building this super simple app.  &lt;br /&gt;&lt;br /&gt;Also, please, by all means, send me feedback (use the feedback link shown near the bottom of the site) if you'd like to see some feature or enhancement or what not.  Or, just use it to help you quickly gauge shipping rates.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-2709727362252491602?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/2709727362252491602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=2709727362252491602' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2709727362252491602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2709727362252491602'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/05/announcing-shipfu.html' title='Announcing ShipFu!'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-932349720518152162</id><published>2008-04-21T12:00:00.001-07:00</published><updated>2008-04-21T22:20:43.174-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Slicehost'/><category scheme='http://www.blogger.com/atom/ns#' term='MovableType'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><category scheme='http://www.blogger.com/atom/ns#' term='WordPress'/><title type='text'>Movable Type 4 Setup on Ubuntu</title><content type='html'>I am in the process of consolidating my blogs to a single system, and in doing so, am switching to &lt;a href="http://movabletype.com"&gt;Movable Type&lt;/a&gt;.  This blog will eventually move, but the initial impetus was for some other blogs that were running on WordPress where I was having some problems (and spent way too much time trying to fix that - one of the key things I don't want to be doing with my blog system).  But, in relation, I found the setup instructions for Movable Type a bit lacking, especially in relation to using multiple blogs, and how this works in terms of Apache and MT setup.  &lt;br /&gt;&lt;br /&gt;I also want to say a bit thanks to &lt;a href="http://duncandavidson.com/"&gt;Duncan&lt;/a&gt; for showing me his Apache config, and some brief discussion of multiple blogs with MT.  The MT docs were really lacking here as said, but Duncan's knowledge made it clear this was pretty easy and a nice way to go.  Thanks Duncan, and check out his blog and site, and of course all &lt;a href="http://flickr.com/photos/x180"&gt;his great pics on Flickr&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I am using a single installation of Movable Type, supporting multiple blogs, with each blog having their own domain name, and that blog (or really the MT content) living at the root of that domain name (this last part isn't required/essentially for this tutorial, you can easily tweak the Apache config). &lt;br /&gt;&lt;br /&gt;So, with that, given that it actually turns out to be relatively simple to set up once you know a few key bits, I figured I'd pass along what I did...&lt;br /&gt;&lt;br /&gt;First, I created my standard Ubuntu slice at Slicehost.  I host everything with them these days, and as such, I have a base system image that I've built for myself.  It's built with their standard Ubuntu 7.10 choice, and then I make tweaks to the SSH setup, add a few bits I need, etc.  But, I believe you could simply take pretty much a standard Ubuntu server install and use that.  Please let me know if this guide doesn't work for you in that case.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Preparations&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;In preparation for the move, while my existing blogs were running, I exported their data from WordPress using WordPress' Export feature, which produces a WXR file.  Save that to my local machine.&lt;br /&gt;&lt;br /&gt;I also made sure I had my domain names secured, and the DNS for them setup.  In particular, one thing to note is that Movable Type is sort of a two part system.  You have the MT web application, which is a publishing application, but is not what someone hits when visiting your blog(s).  MT publishes your blog out as static content (or that's the default option anyway).  So, I setup an "mt" subdomain on one of my domains where I will access MT (more on that below).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Apache and Perl Install&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Apache 2 and mod_perl were not on my system by default, so I needed to install those. This amounts to:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;sudo apt-get install apache2 libapache2-mod-perl2 libapache2-mod-perl2-doc&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The above will not only install it, but configure mod_perl for use in Apache, and you can now run Perl based web apps (MT is developed in Perl).  Also, depending on how you want to do email, you may need to install Perl's Mail::Sendmail (if using SMTP; if you use sendmail, then you can choose that when setting up MT):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;sudo perl -MCPAN -e "install Mail::Sendmail"&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Create a Database&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;I created a database for MT using MySQL.  I also setup a specific MySQL user, password, and assigned them rights to that database.  You'll need this info later when setting up/configuring MT.  &lt;br /&gt;&lt;br /&gt;I have been using &lt;a href="http://www.navicat.com/"&gt;Navicat&lt;/a&gt; for nearly all my DB management.  It works really well given it can do SSH tunneling as I don't open the MySQL port on my servers, etc.  It is a commercial app, but as a developer who works with DB's often, has proven to be my tool of choice (I've tried many others, and this is the one that's worked best for me).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Apache Configuration&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;I have a relatively minimal Apache configuration file.  The bulk of it is done with a file that sets up my virtual hosts (several domains point to a single machine).  The setup for MT has a few critical pieces:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Setting a &lt;code&gt;ScriptAlias&lt;/code&gt; for the "mt" directory, so mod_perl knows to execute .cgi files there.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Setting an &lt;code&gt;Alias&lt;/code&gt; for the "mt-static" directory, which is MT's static content, and which you'll want to be referenced from all your blogs.  You can also do this with a symlink, but I've done it with an Apache alias below so that I don't have to worry about a given blog's static content getting wiped out and breaking this (if the static content gets wiped out, you can just republish in MT to restore it, so I prefer to keep that purely maintained by MT).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Setup the proper options/settings for the MT directory.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Thus, my configuration for my virtual hosts looks like the following (fake domain names used), notes following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;NameVirtualHost *&lt;br /&gt;&amp;lt;VirtualHost *&amp;gt;&lt;br /&gt;        ServerAdmin chris@example.com&lt;br /&gt;        ServerName mt.example.net&lt;br /&gt;        DocumentRoot /var/www/mt&lt;br /&gt;&lt;br /&gt;        Alias /mt-static /var/www/mt/mt-static&lt;br /&gt;        &amp;lt;Directory /var/www/mt/mt-static&amp;gt;&lt;br /&gt;                Options Indexes FollowSymLinks MultiViews&lt;br /&gt;                AllowOverride All&lt;br /&gt;                Order allow,deny&lt;br /&gt;                allow from all&lt;br /&gt;        &amp;lt;/Directory&amp;gt;&lt;br /&gt;&lt;br /&gt;        ScriptAlias / /var/www/mt/&lt;br /&gt;        &amp;lt;Directory /var/www/mt&amp;gt;&lt;br /&gt;                AllowOverride None&lt;br /&gt;                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch&lt;br /&gt;                Order allow,deny&lt;br /&gt;                Allow from all&lt;br /&gt;        &amp;lt;/Directory&amp;gt;&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;VirtualHost *&amp;gt;&lt;br /&gt;        ServerAdmin chris@example.com&lt;br /&gt;        ServerName example.com&lt;br /&gt;        ServerAlias example.com www. example.com&lt;br /&gt;        DocumentRoot /var/www/example&lt;br /&gt;&lt;br /&gt;        Alias /mt-static /var/www/mt/mt-static&lt;br /&gt;        &amp;lt;Directory /var/www/mt/mt-static&amp;gt;&lt;br /&gt;                Options Indexes FollowSymLinks MultiViews&lt;br /&gt;                AllowOverride All&lt;br /&gt;                Order allow,deny&lt;br /&gt;                allow from all&lt;br /&gt;        &amp;lt;/Directory&amp;gt;&lt;br /&gt;        Redirect /mt.cgi http://mt.example.net/mt.cgi&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The first VirtualHost block sets up where I'll access MT, thus at http://mt.example.com.   There you will see both the &lt;code&gt;Alias&lt;/code&gt; for mt-static, and also the &lt;code&gt;ScriptAlias&lt;/code&gt; for mt.  These are critical.&lt;br /&gt;&lt;br /&gt;The second Virtual Host block defines one of the actual blogs, which will be accessible at http://example.com or http://www.example.com.  For additional blogs, you would add another of these blocks per domain name.  The key bits here are the &lt;code&gt;DocumentRoot&lt;/code&gt; and the &lt;code&gt;Alias&lt;/code&gt; for mt-static.  The &lt;code&gt;DocumentRoot&lt;/code&gt; is where you will have MT publish your static blog content.  Make sure that directory is writable by Apache/MT.&lt;br /&gt;&lt;br /&gt;Finally, the &lt;code&gt;Redirect&lt;/code&gt; sets things up so that when you are logged in and visit your blog, and see the various links for "Edit this content" that those will actually work (they point to mt.cgi, so this redirects them to whatever domain is serving mt).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Setup Movable Type&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Next, visit http://mt.example.com/mt.cgi in your browser to begin setting up and configurating Movable Type.  It will ask you about your database, and a few other bits, and then prompt you to create the first blog.  Make sure the blog URL and directory match what you setup in your Apache configuration above.  Beyond this you will need to refer to Movable Type docs for questions.  But, you should essentially have a blog running, and will just need to Publish it to have MT write the static files into the directory you've defined.&lt;br /&gt;&lt;br /&gt;The last step for me was to import my blog content from my prior WordPress setup, using the WXR dump I created at the beginning of all this.  One key note here.  When you go into MT's Import page - choose the blog you want to import to (even if you only have one) first.  Only then when you pick WXR (if appropriate) for your import will it give you the proper fields for the info it needs for the WXR import.  Otherwise it'll set your import type back to MovableType, and claim it has read in your import file fine (but you'll of course have no content).&lt;br /&gt;&lt;br /&gt;I'm still tweaking my templates and doing a few bits to the sites I'm moving over, so I'm off to continue on that.  Hope this helps someone.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-932349720518152162?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/932349720518152162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=932349720518152162' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/932349720518152162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/932349720518152162'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/04/movable-type-4-setup-on-ubuntu.html' title='Movable Type 4 Setup on Ubuntu'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-3378455250548970450</id><published>2008-04-16T11:13:00.001-07:00</published><updated>2008-04-16T11:13:12.565-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='startup'/><category scheme='http://www.blogger.com/atom/ns#' term='Office'/><category scheme='http://www.blogger.com/atom/ns#' term='consulting'/><title type='text'>Working at Home, The Zone, and Importance of Equipment</title><content type='html'>Recently, there was a good writeup at &lt;a href="http://hivelogic.com"&gt;Hivelogic&lt;/a&gt; on &lt;a href="http://hivelogic.com/articles/2008/03/offices-and-the-zone"&gt;Offices and the Creativity Zone&lt;/a&gt;.  This is partially also in response to the Jason Calcanas' post on &lt;a href="http://www.calacanis.com/2008/03/07/how-to-save-money-running-a-startup-17-really-good-tips/"&gt;how to save money&lt;/a&gt;, &lt;a href="http://www.37signals.com/svn/posts/902-fire-the-workaholics"&gt;37 Signals response&lt;/a&gt;, and so on.  I'm getting around to my thoughts/response, as someone who has been working at home for about 60% of the last 10 years.&lt;br /&gt;&lt;br /&gt;I'd like to comment on/respond to a few things, in particular:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;chairs and desks&lt;/li&gt;&lt;br /&gt;&lt;li&gt;pair programming&lt;/li&gt;&lt;br /&gt;&lt;li&gt;"The Creativity Zone", as well as working in coffee shops&lt;/li&gt;&lt;br /&gt;&lt;li&gt;what I think is important for a home office -  and in working at home&lt;/li&gt;&lt;br /&gt;&lt;li&gt;passion for your work, and the relation of that and hours put in at startups&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Chairs and Desks&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;First, chairs and desks.  As most folks will say, do NOT skimp on a chair.  Go straight to a Herman Miller Aeron, or a Human Scale chair, do not pass go.  I'll wait.  I've had my posterior in an Aeron since I started at Adobe (thank you Adobe!) in 1996.  When I moved, and was no longer working in the office, I used their program that allowed employees to buy these chairs at a discount, and picked one up for $500.  I'd have gladly paid full price.  Additionally, make sure you get the proper size, it makes a huge difference!&lt;br /&gt;&lt;br /&gt;Following on that, I completely disagree on getting cheap desks, or doing the door/board on top of a file cabinet approach mentioned in Calcanas' post.  I don't think you need to spend a lot on a desk, afterall, you just need a good surface.  However, the key here is getting a desk that is the proper height.  If you do the file cabinets thing, or buy your average stock desk they are almost always too tall.  Take it from me, I'm 6'2" tall, and these desks are still too tall if you properly set your chair height (thighs level, feet flat on ground, forearms level or close to it, etc.).  So, I suggest finding adjustable height desks, or if you are building your own, to make sure you figure out the proper height.  I've been using Anthro's &lt;a href="http://anthrocart.com/ppage.aspx?pmid=32"&gt;AnthroBench&lt;/a&gt; desks, which are not cheap, but are kick ass.  However, the height adjustment is non-trivial, so you mostly have to get it right the first time.  I've seen some since, that consumers can buy, that have more of an infinite height adjustment (which is what we had with the desks at Adobe, but I was unable to buy those).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Pair Programming&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;I'll cut to the chase: I'm not into it.  I know folks who are and swear by it (e.g. &lt;a href="http://pivotallabs.com/"&gt;Pivotal Labs&lt;/a&gt; does it the most and best I've ever seen).  But, it's not for me.  It doesn't fit with the way I think and work.  I like a personalized environment, I like things quiet, and I like a bit more free flow.  I also don't feel that it is a guarantee of better code quality.  &lt;br /&gt;&lt;br /&gt;Some of the complications to me are all the personalization developers like to do, whether that be fonts, keyboards, screen arrangements, colors, coding styles, and so on.  Some of that can be worked around, but I'm simply not a fan, and don't believe it's the big advantage various others believe it is.  But, in the same note, if it works for you, you prefer it, and you find someone/people to pair with that works well, then more power to you.&lt;br /&gt;&lt;br /&gt;Also, I have a long history of doing remote work, working with other remote folks, and so on, and that is either impossible, or mostly defeats pair programming (Pivotal may disagree, but I do know they've had some hardships in this area as well).  Differing time zones are not friendly to pair programming.&lt;br /&gt;&lt;br /&gt;All this also ties into the next topic...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Creativity Zone&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;I think Hivelogic nails it with this:&lt;br /&gt;&lt;blockquote&gt;Unfortunately, most people can’t simply step into The Zone. In the very same way you’d want to find the right time and place to read a book, creative types need to setup the specific conditions they need to enter The Zone. For some people, this might mean listening to a certain kind of music. It might be fueled by caffeine and a dark room late at night. Some people work best in the silence of the early morning. It all depends on the person.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;As you can guess from my pair programming comments above, I agree about having the right environment, and that you can't just force the work to flow.  I've worked with a lot of different folks.  Some people like to listen to music, some don't.  Those that do range from listening to classical on low volumn to high volumn metal.  Some work at night best, others can do the 9-5 thing, etc.  This to me is similar to the situation of working in a cafe.&lt;br /&gt;&lt;br /&gt;I think working in cafes is not good.  I'm ok with popping in for an espresso, having a casual meeting there, or just using it to take a break from the office (whether that be a company office, or home office), and just checking email or reading RSS, or what not.  But I don't buy it for serious work, and secondarily, I think you people who do do that suck.  Yep, straight up, you suck.  You go into a coffee shop, and take up space, and then ignore everyone.  Why are you there?  And why do you think that's fair?  You are in no way contributing to the "cafe culture" or environment of a cafe, you are detracting from it.  I was glad to see Ritual take away outlets and such.  You shouldn't be sitting there for hours on end leeching from them.&lt;br /&gt;&lt;br /&gt;And furthermore, I simply don't buy it as a productive environment, even when you wall yourself off from what is around you - which by definition tells me you don't think it's a productive environment either, otherwise you wouldn't need to bring your headphones and ignore everyone and all that.&lt;br /&gt;&lt;br /&gt;Instead, make yourself a nice home office.  There are a ton of resources on the web on how to do this if you need some pointers.  Which leads me to...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What's Important in a Home Office - And In Working at Home&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;The above referenced articles already cover some of this, I'll try to be brief.  Bring on the bullets:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Great chair and desk, see above&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Proper lighting.  In this I mean both the actual lights, but also how windows affect your workspace.  Do not face directly into a window, as much as the view may be awesome.  Usually you want windows on the side of you (not in front or back).  I have a nice forest, mostly, to look out on my left side window - easy enough when I need a break to just turn my head.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A separate room.  Not everyone can do this, but I feel VERY strongly about this if you plan to do significant amounts of work at home.  You need a space that you can go to that is your office, where you can make a shift into work mode, have some isolation, close doors (so phone calls are quiet and so you can work without distraction), etc.  It doesn't have to be huge, but make it your office space.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Good machine and monitor(s).  Big monitors are key.  I use a MacBook Pro as my main machine, but have an external 24" monitor (I want to go to a 30" when I can) on it as well, and an external keyboard is good too.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I feel you shouldn't have a beverage bar in your office.  Just keep it in the kitchen, save electricity or whatever.  But, for me, this is a good way to force me to get up and walk a bit, allows some different thinking time, etc.  I almost always have a glass of water on my desk, but I get up to make an espresso, or maybe grab some fruit, or whatever.  The break is always good.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Ok, I used to laugh at this recommendation, but I'm now one who does it, although I don't think it's required...  Get up, and take a shower, get dressed, etc.  I mention this for the two reasons I need to do it (but if you don't, then no biggy): I am not a morning person.  I need to wake up a bit slower, and I prefer less interaction with people when I first get up.  So, for me, what I've found is great, is to get up, and go shower.  It is my way of having a slower re-entry.  But, it also helps shift me into work mode (even if I don't wind up "going to work" for another hour or two.  It flips that switch more explicitly for me.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;That's all for now, as I want to get on to the last point...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Passion&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;In some of the referenced articles, and this has grown to be discussed a lot in reference to these, there is mention of whether folks need to be work-a-holics to have a successful startup.  37 Signals says to fire them.  Calcanas mostly the opposite.  I'm very strongly in the 37 Signals camp on this - to me it all comes down to passion.  I believe this beyond startups as well, and it's one reason I just have no interest in working for larger companies anymore, because I feel the logistics simply make it a lot harder to have everyone be passionate.  But, in the end, the folks I want to work with are passionate about their work/the project.  This is how I want to be with what I'm working on.  Sure, there are always parts that aren't as fun, but the overall idea is to have an overarching passion for what you're doing.  To me that produces the best result, regardless of actual hours worked.  In fact, I'd argue that you will get FAR better results from passionate folks working moderate hours, than simply a box of people putting in massive hours.  &lt;br /&gt;&lt;br /&gt;I recall we used to joke about how there was this notion that at Oracle (or substitute various others), all the engineers worked 80 hour weeks.  That was BS of course.  Note, I haven't worked at Oracle, but know folks who did, although that is somewhat beside the point...  They may have been at the office 80 hours a week, but there is no way they were productively cranking out great work for all 80 hours.  No, they were going to the gym, eating in the cafes, goofing off, or half awake at the keyboard.  Recipe for burnout.&lt;br /&gt;&lt;br /&gt;Now, as long as you have the passion, that's the key to me.  After that, if you want to put in some epic hours because you're so psyched to be moving some great project forward, that's cool.  I've done it.  I don't think it's something that's sustainable long term, but bursts of this are great, go for it.&lt;br /&gt;&lt;br /&gt;Right now, to share a bit, I'm making less money than I have in a long long time, but I'm more psyched than I probably ever have been, on the work I'm doing.  I'm hoping the money part changes as the startups I'm working on grow, but I'm just loving it.  Working with others who are passionate, working on cool stuff, running the show myself, or being involved at fundamental levels is why I left the mothership, and I really just wish I'd left sooner.  &lt;em&gt;I can get into that Creative Zone every day, and I look forward to doing so!&lt;/em&gt;  &lt;br /&gt;&lt;br /&gt;So, I recommend you think hard about your work environment, how you make for a productive and enjoyable environment.  But most of all, shoot for the passion, and mold your environment to support and foster that passion.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-3378455250548970450?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/3378455250548970450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=3378455250548970450' title='23 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3378455250548970450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3378455250548970450'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/04/working-at-home-zone-and-importance-of.html' title='Working at Home, The Zone, and Importance of Equipment'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>23</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-2485263416985726414</id><published>2008-04-11T12:32:00.001-07:00</published><updated>2008-04-11T12:32:57.229-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Shoulda and object_daddy Sitting in a Tree, t-e-s-t-i-n-g</title><content type='html'>Like some other folks working with Rails, I've been a bit frustrated with Fixtures.  Foxy Fixtures, Rathole, and such things, including what is in Rails 2, have helped a lot.  However, the two biggest frustrations for me come down to the fragility of fixtures, and knowing what fixtures you have and how they relate to their associated fixtures.  I would find myself thinking, "hmm, which user do I use when I want the one with X associations" or what not.  Naming your fixtures well helps, but only so much.&lt;br /&gt;&lt;br /&gt;Lately, I've come across two plugins that I am really loving.  These are &lt;a href="http://www.thoughtbot.com/projects/shoulda"&gt;Shoulda&lt;/a&gt; and object_daddy.  Shoulda seems to be gaining in popularity in the Rails community, which doesn't surprise me.  It gives you some of the best syntax of RSpec, without having to use RSpec (which I am not all in love with, unlike various others), as well as it gives you some nice "should" methods, and other features I'll get into in a minute.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://b.logi.cx/2007/11/26/object-daddy"&gt;object_daddy&lt;/a&gt; I think is rather obscure.  I only found out about it due to Tammer Saleh's presentation (&lt;a href="http://mtnwestrubyconf2008.confreaks.com/12saleh.html"&gt;video link&lt;/a&gt;) on Shoulda from the 2008 MountainWest RubyConf.  object_daddy has &lt;a href="http://b.logi.cx/2008/2/19/object-daddy-updates"&gt;improved&lt;/a&gt; in its short life, and is quite useful today.  What it does, is provide a factory/generator mechanism for creating model objects.  I've done this in the past with object constructors or factories, etc., but object_daddy organizes all this, and provides a slick mechanism, called "exemplars", that specify how model attributes are defined when generating objects, and more importantly, when generating multiple objects.  Tammer covers this issue in his presentation, which I highly recommend watching.&lt;br /&gt;&lt;br /&gt;It's taken me a bit of time/use of Shoulda to get really into it, but like so many things, use it a bit and then the light bulb not only goes off, but seems to erupt with light.  The big one here for me was how to leverage contexts, and by that I really mean nested contexts.  My tests now not only read better, but can be written in a much nicer fashion, as well as organized in a great way.  On the organization front for example, I now often have two top level contexts in a functional test: one for cases where I'm testing actions without a user being logged in, and the other for when a user is logged in.  Great way to group them.  &lt;br /&gt;&lt;br /&gt;But, what's got me most excited lately is the combination of these two testing tools, and what it's done to my tests.  First, I've darn near eliminated fixtures on the project I'm using this most with so far.  This has removed the fragility, as well as it's just FAR easier to understand a test case's setup/scenario.  I use Shoulda's contexts and setup, combined with generated objects from object_daddy to create "scenarios" (to steal the term from the &lt;a href="http://code.google.com/p/fixture-scenarios/"&gt;plugin&lt;/a&gt; that provides this kind of thing for fixtures).  The benefit is that you have all of the info about your test right there in one place in front of you.  You don't need to bounce between likely multiple fixture files and your test code file to ascertain what's being used in your test.  Plus, you can be very specific about the data being used in that particular test (or tests).  &lt;br /&gt;&lt;br /&gt;I heartily recommend you try this out.  Two other things of note:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Shoulda can be mixed in with existing TestUnit.  So, you can slowly convert to it, or just build new tests with it, etc.  Very nice.  And, it doesn't require anything special to run the tests (it really is just a method generator for building TestUnit tests).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Check out Shoulda's "should_eventually" method.  I'm making more and more use of this, as I use a Test First approach.  So, I go in, and build lots of tests, and do a lot of "should_eventually" as I think of things to test and functionality I need, etc.  Then as I determine how to write those tests, and following on from that, write the implementation, you simply remove the "_eventually" and let it rip.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Note, if you are an RSpec fan, you can of course achieve the same as Shoulda for contexts and such (I think anyway), so just pull in object_daddy and leverage that aspect.&lt;br /&gt;&lt;br /&gt;And last, but not least, I've forked object_daddy to make one tiny change (a single line, actually, a single method call name change!) that's made a big difference for me (comments very welcome).  This change is to, by default, call &lt;code&gt;create&lt;/code&gt; in the &lt;code&gt;generate&lt;/code&gt; method that object_daddy adds to your ActiveRecord objects, instead of calling &lt;code&gt;new&lt;/code&gt;.  This avoids what I found to be the common case of doing:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;my_new_object = SomeModel.generate&lt;br /&gt;my_new_object.save&lt;br /&gt;my_new_object  # or some use of it&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now, you can simply call &lt;code&gt;SomeModel.generate&lt;/code&gt;, and use that inline, knowing it's saved in  the DB, etc.  I want to take a look at adding options to generate, or additional generate methods that provide the flexibility to use new, or create! or such things, for the cases where those are needed.  My fork is hosted on GitHub, and is public, so feel free to check it out:  &lt;a href="http://github.com/chris/object_daddy"&gt;http://github.com/chris/object_daddy&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;p.s. For those that wonder why I've "all but eliminated fixtures", as in, what do I still have in fixtures?  The only things are standard data, which in my case amounts to a couple specific users, and a couple of Roles and Permissions.  These normally get setup in the DB migrations, but I'm working through what Rails does when you run tests and it wipes the DB clean (and thus doesn't pick up seed data from migrations), and other such issues.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-2485263416985726414?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/2485263416985726414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=2485263416985726414' title='34 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2485263416985726414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2485263416985726414'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/04/shoulda-and-objectdaddy-sitting-in-tree.html' title='Shoulda and object_daddy Sitting in a Tree, t-e-s-t-i-n-g'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>34</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-8623692472471078481</id><published>2008-04-07T21:09:00.001-07:00</published><updated>2009-07-28T15:46:44.756-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CruiseControl'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ContinuousIntegration'/><title type='text'>Setting up CruiseControl.rb with/for Git Based Projects</title><content type='html'>&lt;p&gt;&lt;em&gt;[Updated to refer to official ThoughtWorks CC.rb Git repo.]&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I have a new Rails project I'm working on and I use Git/GitHub for source control.  It was time to setup continuous integration, and my usual weapon of choice for that is CruiseControl.rb.  Here's what I did to get my project setup under &lt;a href="http://github.com/thoughtworks/cruisecontrol.rb/tree/master"&gt;CruiseControl.rb with Git&lt;/a&gt;, on an Ubuntu 7.10 machine...&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Setup for accessing GitHub repo&lt;/h3&gt;&lt;br /&gt;All I needed to do here was generate an SSH key for my account on the host machine, and then add that key to the allowed keys for my GitHub account.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Prerequisites&lt;/h3&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;I setup a builder@mydomain.com email address which will get used by CruiseControl for sending build related emails/notifications.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You'll need to determine a port you want CruiseControl to run on, and your strategy for accessing it.  For example, I run mine on a port other than port 80, and other than the default 3333.  I then proxy that via Nginx, and also use Nginx to password protect access to it (since this is not a public project, etc.  This will affect the CC dashboard URL setting specified below.  Some notes on this:&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;I did my initial Nginx configuration using &lt;a href="http://errtheblog.com/posts/52-nginx-config-like-whoa"&gt;err's Nginx config generator&lt;/a&gt;.  However, this makes a lot of path assumptions, and various other things, so you'll definitely want to go through the resulting file closely.  I had a few sites on this server, so it was relatively useful to use this as a base starting point, and then just fix up paths to the access and error logs, and the PID file.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Here's a quicky on &lt;a href="http://brunomiranda.com/past/2007/10/29/password_protect_a_folder_in/"&gt;how to add password protection&lt;/a&gt; to an Nginx server (and a specific location).&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Install CruiseControl and Do Site Configuration&lt;/h3&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Cloned the Git version of CruiseControl.rb in location I wanted it (you could also simply download it and expand the tarball): &lt;code&gt;git clone git://github.com/benburkert/cruisecontrolrb.git&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The DEPENDENCIES file indicated I needed to have the grit and mime-types gems, so installed those.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Where your projects get stored for CruiseControl.rb is now defined by the &lt;code&gt;CRUISE_DATA_ROOT&lt;/code&gt; environment variable, and if you don't set this, it defaults to &lt;code&gt;$HOME/.cruise&lt;/code&gt;.  I personally changed this to be &lt;code&gt;/var/cruisecontrolrb&lt;/code&gt;.&lt;br /&gt;&lt;li&gt;Edit the &lt;code&gt;config/site_configuration.rb&lt;/code&gt; (probably need to rename the example version accordingly) to set site-wide settings, such as your email config and so on. &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;For email setup, I use Gmail for domains, so I have a block like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;ActionMailer::Base.smtp_settings = {&lt;br /&gt;  :address =&gt;        "smtp.gmail.com",&lt;br /&gt;  :port =&gt;           587,&lt;br /&gt;  :domain =&gt;         "mydomain.com",&lt;br /&gt;  :authentication =&gt; :plain,&lt;br /&gt;  :user_name =&gt;      "builder@ mydomain.com",&lt;br /&gt;  :password =&gt;       "password"&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You'll want to specify the &lt;code&gt;Configuration.dashboard_url&lt;/code&gt; setting so URL's work properly.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;There are a variety of other settings available in the file that you may want to tweak.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Add Project and Configure&lt;/h3&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Did the usual usual &lt;code&gt;cruise add&lt;/code&gt; command to add my project, but with the Git variant: &lt;code&gt;./cruise add MyProjectName --git-url git@github.com:mylogin/myproject.git&lt;/code&gt; (modify the Git project URL for your Git repo of course).  Note that you can see all the options by doing a &lt;code&gt;./cruise add&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Create the test database for your project.  The easiest way is just to go into &lt;code&gt;$CRUISE_DATA_ROOT/projects/MyProjectName/work&lt;/code&gt; and do a &lt;code&gt;rake db:create RAILS_ENV=test&lt;/code&gt;.  Your first build will have already failed because this hasn't been made, this step hopefully fixes that.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If your log directory isn't in Git, you'll need to go mkdir it, so something like:&lt;code&gt;mkdir $CRUISE_DATA_ROOT/projects/MyProjectName/work/log&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Setup CruiseControl.rb Service/Daemon&lt;/h3&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Copy the &lt;code&gt;&lt;a href="http://gist.github.com/157741"&gt;cruisecontrolrb&lt;/a&gt;&lt;/code&gt; file into &lt;code&gt;/etc/init.d&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I set the port for CruiseControl.rb to run on in the above /etc/init.d/cruisecontrolrb daemon file, by adding "--port 1234" (for example) to the DAEMON_ARGS variable.&lt;br /&gt;&lt;li&gt;Start the CruiseControl.rb daemon as appropriate for your system (e.g. "sudo /etc/init.d/cruisecontrolrb start").&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Finally, surf to your cc.rb site on the web and see how your build has done.  If you run into build problems, you'll want to look at the cc.rb build logs (if it was your project test/build that failed) which are in the &lt;code&gt;$CRUISE_DATA_ROOT/projects/MyProjectName&lt;/code&gt; directory (or rather, the subdirectory in there for the particular build).  And Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-8623692472471078481?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/8623692472471078481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=8623692472471078481' title='28 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8623692472471078481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8623692472471078481'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/04/setting-up-cruisecontrolrb-withfor-git.html' title='Setting up CruiseControl.rb with/for Git Based Projects'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>28</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-115657935879448437</id><published>2008-03-24T20:22:00.001-07:00</published><updated>2008-03-24T20:22:54.123-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='coffee'/><category scheme='http://www.blogger.com/atom/ns#' term='Espresso'/><category scheme='http://www.blogger.com/atom/ns#' term='cooking'/><category scheme='http://www.blogger.com/atom/ns#' term='recipes'/><category scheme='http://www.blogger.com/atom/ns#' term='food'/><title type='text'>Steak and Chard</title><content type='html'>My wife is visiting friends with the kids this week, during my daughter's first week of spring break.  I'm home doing a lot of work, but it's also a real rarity that I'm home when I'm away from my family (usually it's me who's traveling).  Anyway, I'm definitely doing some cooking, as well as will investigate one or two "sketchy" Mexican taco places (I scout them out, and then take the fam if good :)  They're sketchy in appearance (hopefully not in food).  But, for me, the sketchier, usually means the better.  But I digress...&lt;br /&gt;&lt;br /&gt;Tonight I made probably the best steak I've made in a long time, definitely one of my best ever.  Not a new recipe, but just perfectly executed, if I do say so myself.  Combined with it was an experiment with chard; recipe of my own on-the-fly creation.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Steak&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;First I went and got an absolutely top quality ribeye from my local meat market (&lt;a href="http://longsmeatmarket.com/"&gt;Long's&lt;/a&gt;, here in Eugene).  A Roughly 1lb beauty.  Then I ground up some fresh &lt;a href="http://www.bluebottlecoffee.net/"&gt;Blue Bottle&lt;/a&gt; Roman Espresso coffee (ground at a setting approx between drip and French Press, so on the course side, but not huge chunks).  It is absolutely key to use fresh coffee beans, and grind them, none of this canned or pre-ground crap.  Also, the better the coffee, the better the result.  I could go on a long time here, but I won't (because I'm working on a blog entry about Blue Bottle :)  Next, combine that with a pinch or three of either kosher salt or Fleur de Sel or similar salt of your choice.  And then, add fresh ground pepper to the mix - about 1/3rd as much as you have coffee (more or less to taste I suppose - but don't put so much that you drown out the coffee).  Liberally coat your steak with that - hide the steak in it.&lt;br /&gt;&lt;br /&gt;I then recommend grilling the steak over a very hot grill.  I use a gas BBQ, with my burners all on high - about 500 degrees on average.  For the thickness of steak I had tonight (1.25"?), I cooked it just short of 11 minutes - about 5 minutes a side or so.  This yields a medium-rare steak, and I mean truly medium-RARE, plenty of pink, but not bleeding.  Once done grilling, pull it off and let it rest a few minutes.  Stellar.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Chard&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I'm a big fan of chard, usually sautéed.  Tonight I had some organic red chard.  At Long's I'd also picked up some prosciutto, although a last minute decision to try something new, yielded some green peppercorn infused prosciutto cotto (cooked).  First I sautéed some chopped red onion, with a pinch of Napa herbs, fresh ground pepper, and a bit of the helpful chunky grey garlic sea salt (go light here, this is not a garlic thing).  A bit of red wine (a bottle I had open, oddly enough a tempranillo-syrah blend).  Saute and fry that prosciutto up a bit.&lt;br /&gt;&lt;br /&gt;Next, I separated the stalks from the chard, as they need to cook longer.  Toss those in with the above mixture and steam/saute a bit to soften the stalks up.  Then, put the chard leaves in, and essentially steam until done.  Doesn't take long.  Given that I made this up while I was cooking it, it worked out really well.  Of course, most things with prosciutto do :)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Drink&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I went with the easy choice here, although unexpected.  I think most people would expect a nice bold red wine, and I do have some nice ones in the wine fridge.  But, when I'm alone and not at a restaurant (thus not opening a bottle, or ordering by the glass) I'll go with a cocktail.  My standard favorite is gin rocks with onions.  Tonight this was &lt;a href="http://www.zuidam.com/"&gt;Zuidam&lt;/a&gt; dry gin (battling for top spot with my usual favorite &lt;a href="http://www.tanqueray.com/en-us/World%20of%20Tanqueray%20Products/No.%20Ten%20by%20Tanqueray"&gt;No. Ten by Tanqueray&lt;/a&gt;), and the best cocktail onions, &lt;a href="http://www.sableandrosenfeld.com/product/cocktail_garnishes.html"&gt;Sable and Rosenfeld Tipsy Onions&lt;/a&gt;.  I prefer my gin over just a couple large cubes of ice, so that it's not so cold as to take away flavor.  Good botanical gin has a myriad of wonderful flavors, and I think shaking it with ice just kills some of that - No Ten is FAR better just slightly cooled over a couple cubes of ice.&lt;br /&gt;&lt;br /&gt;All this, while listening to some great jazz (not typical for me, but "completed" the evening), and sitting at the bar-counter in our house.  I felt like I was in a great restaurant, eating a wonderful meal at the bar, only it was in the comfort of my own home, relaxing, and loving it.  I guess it was my own great restaurant; how nice!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-115657935879448437?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/115657935879448437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=115657935879448437' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/115657935879448437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/115657935879448437'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/03/steak-and-chard.html' title='Steak and Chard'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-3967677574019596245</id><published>2008-03-20T09:50:00.001-07:00</published><updated>2008-03-20T09:50:13.382-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='Sparkle'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyCocoa'/><title type='text'>Creating Sparkle Appcast via Rake Tasks</title><content type='html'>I have a RubyCocoa application that self-updates using &lt;a href="http://sparkle.andymatuschak.org/"&gt;Sparkle&lt;/a&gt;.  To do so, you need to create an "appcast" file which contains the version and download information for your application, as well as creating the zip file that holds your app.  Then, you of course have to upload this to the server and location that you have specified in the &lt;code&gt;SUFeedURL&lt;/code&gt; key value in your Info.plist file of your app.  For general instructions on using Sparkle and setting it up, see their &lt;a href="http://sparkle.andymatuschak.org/wiki/Documentation/Basics"&gt;Basic Instructions&lt;/a&gt; page.&lt;br /&gt;&lt;br /&gt;My Rake tasks do not create the zip file.  I may enhance it to do this at some point, but so far I haven't needed to, and have had cases where I need to create it myself for various reasons.  What the tasks do is to build an appcast.xml file from a YAML file that contains all the necessary information.  Note that the name of my app is "Linker", so you'll see that in various spots.  The tasks do rely on a simple directory structure:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Your app root directory&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Rakefile&lt;/li&gt;&lt;br /&gt;&lt;li&gt;appcast&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;version_info.yml&lt;/li&gt;&lt;br /&gt;&lt;li&gt;build&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Your app zip files go here (e.g. Linker_0.8.zip, Linker_0.9.zip, etc.)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Rake task will create the linker_appcast.xml file here&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;So, you have a spot you drop your zip files into, and this same dir is where the Rake tasks create the appcast file.  The version_info.yml file is where you put the info needed to generate the appcast.  It looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;linker-04:&lt;br /&gt;  title: Linker 0.4&lt;br /&gt;  filename: Linker_0.4.zip&lt;br /&gt;  description: Added Sparkle updating mechanism.&lt;br /&gt;&lt;br /&gt;linker-05:&lt;br /&gt;  title: Linker 0.5&lt;br /&gt;  filename: Linker_0.5.zip&lt;br /&gt;  description: Added help (see Help menu).  Added bookmarklet support/custom URL protocol handling.  See the new help for information on how to use the bookmarklet.&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note that you can put HTML into the "description" field, and my Rake task will deal with and preserve that.  &lt;br /&gt;&lt;br /&gt;Finally, I have two Rake tasks, one for building the appcast, and the other for uploading it and the latest zip file to the server.  These each are simply one liners that call a parallel Ruby method within the Rakefile:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;namespace :appcast do&lt;br /&gt;  desc "Create/update the appcast file"&lt;br /&gt;  task :build do&lt;br /&gt;    make_appcast&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  desc "Upload the appcast file to the server"&lt;br /&gt;  task :upload do&lt;br /&gt;    upload_appcast&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The two methods rely on you defining a couple of variables in your Rakefile, adjust these as desired:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;APPCAST_SERVER        = 'your_appcast_server.com'&lt;br /&gt;APPCAST_URL           = "http://#{APPCAST_SERVER}"&lt;br /&gt;APPCAST_FILENAME      = 'linker_appcast.xml'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here are the methods, first the one that builds the appcast, which you'll need to modify for your app:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;def make_appcast&lt;br /&gt;  begin&lt;br /&gt;    versions = YAML.load_file("appcast/version_info.yml")&lt;br /&gt;  rescue Exception =&gt; e&lt;br /&gt;    raise StandardError, "appcast/version_info.yml could not be loaded: #{e.message}"&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  appcast = File.open("appcast/build/#{APPCAST_FILENAME}", 'w')&lt;br /&gt;&lt;br /&gt;  xml = Builder::XmlMarkup.new(:target =&gt; appcast, :indent =&gt; 2)&lt;br /&gt;&lt;br /&gt;  xml.instruct!&lt;br /&gt;  xml.rss('xmlns:atom' =&gt; "http://www.w3.org/2005/Atom",&lt;br /&gt;          'xmlns:sparkle' =&gt; "http://www.andymatuschak.org/xml-namespaces/sparkle", &lt;br /&gt;          :version =&gt; "2.0") do&lt;br /&gt;    xml.channel do&lt;br /&gt;      xml.title('BWA Linker')&lt;br /&gt;      xml.link(APPCAST_URL)&lt;br /&gt;      xml.description('Linker app updates')&lt;br /&gt;      xml.language('en')&lt;br /&gt;      xml.pubDate(Time.now.rfc822)&lt;br /&gt;      xml.lastBuildDate(Time.now.rfc822)&lt;br /&gt;      xml.atom(:link, :href =&gt; "#{APPCAST_URL}/#{APPCAST_FILENAME}", &lt;br /&gt;               :rel =&gt; "self", :type =&gt; "application/rss+xml")&lt;br /&gt;&lt;br /&gt;      versions.each do |version|&lt;br /&gt;        guid = version.first&lt;br /&gt;        items = version[1]&lt;br /&gt;        file = "appcast/build/#{items['filename']}"&lt;br /&gt;        &lt;br /&gt;        xml.item do&lt;br /&gt;          xml.title(items['title'])&lt;br /&gt;          xml.description { xml &lt;&lt; "&lt;![CDATA[#{items['description']}]]&amp;gt;" }&lt;br /&gt;          xml.pubDate(File.mtime(file))&lt;br /&gt;          xml.enclosure(:url =&gt; "#{APPCAST_URL}/#{items['filename']}", &lt;br /&gt;                        :length =&gt; "#{File.size(file)}", :type =&gt; "application/zip")&lt;br /&gt;          xml.guid(guid, :isPermaLink =&gt; "false")&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Looking through that above, you'll want to modify the title and description at least.  Now on to the uploader method:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;def upload_appcast&lt;br /&gt;  remote_dir = "/var/www/apps/bwa/shared/public/updaters/"&lt;br /&gt;&lt;br /&gt;  Net::SSH.start( APPCAST_SERVER, 'deploy' ) do |session|&lt;br /&gt;    cwd = Dir.pwd&lt;br /&gt;    Dir.chdir('appcast/build')&lt;br /&gt;&lt;br /&gt;    shell = session.shell.sync&lt;br /&gt;&lt;br /&gt;    begin&lt;br /&gt;      out = shell.cd remote_dir&lt;br /&gt;      raise "Failed to change to proper remote directory." unless out.status == 0  &lt;br /&gt;&lt;br /&gt;      out = shell.ls("-1")&lt;br /&gt;      raise "Failed to get directory listing." unless out.status == 0&lt;br /&gt;&lt;br /&gt;      files = Array.new&lt;br /&gt;      out.stdout.each { |file| files &lt;&lt; file.strip }&lt;br /&gt;&lt;br /&gt;      # Look through the list of files and see what we need to upload, as &lt;br /&gt;      # compared to what we have locally - but always upload the appcast itself&lt;br /&gt;      local_files = Dir.glob('*')&lt;br /&gt;      files.delete(APPCAST_FILENAME)  # we always upload this&lt;br /&gt;      local_files.each do |local_file|&lt;br /&gt;        unless files.include?(local_file)&lt;br /&gt;          print "Uploading: #{local_file}... "&lt;br /&gt;          `scp #{local_file} deploy@#{APPCAST_SERVER}:#{remote_dir}`&lt;br /&gt;          puts $?.exitstatus == 0 ? "done." : "FAILED!"&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    rescue =&gt; e&lt;br /&gt;      puts "Failed: #{e.message}"&lt;br /&gt;    ensure&lt;br /&gt;      Dir.chdir(cwd)&lt;br /&gt;      shell.exit  &lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;You will of course want to modify the &lt;code&gt;remote_dir&lt;/code&gt;, and the login credentials towards the bottom (where it does the &lt;code&gt;scp&lt;/code&gt; command).  This also relies on you having your SSH keys set up, so you don't have to enter a password when it does the scp.&lt;br /&gt;&lt;br /&gt;You could further generalize this obviously, but this is what I have, it works fine, and I haven't needed to extract anything out further.  Posting here as per a request, and hopefully it saves someone else a few minutes.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-3967677574019596245?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/3967677574019596245/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=3967677574019596245' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3967677574019596245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3967677574019596245'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/03/creating-sparkle-appcast-via-rake-tasks.html' title='Creating Sparkle Appcast via Rake Tasks'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7272381794350422053</id><published>2008-03-18T16:56:00.001-07:00</published><updated>2008-03-18T22:42:59.322-07:00</updated><title type='text'>Webcam Recommendations?</title><content type='html'>I setup the site &lt;a href="http://basecampsilverton.com"&gt;Basecamp Silverton&lt;/a&gt; for a friend, and he's wanting to add a webcam to it, to show what the mountain and a bit of town look like at a fairly frequent interval.  He had gotten what looked like a relatively decent web cam - the optics are fairly good for the price, but the thing's software is atrocious and it only does FTP in terms of sending images out (it does provide a live feed, but we're not after that).  So, I'm seeking recommendations.&lt;br /&gt;&lt;br /&gt;What we want is a networked webcam with the following characterisitcs:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;A decent enough lens to point it from his house in town up at the mountains (which are right there - as in less than a mile away).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It should be low cost (preferably under $300, over that will be considered, but there has to be a good reason).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Support SFTP preferably (FTP is ok), as a way to send images at regular intervals from the camera to a server.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;RSS Feed for the images is an acceptable alternative to FTP/SFTP.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Be easy to configure and manage.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;WiFi is ideal, but not required.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Must be configurable from a Mac or a Mac browser (Safari or Firefox).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Multiple mounting options would be good - bolt on, simply sit on a desk/shelf, etc.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;No special networking requirements.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Exported image size of about 500 pixels wide or more.  e.g. something with reasonable size to provide reasonable detail.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Exported images in JPEG, PNG, or GIF.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;&lt;strike&gt;Anyway, let me know your recommendations.&lt;/strike&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;&lt;i&gt;Update: &lt;/i&gt;&lt;/b&gt;It turned out that there was a network configuration issue with the camera we have.  I was luckily able to figure this out within literally 1 minute of logging into the configuration web app for the camera, after Matt opened up a hole in his firewall so I could remotely access the camera.  There still seems to be some problems with the FTP, but this got us closer, and I suspect we'll be staying with this camera afterall.  Of course, don't hesitate to recommend what you like, may be useful later on (and we may do a second camera if this one proves as successful as the demand has indicated so far).&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7272381794350422053?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7272381794350422053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7272381794350422053' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7272381794350422053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7272381794350422053'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/03/webcam-recommendations.html' title='Webcam Recommendations?'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-6802387059034223813</id><published>2008-03-18T10:15:00.001-07:00</published><updated>2008-03-21T10:29:50.958-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Books'/><title type='text'>Tech Books for Free</title><content type='html'>I have some tech books that I will be donating to the local library, unless someone wants any of them.  If you would like one or more of these books, I'm happy to send them to you for the price of shipping.  Click through to the Flickr page and message me, or leave a comment on my blog (make sure you include your email address (which doesn't get published) in your comment, so I can reply.  The books are primarily cover Java and Linux, but also Python, Jabber, Mozilla, Emacs, etc.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/80818705@N00/2343705852" title="View 'Books For Free' on Flickr.com"&gt;&lt;img src="http://static.flickr.com/2260/2343705852_27c63d0508_m.jpg" alt="Books For Free" border="0" width="" height="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Also, not in the picture, but most likely available is, "Object Oriented Perl" by Damian Conway, from Manning Press.  It's on eBay, but doesn't appear it'll sell.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-6802387059034223813?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/6802387059034223813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=6802387059034223813' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6802387059034223813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6802387059034223813'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/03/tech-books-for-free.html' title='Tech Books for Free'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-3855995309489109756</id><published>2008-03-17T21:48:00.001-07:00</published><updated>2008-03-17T21:48:15.811-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Another Reason to NOT Put Seed Data in Rails Migrations</title><content type='html'>I discussed an approach I took recently to getting standard or seed data into your app.  While I've used Migrations quite successfully in the past for this, I am no longer doing so.  And, on an older app, I just got bit by it.  So, here's another reason not to do it...&lt;br /&gt;&lt;br /&gt;Now that I've run into this, it's extremely obvious, but:  If you change model code for a model which is used to create records in previous migrations, you can easily break those prior migrations.  This won't matter when you have existing databases you are migrating, but it will matter if you need to create a database and migrate it from scratch (maybe your Continuous Integration server does that for example, or you are simply setting up a new DB in your development environment).&lt;br /&gt;&lt;br /&gt;For example, the case that bit me was that I recently changed a model, that had some data created by migrations, to specify "acts_as_list".  In doing so, I created a new migration that added the position column - an attribute that gets filled in automatically for your model when you create objects of that type.  However, when recreating the database and running up through the older migrations, the prior seed data failed, since the position column did not yet exist, yet the model's code was trying to populate it.  &lt;br /&gt;&lt;br /&gt;Luckily I was actually adding an administrative interface to managed CRUD and other ops on this particular model, and as part of that, no longer needed the seed data anyway, so was able to just nuke that from the older migrations (and luckily no tests depended on it, and production and staging systems were well past those migrations).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-3855995309489109756?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/3855995309489109756/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=3855995309489109756' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3855995309489109756'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3855995309489109756'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/03/another-reason-to-not-put-seed-data-in.html' title='Another Reason to NOT Put Seed Data in Rails Migrations'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-3980309842319476733</id><published>2008-03-13T11:05:00.001-07:00</published><updated>2008-03-13T11:10:56.781-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Facebooker Publisher and URL Fixes for Rails 1.2.x Use</title><content type='html'>I'm using Facebooker, and specifically the new Publisher class it has, with a Rails 1.2.6 app (hopefully I'll get us on Rails 2 sooner than later).  But, Publisher uses some methods that are only available in Rails 2 it appears, as well as the mechanism it uses to look up Publisher view templates doesn't work properly in Rails 1.2.  Also, link generation doesn't work quite right in all cases, so I have a fix for that too.  Documenting my changes here for my own reference, as well as anyone else it may help.  &lt;br /&gt;&lt;br /&gt;For Publisher, I've made two changes to remedy these issues, both in &lt;code&gt;facebooker/lib/facebooker/rails/publisher.rb&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;In the &lt;code&gt;initialize_template_class&lt;/code&gt; method, change the line:&lt;br /&gt;&lt;pre style="white-space: nowrap;"&gt;&lt;code&gt;returning ActionView::Base.new([template_root,File.join(template_root,self.class.controller_path)], assigns, self) do |template|&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;to instead be:&lt;br /&gt;&lt;pre style="white-space: nowrap;"&gt;&lt;code&gt;returning ActionView::Base.new(template_root, assigns, self) do |template|&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This fixes the problem where the Publisher would look for views in a directory path that contained your publisher's name twice.&lt;br /&gt;&lt;br /&gt;The second one is to change the &lt;code&gt;inherited&lt;/code&gt; method's call to &lt;code&gt;send!&lt;/code&gt; to instead simply call &lt;code&gt;send&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;For the link generation, I tweaked the implementation of Facebooker's UrlRewriter#link_to_canvas? method, shown in entirety here:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;def link_to_canvas?(params, options)&lt;br /&gt;  option_override = options[:canvas]&lt;br /&gt;  options[:only_path] = false if !option_override.nil?&lt;br /&gt;  return false if option_override == false # important to check for false. nil should use default behavior&lt;br /&gt;  option_override || @request.parameters["fb_sig_in_canvas"] == "1" ||  @request.parameters[:fb_sig_in_canvas] == "1"&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The result is that if the &lt;code&gt;canvas&lt;/code&gt; parameter is specified, then we force a full URL, instead of only a path (which is the default).  This covers apps that have both a regular web application and a Facebook app, where you are generating links that point to one from the other (e.g. you're in Facebook, but generating a link that points to your regular web app).&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-3980309842319476733?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/3980309842319476733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=3980309842319476733' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3980309842319476733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3980309842319476733'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/03/facebooker-publisher-and-url-fixes-for.html' title='Facebooker Publisher and URL Fixes for Rails 1.2.x Use'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-2258417532890909681</id><published>2008-03-13T00:25:00.001-07:00</published><updated>2008-03-27T00:28:38.631-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><title type='text'>Seed Data for Your Rails 2 Apps - Another Approach</title><content type='html'>Historically, I've used migrations to set up standard data that my database must contain in a Rails app.  This would be things like standard Roles for the system, or maybe country codes or such things.  However, it appears this simply won't work in Rails 2.x, because as far as I can tell, when you run something like "rake test", it blows away ALL data in your database (not just fixture data).  If I'm wrong about that, please correct me.  This makes sense given that it seems the drive is towards schema.rb being the official way to create a DB from scratch, and that you have the equivalent of Foxy fixtures which do lots of magic to make creating your fixtures easy (but likely quite painful to figure out how to explicitly clean up those fixtures in certain cases - so it's easier just to wipe the DB clean).&lt;br /&gt;&lt;br /&gt;There are various solutions for creating seed/standard/structured data for your app.  However, from what I've seen none address this problem that that data will get wiped out when testing.  For many people that may not matter, their tests may not hinge on it.  But, I like to stay DRY, and when you have standard roles, or similar types of data, there is no reason I should have to recreate those in fixtures (and risk being out of sync), or leave them out, etc.  I likely have app functionality that directly depends on such things, and thus I need this during testing as well.&lt;br /&gt;&lt;br /&gt;My solution as of now is a simple one, and one that does not scale well for large amounts of data, but for the five records I need at this point in the particular app I'm working on, it's an approach (I very much welcome better approaches!)...  I simply created a "seed_data.rb" file in my config/initializers directory.  Within this file I have code that does a &lt;a href="http://railspikes.com/2008/2/1/loading-seed-data"&gt;create_or_update&lt;/a&gt; (or similar) of the standard data I need.  This seems to work out quite well.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Update:&lt;/strong&gt; the above breaks things like "rake db:reset", because when the initializers run, as part of the Rake environment, and the DB has been dropped, the initializer fails, and thus fails rake.  &lt;/em&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-2258417532890909681?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/2258417532890909681/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=2258417532890909681' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2258417532890909681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2258417532890909681'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/03/seed-data-for-your-rails-2-apps-another.html' title='Seed Data for Your Rails 2 Apps - Another Approach'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-1936643105705748158</id><published>2008-03-11T15:40:00.001-07:00</published><updated>2008-03-11T15:49:03.299-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Versioin Control'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>SVN Externals are Evil; Use Piston or Braid</title><content type='html'>I've recently spent a considerable amount of time rectifying problems caused by SVN externals.  In one of the codebases I work on, it had been developed with a heavy number of Rails plugins as SVN externals.  In general, it was a good approach as these were external code, or shared code, etc.  This I think is at least better than directly checking the code in, as you have a more precise record of where it's from, etc.  I should also note that our externals were all set to specific tags or branches specific to our code (i.e. not to trunk, where you'd be getting updates without your control).  Sounds good, what about this "evil"?&lt;br /&gt;&lt;br /&gt;The problem comes in when you need to make changes to the code of an external.  You might think, well, go change the root code and then adjust your tag, etc.  In some cases you can't do that - maybe it's not code you have commit rights to, or you're making a change that's specific to your app and can't be done another way, or, as was often in the case I had, we were on a much older version, and the trunk and other tags had major differences that I didn't want to integrate.  &lt;br /&gt;&lt;br /&gt;Thus, what I needed to do was remove this as an external, and check the code in directly.  Another approach would be to branch it from where you were and modify that, etc.  I wasn't able to do that due to various Subversion permissions (probably not a common case, but I had no choice).  This action itself (remove external, add code) is not a real problem in SVN.  But, it IS a problem when you go to update.  A simple "svn up" on other machines failed.  That is pathetic.  Instead, what I had to do was go delete the existing (svn externaled) directories, then do "svn up".  This of course broke our continuous integration server, and I also had to go manually fix this up on machines I was deploying to.  Crappy, but if that was the end of it, I'd probably not be as unhappy...&lt;br /&gt;&lt;br /&gt;When it comes to merging these kinds of changes into branches, watch out!  This is where SVN just flails.  First if you happen to use &lt;a href="http://www.orcaware.com/svn/wiki/Svnmerge.py"&gt;svnmerge.py&lt;/a&gt; to manage your branch merging, forget it.  It just can't deal with it, and will leave you with a partially complete merge.  Doing it manually, even with things like --ignore-ancestors, does not work either.  I had to do something similar as to the "svn up" fix: I had to go in and delete all the directories that were previously svn externals, and then do my merge.  And note, do NOT delete the parent directories.  For example, if all of your Rails app's plugins were externals, do go and nuke "vendor/plugins".  It will then be totally confused and just not do anything, and fail.  Nope, you need to specifically delete each offending svn external directory.  I make extensive use of branches (I do most work on a branch for daily work), so you can multiply these problems across the number of branches you might need to be merging to, etc.&lt;br /&gt;&lt;br /&gt;Having said all that, this problem isn't really all that illogical.  I don't know how SVN works internally, but the whole svn:externals thing seems a bit like a hack, or at least not a first class citizen in SVN land.  SVN merge or update, should be able to see: hey, you were up to date (for your current revision) on directory X, but this update is going to replace that with new code with the same dir name.  But, it doesn't, maybe because it doesn't look at the externals properly in relation.  I don't know, and I don't care, since it's broken, and my fix is that I'm moving to Git soon enough :)  Also, as another point of view, I know Perforce handles this kind of thing just fine (we used remote mounted Perforce depots all the time at Adobe, and made seriously extensive use of branches (in fact, we required working on a branch)).&lt;br /&gt;&lt;br /&gt;Now that I've spent entirely too much time on the build-up, what's the solution?  Simple: use &lt;a href="http://piston.rubyforge.org/usage.html"&gt;Piston&lt;/a&gt; (or &lt;a href="http://evil.che.lu/projects/braid"&gt;Braid&lt;/a&gt; if using Git).  What Piston does, is to not use svn:externals, and instead check the code in directly, yet maintain linkage to the external it came from.  My take is this is really probably how svn:externals should've worked (I presume that constantly updating an external is actually a rarely desired trait).  You import an svn external using Piston, and it will pull the latest code from whatever SVN URL you supply.  In this case, you could use trunk, or you could as usual use a tag or branch.  But then it's fixed - it will not update that anytime you do "svn update".  Instead, it is up to you to explicitly tell it to update.  This avoids svn externals as far as your daily operations go, and also causes zero problems for merges.  It does more though.&lt;br /&gt;&lt;br /&gt;The second benefit of Piston is that you can then modify the external code, but still bring down updates from the external, allowing a synergy between using external code and your app's specific needs.  This is exactly what I needed on a couple of plugins we use, where those plugins' code had deviated significantly from our codebase so I couldn't use a newer version, but I needed to make some changes.&lt;br /&gt;&lt;br /&gt;To summarize, the evil is SVN itself not handling changing of externals (i.e. to/from an external) in basic operations like updates and merges, which may cause a lot of manual work on your end, and break automated builds or similar.  The solution: use Piston or Braid and get the best of everything.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-1936643105705748158?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/1936643105705748158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=1936643105705748158' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/1936643105705748158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/1936643105705748158'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/03/svn-externals-are-evil-use-piston-or.html' title='SVN Externals are Evil; Use Piston or Braid'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4952541652501666444</id><published>2008-03-06T11:25:00.001-08:00</published><updated>2008-03-06T11:25:14.238-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Versioin Control'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><title type='text'>Rails Applications and Gems: Solving the Dependency Problem</title><content type='html'>There's a post today on the Relevance blog about &lt;a href="http://blog.thinkrelevance.com/2008/3/6/frozen-gems-generator"&gt;Frozen Gems Generator&lt;/a&gt;.  I tried posting a comment there, but it seems to have not gone through, so I'll blog my solution here instead.&lt;br /&gt;&lt;br /&gt;Chad Woolley at Pivotal Labs created &lt;a href="http://geminstaller.rubyforge.org/"&gt;GemInstaller&lt;/a&gt; to solve the problem of specifying exactly what gems you want your Rails app (or other Ruby code) to use.  I've dealt with this issue a lot over the course of building Rails apps, and while at first blush I didn't think this was a good solution, I'm now really like it, and use it on most of my projects (basically all the projects I control or can :)&lt;br /&gt;&lt;br /&gt;So, why is it better than other solutions, or at least the other solutions I've seen?  First, let me give a quick synopsis: it is a simple gem that allows you to create a geminstaller.yml file that specifies the version(s) of gems your app wants.  This can be an explicit version, or can use things like &gt;= version, etc.  It can then automatically install the gems for you on app launch, on deploy, or just at the command line.  The benefits of this solution for a Rails app include:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Solves the arhictecture/platform-specific gems problem.  I haven't seen any of the other solutions do this, or do it well.  Most just punt on it, others require a convoluted process or hacking up your other code.  Because geminstaller simply relies on the gems being installed on your system, it will use the proper version for whatever system it is running on.  This also ties into the next point...&lt;/li&gt;&lt;br /&gt;&lt;li&gt;No polluting your source control with gems.  This speeds up your source control, as well as your deploys.  Further, for architecture specific gems, you now don't have to have every version of each gem in your source control for each platform you need (which is quite likely at least two: your dev boxes (e.g. Macs) and your deployment boxes (Linux), but could be even more).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Easier, single location, statement of what gems your app requires.  By using the geminstaller.yml file, you have a single place to go see what gems and which versions of those gems your app uses.  This is much better than trying to look through your vendor directory, and determine what version of a gem you might have.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Great for bootstrapping your development environment.  Sure, frozen gems usually solve this too (except for the architecture specific ones!).  You can just run geminstaller after pulling down the code and it'll go install all the specific version gems you need.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Allows for multiple config files, so that you can build common ones you use across projects, etc.  Or even cooler, your plugins or whatever can provide a file to specify what they need and you can integrate that into your config!&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Easy to install and use.  In Rails 2 environments, you can simply drop the few lines needed to use it into its own file in config/initializers.  In Rails 1.x, you add these lines to your environment.rb.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You determine what level of function you want geminstaller doing in your app: e.g. do you want it automatically installing missing gems or just warning  you?  Should it put them on the load path so you are guaranteed the proper version loads, or do you want to just use it to bootstrap and live dangerously otherwise ;-)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Makes it easier to experiment with new versions of gems.  Since you'll have to install the gem anyway (or most solutions need that to freeze them in, but not all), you can experiment by simply changing the version number in your geminstaller.yml file.  To undo it, just change the number back.  No need to copy the gem into vendor or a private gem repo, etc.  Easy.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;GemInstaller can tell you what gems you have on your system, but are not in your config file, as a way to see what you might need.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Check out the &lt;a href="http://geminstaller.rubyforge.org/"&gt;GemInstaller&lt;/a&gt; page for more details.  I highly recommend this, and thanks Chad for creating it.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4952541652501666444?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4952541652501666444/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4952541652501666444' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4952541652501666444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4952541652501666444'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/03/rails-applications-and-gems-solving.html' title='Rails Applications and Gems: Solving the Dependency Problem'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-2119811860075853981</id><published>2008-03-05T09:24:00.001-08:00</published><updated>2008-03-05T09:24:03.973-08:00</updated><title type='text'>Innovation and the New Gauge of a Good Job</title><content type='html'>Sam Davidson has a great post over on the new-ish &lt;a href="http://www.brazencareerist.com"&gt;Brazen Careerist&lt;/a&gt; blog/site, "&lt;a href="http://www.brazencareerist.com/2008/03/04/new-guage-of-a-good-job-freedom/"&gt;New Gauge of a Good Job: Freedom&lt;/a&gt;."  I couldn't agree more.  This pretty much sums up why I left Adobe.&lt;br /&gt;&lt;br /&gt;There are parts of Adobe, in my opinion, doing interesting things (Air and Lightroom for example), but for the most part it's so corporate, slow, and risk averse, that they are still not in the web app game - they're not just late, they're non-existant (and note that I say that as someone who has shipped network and web apps for Adobe).  And to think that Microsoft said they were late to the game 10 years ago!  (I don't have the quote from Gates on that, so 10 years give or take :)&lt;br /&gt;&lt;br /&gt;I have worked on web apps there, and there are actually a couple out there, but none anybody talks about.  It is sad to me, because there are awesome people there!  I've worked in the web services &amp; apps groups, Photoshop group, on consumer software, and so on, and there are so many super smart people, and lots of great ideas.  I've worked for Adobe twice in my career, so it's not as if it's a bad or evil company.  Moving on...&lt;br /&gt;&lt;br /&gt;In Mr. Davidson's article, it's mentioned that Fast Company's latest issue says Google is the world's most innovative company.  I've been discussing innovation with friends lately, and our (if I may) take is that that's not actually true.  It is potentially the most visible and obvious candidate for that, but look at many of Google's "innovations" lately: they're actually acquisitions.  The percentage of in-house developed apps and innovation has gone down as they've grown (not surprisingly).  &lt;br /&gt;&lt;br /&gt;At the core of our discussions is that big companies just aren't the ones doing the bulk of innovation these days, or even that noticeable of a percentage of it.  Most innovation is coming from the tiny startups, the "garage" built companies, or much smaller companies.  To many people this may not be obvious, because what seems to then often happen is that Google, Yahoo, etc. snatch up those companies.  I would argue that Apple is more innovate from within than any other big company right now (iPhone, iPod, MacBook Air).  Amazon might be my next candidate (Amazon Prime, their web services).  It's of course all debatable and that in and of itself is fun.&lt;br /&gt;&lt;br /&gt;The best part of it all to me, is simply that there is a lot of great stuff being done!  Lots of cool web apps, interesting hardware bits, intriguing business models, and so on.  So, here's to all the innovation going on out there, regardless of where it's being done!  And, for folks sitting there in a non-creative, or constrained environment, take a serious look outside.  It can be a bit scary to leave that cushy, well paying, great benefits job, but there's a lot more to life, and having made the jump myself, I find I'm constantly saying I wish I'd done it sooner!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-2119811860075853981?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/2119811860075853981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=2119811860075853981' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2119811860075853981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2119811860075853981'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/03/innovation-and-new-gauge-of-good-job.html' title='Innovation and the New Gauge of a Good Job'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-5087645883651045231</id><published>2008-03-02T16:47:00.001-08:00</published><updated>2008-03-02T16:48:06.040-08:00</updated><title type='text'>Beautiful Dining Table, Chairs, and Mirror For Sale</title><content type='html'>&lt;a href="http://www.flickr.com/photos/80818705@N00/2305514657" title="View 'DiningSet-1' on Flickr.com"&gt;&lt;img src="http://farm4.static.flickr.com/3249/2305514657_ebdc392491_m.jpg" alt="DiningSet-1" border="0" width="240" height="160" align="left"/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Normally I don't post eBay or Craigslist stuff I'm selling on my blog, but this is a special item (items).  We have an amazing dining room table, chairs, and mirror that we're selling, because it very unfortunately doesn't work (color wise) in our new house.  We've held out nearly a year (since moving) and are finally ready to part with it :)  &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/80818705@N00/2306314494" title="View 'DiningSet-2' on Flickr.com"&gt;&lt;img src="http://farm3.static.flickr.com/2156/2306314494_c0b66a7138_m.jpg" alt="DiningSet-2" border="0" width="160" height="240" align="right"/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Check out the &lt;a href="http://eugene.craigslist.org/fur/593487854.html"&gt;ad on Craigslist&lt;/a&gt;, as well as the bigger/better &lt;a href="http://cobaltedge.com/diningtable/"&gt;photo gallery&lt;/a&gt;.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-5087645883651045231?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/5087645883651045231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=5087645883651045231' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5087645883651045231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5087645883651045231'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/03/beautiful-dining-table-chairs-and.html' title='Beautiful Dining Table, Chairs, and Mirror For Sale'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm4.static.flickr.com/3249/2305514657_ebdc392491_t.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-266610577957001410</id><published>2008-02-25T22:03:00.001-08:00</published><updated>2008-02-25T22:03:54.776-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>Git: Start As a Superior SVN, then Leverage Even More</title><content type='html'>&lt;a href="http://git.or.cz/"&gt;Git&lt;/a&gt; has been getting a fair bit of attention lately.  I am relatively new to Git, but am definitely a convert and big fan after on a short time using it.  I'm to the point where I really don't want to use anything else.  I have existing projects using SVN, and also have extensive experience with Perforce, both of these being centralized version control systems.&lt;br /&gt;&lt;br /&gt;So, why Git, why as a superior SVN, and so on?  If you are using Subversion, or for that matter, many other choices, it is worth a serious look at Git, if at least to provide a superior solution to existing centralized version control.  You can ignore the distributed version control aspects to start out.  I am a strong proponent of using developer "sandboxes."  My definition of this stems from our use of version control at Adobe.  Put simply, a sandbox is really a developer's private branch.  Those familiar with Git, Mercurial, or other distributed SCM's will immediately see the parallel.  With team development, each team member works in a sandbox, and then when they have completed some amount of work that they deem suitable for the main line, or that follows with their team's checkin policies, etc., they merge their branch into the mainline (aka trunk).  Doing this in SVN is fairly painful (svnmerge.py helps, but it's still weak; SVN 1.5's merge abilities may help, but it's still not even up to what SVK does).  Perforce has great support for this, but it's not all that fast, and setup isn't quite as easy as Git.  Also, Perforce has a locking model (i.e. to edit files, you must check them out first), which annoys me to no end after having also used SVN, etc.&lt;br /&gt;&lt;br /&gt;A sandbox is like your own private repository, and while I don't recommend ever checking in code that doesn't compile, etc., you can if you want, and thus gain the security of your code at least being backed up/in a second location, check pointing it as much as you want, and leveraging version control, all without hosing your teammates.  On larger projects at Adobe, like Photoshop, we even took this a level further, and had a sandbox for the sub-team, so you would merge your sandbox to that, your sub-team's QA would test that, and then that got pushed to main, etc.&lt;br /&gt;&lt;br /&gt;With Git however, this "sandbox" model would be had for free, due to the distributed/decentralized model.  But, do not fear, you can/do still have a central repository that is the official mainline/trunk of code!  The mainline is set up as a repository, then each developer to begin work, "clones" that mainline, which creates a FULL repository on their machine (as in, not just the latest version of the code, but all history, etc.).  Now, said developer can simply do their work, committing changes at will, taking full advantage of the version control system.  Then, when they are ready to push their changes to the mainline/rest of the team, they simply do a push and all their changes get merged into the main repository.  Very much like working on a branch/in a sandbox model, but the beauty is that you aren't having to set up a branch, you don't have to manage your branch (more painful in SVN, fairly easy in P4), and it's all VERY fast (the speed is crazy fast compared to both SVN and P4 for all these operations).&lt;br /&gt;&lt;br /&gt;What's also cool, is that you can create branches off your own repository to do experiments or sub-projects, or isolate changes for say a bug fix, or whatever.  Creating branches is so dang easy in Git that there is no reason not to do it for even the smallest thing.  &lt;br /&gt;&lt;br /&gt;Thus, it's not that you can't do any of this without Git, but Git simply makes it far easier and far faster to do this, lowering the barriers to great use of source control, and making management of your code that much better. &lt;br /&gt;&lt;br /&gt;And, leveraging this further, you can use Git to collapse a bunch of checkins down into one.  So, in this sandbox model, say you were doing a bunch of really small incremental commits, you could "squash" some or all of those prior to pushing your code into main.  &lt;a href="http://adam.blog.heroku.com/past/2008/2/18/changesets_not_snapshots/"&gt;Here's one blog entry&lt;/a&gt; on this kind of thing.&lt;br /&gt;&lt;br /&gt;Now, Git does offer one feature that I find really cool, that is not in SVN or P4 (nor any other system that I'm aware of, but of course there are many I haven't used either).  This is the "stash" (see &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-stash.html"&gt;git-stash&lt;/a&gt;).  &lt;br /&gt;&lt;br /&gt;You can probably guess what it does.  The stash allows you to take some work, and stash it away (without checking it in!) while you then work on something else in the mean time.  Maybe you are trundling along on a new feature, and then something quick comes up that you need to make your top priority.  Just stash your existing work away, do that new work, then apply the stash back when ready to work on that code again.  The stash is like a temporary holding spot - allowing you to keep track of work, but without having to check it in.  Sure, you could simply whip up a branch and check it in to that, and that certainly works, but the stash is great when appropriate.&lt;br /&gt;&lt;br /&gt;Some of this might seem small, but as we developer's know, some of these small things can make a huge impact on your efficiency and make your day that much nicer.  As said, I'm totally sold on Git, and have been converting my SVN projects to Git.  I've been using &lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt; as my "central" repository, or rather, the way I look at it, it's my offsite copy, or backup.  But, setting up your own on a server is relatively simple as well, and you can use gitosis to manage access control and so on.  &lt;a href="http://scie.nti.st/2007/11/14/hosting-git-repositories-the-easy-and-secure-way"&gt;Garry Dolley has a great writeup&lt;/a&gt; of the entire process (which is really rather short).&lt;br /&gt;&lt;br /&gt;It might seem like a pain to change source/version control systems, but Git has tools to import an SVN repository, including all history, etc.  I've used this on a relatively simple SVN repo and it worked fine - I haven't tried it on one with a slew of branches and tags, etc.  Regardless, I would highly recommend checking out Git.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-266610577957001410?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/266610577957001410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=266610577957001410' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/266610577957001410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/266610577957001410'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/02/git-start-as-superior-svn-then-leverage.html' title='Git: Start As a Superior SVN, then Leverage Even More'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-5863573168134381461</id><published>2008-02-19T16:18:00.001-08:00</published><updated>2008-02-19T16:18:21.999-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='travel'/><category scheme='http://www.blogger.com/atom/ns#' term='coffee'/><category scheme='http://www.blogger.com/atom/ns#' term='Espresso'/><category scheme='http://www.blogger.com/atom/ns#' term='wine'/><category scheme='http://www.blogger.com/atom/ns#' term='restaurants'/><category scheme='http://www.blogger.com/atom/ns#' term='food'/><title type='text'>Tour de Cafe - SF Espressos, food/restaurants, wine bars</title><content type='html'>I'm in San Francisco this week to assist with the &lt;a href="http://www.buildingwebapps.com/seminar"&gt;RailsQuickStart seminar&lt;/a&gt; on Wed and Thurs.  But, in the mean time, I'm enjoying the food and drink scene.  Monday I spent with my good friend Matt, who recently moved from SF to Silverton, CO, but was back in town for a while selling some houses.  Matt used to go out essentially every night, and really knows the scene.  He picked me up at the airport at 9:30a, and we began our tour.&lt;br /&gt;&lt;br /&gt;First stop, and top priority, was the new &lt;a href="http://www.bluebottlecoffee.net/"&gt;Blue Bottle cafe&lt;/a&gt; in the Mint district.  Luckily the line was minimal, an we ordered our cappuccinos and poached eggs &amp; toast breakfast.  The cap was awesome of course, and the food was quite good too.  Blue Bottle is just really good with capuccino - superb micro-foam and great afteraste.  It was also cool to see their new siphon bar in action.  It's a trippy, chem-lab looking setup.  I don't know if I'll have a chance to try it on the trip, but will do so if I'm in the cafe again this trip.  We almost ordered another drink, but decided the line was a bit long by now, and so headed over to &lt;a href="http://ritualroasters.com/"&gt;Ritual Roasters&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Arriving at Ritual, we were greeted with a huge line out the door.  But, it moved fairly quick, and we each ordered a doppio.  However, we were extremely disappointed (which is saying it nicely)...  the espresso was crap.  Straight up, they should have been embarrassed to serve us those totally sour shots of under-extracted, under-temperature espresso!  This was surprising to both of us, although it sounds like Matt has found them declining for a while (maybe they need to go back to using &lt;a href="http://stumptowncoffee.com/"&gt;Stumptown&lt;/a&gt; - go Oregon! ;-)  Yuck, we left them on the bar and skedaddled. &lt;br /&gt;&lt;br /&gt;As the lunch hour arrived, we both didn't want to pass up the opportunity to hit the taco truck(s) over by Best Buy.  Good authentic, simple tacos.  I went with carnitas, Matt had carne asada and ate all his jalapenos.  Back to his friend Jeff's house to meet Jeff, do a quick email session, and check the status of the day's &lt;a href="http://www.amgentourofcalifornia.com/"&gt;Tour of California&lt;/a&gt; stage.  Now it was time for me to check in to my hotel and then head out to dinner with some of Matt's friends.  &lt;br /&gt;&lt;br /&gt;We hit Chow in the Castro.  I'd say this part of the day was just average.  Food was decent, but nothing special, average atmosphere, etc.  We were joining his friend's who have small kids (2 and 4), so I get that aspect completely (Chow was kid friendly), but since I'm traveling and in SF, I'm of course wanting to go to the really great places, or different or unusual or whatever.  From there we split from his friends, picked Jeff up, and headed out to a wine bar.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.hotelbiron.com/"&gt;Hotel Biron&lt;/a&gt; is a small wine bar, tucked away on an alley, sporting just a small "B" sign.  Definitely the kind of place I was looking for - somewhere you wouldn't just stumble across, small, great wine, and oh-my-gosh, you could actually hear people talk in there!  What a concept!  We even sat on a comfy leather couch.  The wine was also great.  Had a nice bottle of malbec, and some glasses of Chilean (which I skipped, as I'm kind of a lightweight).  Oddly enough, earlier in the day we'd seen the owner, Chris, walking across the street carrying a bicycle wheel.  He looked like a bike messenger or something - no clue he'd have been a wine bar owner, but that's SF for you (Matt knows him, thus the reason we could spot this).&lt;br /&gt;&lt;br /&gt;At this point we thought we were going to call it a night, but it was still fairly early, so as we were in the area, and a lot of other things were closed, we went to &lt;a href="http://www.opentable.com/rest_profile.aspx?rid=2910"&gt;A 16&lt;/a&gt;.  Matt claims A 16 is the second best Italian restaurant in SF.  Continuing the small world aspect, as we saddled up to the bar, the bartender turns around and Jeff realizes he knows him.  Of course this made for an even better night.  Tim is a sommelier, travels the world, and was a fun guy to talk to.  He poured us some great wines to go along with the pizza and prosciutto plate we snuck in as a last minute order before the kitchen closed.  &lt;br /&gt;&lt;br /&gt;After a while we decided an espresso might be in order, and knew it might be ok, as they used Blue Bottle beans :)  Of course we needed to have some dessert to go along with that.  We ordered the two most interesting looking desserts, which were the chocolate tart with olive oil and sea salt, and the pecorino gelato with buckwheat brownie.  I was unsure how well the pecorino gelato would combine, but damn if that dessert wasn't awesome!  The buckwheat brownie was superb, and combined with the gelato was just a fantastic dessert.  The pecorino was strong, and I think Matt and Jeff were less enthusiastic about it, but if I went back to A 16, I doubt I'd leave without ordering that dessert again!  Also, the desserts came paired with dessert wines which were outstanding.    Everything there was great, including all the excellent info and wine Tim provided.  I can't help but agree that A 16 was a great stop, and definitely an ideal ending to our evening.&lt;br /&gt;&lt;br /&gt;Tuesday will be more relaxed as I'll be doing some work, but I'm sure will be heading for Blue Bottle and some other cafes again.  Another report to follow...&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-5863573168134381461?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/5863573168134381461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=5863573168134381461' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5863573168134381461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5863573168134381461'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/02/tour-de-cafe-sf-espressos.html' title='Tour de Cafe - SF Espressos, food/restaurants, wine bars'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-5628199261784906933</id><published>2008-02-13T19:22:00.001-08:00</published><updated>2008-09-09T09:35:35.742-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Auto-Complete Text Fields in Rails 2</title><content type='html'>&lt;em&gt;[Note: this entry updated to include required routing, as I failed to mention that the first time.]&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;In Rails 2, the PrototypeHelper and ScriptaculousHelper code was removed to plugins.  This means that doing auto-complete for various fields was no longer part of the base Rails.  I didn't find any great, straight-forward docs on how to do this for Rails 2.x, so am sharing what I've done to hopefully help others.  Further, the README for this tells you how to do it for standard string fields on a given object, but I needed to do it for an associated object field, so I'll cover that here as well.  As you can guess, this only pertains to Rails 2.x...&lt;br /&gt;&lt;br /&gt;First you'll need to install the auto_complete plugin:&lt;br /&gt;&lt;pre&gt;script/plugin install auto_complete&lt;/pre &gt;&lt;br /&gt;This plugin will give you the &lt;tt&gt;text_field_with_auto_complete&lt;/tt&gt; view helper method amongst others.  It also provides a controller hook (&lt;tt&gt; auto_complete_for&lt;/tt&gt;) to implement the auto-complete action/method in your controller for you, if that works for the field you need.  As per the auto_complete README, it looks like:&lt;br /&gt;&lt;pre&gt;class BlogController &lt; ApplicationController&lt;br /&gt;  auto_complete_for :post, :title&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;code&gt;auto_complete_for&lt;/code&gt;, as used above, would implement a auto_complete_for_post_title method in your controller class.  The parameters are the object and field/method of that object.  The method it implements will dig through all the Post records in your database and do a LIKE comparison on the &lt;code&gt;title&lt;/code&gt; column, comparing the title to the contents of the post[title] form field.  With the results, it will generate the HTML for an unordered list (&lt;code&gt;ul&lt;/code&gt;), and return that to the view.&lt;br /&gt;&lt;br /&gt;This is pretty slick: you can essentially get auto-complete with a view method name change in your HTML (from calling &lt;code&gt;text_field&lt;/code&gt;, to &lt;code&gt;text_filed_with_auto_complete&lt;/code&gt;), and a single line added to your controller.  Now, what happens if the field you want to auto-complete on doesn't directly correlate to a field on your model object?  For example, in my case, I wanted to auto-complete on a field from a belongs_to association, so I couldn't use the pre-built auto-completion method that does a direct SQL query on the field.&lt;br /&gt;&lt;br /&gt;This is actually easy to solve.  You can just implement the &lt;code&gt;auto_complete_for_object_field&lt;/code&gt; method yourlself.  And, while you're at it, you might as well leverage some of the other helpful methods in the auto_complete plugin.  Or, if you need custom view/HTML output, you can just render as you need within that method.  When you do this, do not call the controller hook, simply implement the method yourself.  Here's mine for example:&lt;br /&gt;&lt;pre&gt;def auto_complete_for_doctor_organization&lt;br /&gt;  re = Regexp.new("^#{params[:doctor][:organization]}", "i")&lt;br /&gt;  find_options = { :order =&gt; "name ASC" }&lt;br /&gt;  @organizations = Organization.find(:all, find_options).collect(&amp;:name).select { |org| org.match re }&lt;br /&gt;        &lt;br /&gt;  render :inline =&amp;gt; "&amp;lt;%= content_tag(:ul, @organizations.map { |org| content_tag(:li, h(org)) }) %&amp;gt;"&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally, for completeness, here's the field's definition in my view template (Erb):&lt;br /&gt;&lt;pre&gt;&amp;lt;label for="organization"&amp;gt;Group/Practice/Hospital Affiliation&amp;lt;/label&amp;gt;&lt;br /&gt;&amp;lt;%= text_field_with_auto_complete :doctor, :organization, :autocomplete =&gt; "off" %&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The one counter-intuitive looking thing there is the &lt;samp&gt;:autocomplete =&gt; "off"&lt;/samp&gt; bit.  Uh, aren't we doing autocomplete?  Well, this particular attribute tells the &lt;em&gt;browser&lt;/em&gt; to not do it's auto form completion stuff (so that our code can do it instead).  Oh, and of course you need to ensure you are including Prototype and Scriptaculous JavaScript libraries in your views, which you can achieve, rather bluntly, with:&lt;br /&gt;&lt;pre&gt;&amp;lt;%= javascript_include_tag :all, :cache =&amp;gt; true %&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finally, you will need to add route(s) to your routing file.  I use a sort of wild-card route to cover all my auto-completes:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;map.auto_complete ':controller/:action', &lt;br /&gt;                  :requirements =&gt; { :action =&gt; /auto_complete_for_\S+/ },&lt;br /&gt;                  :conditions =&gt; { :method =&gt; :get }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This will resolve any routes that match an action starting with "auto_complete_for_".&lt;br /&gt;&lt;br /&gt;With that, we have auto-completing text fields in Rails 2.x!  Cool stuff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-5628199261784906933?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/5628199261784906933/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=5628199261784906933' title='48 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5628199261784906933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5628199261784906933'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/02/auto-complete-text-fields-in-rails-2.html' title='Auto-Complete Text Fields in Rails 2'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>48</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7832455375321361274</id><published>2008-02-10T10:11:00.001-08:00</published><updated>2008-02-10T10:11:08.352-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Social Networking'/><category scheme='http://www.blogger.com/atom/ns#' term='Facebook'/><title type='text'>Facebook and Business</title><content type='html'>I was, and am still slightly a Facebook skeptic.  I did not use it in college (it didn't exist "back then" ;-)  And, it's just not something I use much, yet.  But, I won't deny the incredible viral effects it has.  And, I am actively working on Facebook applications (or integrations with existing sites).&lt;br /&gt;&lt;br /&gt;I came across a great blog entry, &lt;a href="http://www.curiousoffice.com/2008/01/28/collision-of-the-enterprise-and-web-20/"&gt;Collision of the enterprise and web 2.0&lt;/a&gt;, which talks about how Facebook is being used for business more and more, and how the lines between your friends, and your "business associates is blurring.  I couldn't agree more.  Besides, I'm both friends with and business associates with many of the same people, a lot of them in fact.&lt;br /&gt;&lt;br /&gt;One of the main things that has prevented more use of Facebook for me is simply the lack of "useful" applications.  Zobies and movie quizzes are just not something I have time for, or rather, want to spend my time on.  But, as productivity, business, and other such "useful" applications start to enter, it won't surprise me at all if I use Facebook a lot more.  It is a good social and network property, and downright easy and nice for doing the social networking aspects.  So, here's to seeing how Facebook's application space grows going forward.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7832455375321361274?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7832455375321361274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7832455375321361274' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7832455375321361274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7832455375321361274'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/02/facebook-and-business.html' title='Facebook and Business'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-9019333173566836920</id><published>2008-02-08T10:50:00.001-08:00</published><updated>2008-02-08T10:51:58.332-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><title type='text'>My Dock, Too Many Browsers, Fluid, etc.</title><content type='html'>As may be obvious to readers of this blog, I've been doing a fair bit of Facebook development work lately.  As such, I need to have multiple Facebook (test) users to observe the social net aspects, etc.  I thus have to have multiple browsers open so they can all be logged in at the same time.  I am really hoping that a future version of &lt;a href="http://fluidapp.com/"&gt;Fluid&lt;/a&gt; will allow you to have a separate cookie store per Fluid app, so that I can just create Fluid apps for each FB user.  But for now, I can't, so I have at least two, if not three, sometimes four different browsers open to do testing.  &lt;br /&gt;&lt;br /&gt;I also have been somewhat amused that my dock now consumes almost the entire width of my 24" monitor (1920x1200 resolution)!  &lt;br /&gt;&lt;div class="thumbnail"&gt;&lt;a href="http://skitch.com/chrisrbailey/f97h/fullscreen"&gt;&lt;img src="http://img.skitch.com/20080208-bxd7krd54uchn1bgxk5tg4kexh.preview.jpg" alt="Fullscreen" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family: Lucida Grande, Trebuchet, sans-serif, Helvetica, Arial; font-size: 10px; color: #808080"&gt;Uploaded with &lt;a href="http://plasq.com/"&gt;plasq&lt;/a&gt;'s &lt;a href="http://skitch.com"&gt;Skitch&lt;/a&gt;!&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;Oddly, this isn't bothering me a bit.  I make good use of LaunchBar, but I'm still a Dock fan as well.  See the Skitch page for a list of what some of those dock icons are.&lt;br /&gt;&lt;br /&gt;And a geeky tip for Screensaver developers: drop your debug and/or release versions of your saver into the documents area of the dock as an easy way to install it (that's what the two swirly white document images are at the far right of my dock).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-9019333173566836920?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/9019333173566836920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=9019333173566836920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/9019333173566836920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/9019333173566836920'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/02/my-dock-too-many-browsers-fluid-etc.html' title='My Dock, Too Many Browsers, Fluid, etc.'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4154236554177019888</id><published>2008-02-07T23:49:00.001-08:00</published><updated>2008-02-07T23:49:58.204-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Asynchronous Tasks in Rails</title><content type='html'>On the blog Play/Type, there's a great article on how to do &lt;a href="http://playtype.net/past/2008/2/6/starling_and_asynchrous_tasks_in_ruby_on_rails/"&gt;asynchronous tasks in a Rails app&lt;/a&gt;.  Furthermore, they've built a Rails plugin, Workling, that encapsulates asynch tasks and provides a wrapper around Starling, Spawn, and others, making these easy to use.&lt;br /&gt;&lt;br /&gt;I came across this tonight as I was figuring out a solution for spawning off Facebook profile FBML updates in the background since these can do a fair bit of data gathering.  It is also useful in controllers used in a Facebook app, because while you never want your apps' actions to take more than 8 seconds regardless, if they do for Facebook, Facebook will simply fail to load the page.  Therefore, if you have an expensive operation that can occur asynchronously, but is initiated by a controller, this is another place to leverage something like Workling.&lt;br /&gt;&lt;br /&gt;For my own needs, I didn't wind up using Workling, as &lt;a href="http://rubyforge.org/projects/spawn"&gt;Spawn&lt;/a&gt; was sufficient for my needs at this time.  Before I go to production, I may switch to Workling simply to provide future growth in case this Facebook app takes off, etc.  This will be one to watch for sure.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4154236554177019888?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4154236554177019888/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4154236554177019888' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4154236554177019888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4154236554177019888'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/02/asynchronous-tasks-in-rails.html' title='Asynchronous Tasks in Rails'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-8914750257995472624</id><published>2008-02-04T15:08:00.001-08:00</published><updated>2008-02-04T15:08:16.851-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><title type='text'>Testing Facebook Applications With Test Facebook Users</title><content type='html'>Facebook's terms of service don't allow "fake" users, or user's who aren't associated with a human.  This makes it harder to test Facebook applications which aren't published.  However, they do provide a mechanism to mark an account as a test user account (see the &lt;a href="http://wiki.developers.facebook.com/index.php?title=Test_Accounts"&gt;Test Accounts wiki page&lt;/a&gt;).  It falls under a bunch of different rules, some of which make things slightly challenging.  For example, non-test user's cannot be friends with test users.  This means in order to use a test user, you will have to create at least two of them, so they can be friends.  Doesn't exactly parallel real life does it? :)&lt;br /&gt;&lt;br /&gt;So, the next problem that crops up, is that you will want to register your developer app using a real account, but if real accounts and test accounts can't be friends, how do you share that app?  This is not obvious, but you can extract how to do it from the questions at the bottom of that Test Accounts wiki page.  Here's how I set it up (these are streamlined instructions as I had to futz around a bit before seeing how to work with the limitations):&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Create two new user accounts on Facebook.  You'll obviously need a valid email to go with this.  I run various domains so just setup users in that, but you could use a Yahoo account or whatever.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Add the Developer application to each of the test user accounts.  This is required in order for them to use your application which is still in development and not public.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Have these users become friends now if you like (they can become friends later as well).  Also, have them be friends of the user you have that registered your Facebook application.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;In your real user account that has the registered app, make the test users developers.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;In one of the test user accounts, add the application.  I start with just one, as I often want to test the Invite mechanism for the application.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Now mark the test accounts as test accounts using the URL provided on the &lt;a href="http://wiki.developers.facebook.com/index.php?title=Test_Accounts"&gt;Test Accounts wiki page&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Now you're set to have your test user's be what you use to test your application, allowing you to do invites, post messages to the mini-feed, and so on, and see how this works across friends.  Hopefully Facebook will improve this in the future, as per various suggestions on the wiki page.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-8914750257995472624?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/8914750257995472624/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=8914750257995472624' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8914750257995472624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8914750257995472624'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/02/testing-facebook-applications-with-test.html' title='Testing Facebook Applications With Test Facebook Users'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-6008833528446807491</id><published>2008-02-03T23:55:00.001-08:00</published><updated>2008-02-03T23:55:01.662-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Books'/><title type='text'>Take the Red Book</title><content type='html'>The latest issue of Wired has an article by Clive Thompson titled, &lt;em&gt;Take the Red Book&lt;/em&gt;. The article, &lt;a href="http://www.collisiondetection.net/mt/archives/2008/01/why_scifi_is_th.html%23001730"&gt;available on Mr. Thompson's web site&lt;/a&gt; struck a chord with me.  I have not been a big reader of SciFi, but I've noticed that over the last couple  years, I've been reading less fiction, and amazingly (to myself), a lot of non-fiction.  I think his article resonated because I realized that I have been a bit bored with some of the fiction as well.  Further, his article got me to read Cory Doctorow's, &lt;a href="http://www.infinitematrix.net/stories/shorts/after-the-siege.html"&gt;&lt;em&gt;After the Siege&lt;/em&gt;&lt;/a&gt;, which is a great short story.  It is also not crazy out-there SciFi.  &lt;br /&gt;&lt;br /&gt;I've read William Gibson's two &lt;a href="http://www.amazon.com/Pattern-Recognition-William-Gibson/dp/B000MGAHY6/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1202111563&amp;amp;sr=8-1"&gt;latest&lt;/a&gt; &lt;a href="http://www.amazon.com/Spook-Country-William-Gibson/dp/0399154302/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1202111487&amp;amp;sr=8-1"&gt;books&lt;/a&gt;, er, scratch that, I'm still in the middle of his latest, and honestly, I don't think I'll finish it.  Granted, these are a departure for him, and are not SciFi, but IMHO, aren't that good.  I liked some of his earlier work, and I know he's highly regarded, but a lot of it was just too far out there, too much tech.  I've read &lt;em&gt;Snow Crash&lt;/em&gt;, various Heinlein, Asimov, Douglas Adams, etc.  And actually, while I haven't read all of his works, Bruce Sterling's &lt;a href="http://www.amazon.com/Heavy-Weather-Bruce-Sterling/dp/055357292X/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1202111651&amp;amp;sr=1-1"&gt;&lt;em&gt;Heavy Weather&lt;/em&gt;&lt;/a&gt; is an absolute favorite, that was right up my alley.  And now, having read &lt;em&gt;After the Siege&lt;/em&gt;, and based on the &lt;em&gt;Take the Red Book&lt;/em&gt; article, I'm thinking I need to get back to some SciFi, and just try some different authors.  Recommendations?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-6008833528446807491?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/6008833528446807491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=6008833528446807491' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6008833528446807491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6008833528446807491'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/02/take-red-book.html' title='Take the Red Book'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-6254911487194600247</id><published>2008-02-03T00:28:00.001-08:00</published><updated>2008-02-03T00:28:39.783-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Amazon'/><title type='text'>Delete an S3 Bucket Containing Thousands of Files</title><content type='html'>A backup bucket I had on Amazon S3 (via Jungle Disk) had gotten out of control and was costing me too much.  I decided to kill it off completely and take a different approach.  So, I wanted to delete the bucket.  I thought, easy, I'll just use Interarchy, pick the bucket, hit delete and be done.  Nope.  Interarchy kept choking on some of the files.  I tried a few times.  Turned to Transmit, failed as well.  So, instead, a few lines of Ruby, via the aws-s3 gem, and I was done, with one caveat.  &lt;br /&gt;&lt;br /&gt;Assuming you have the &lt;a href="http://amazon.rubyforge.org/"&gt;aws-s3&lt;/a&gt; gem installed, I just used IRB to do it.  First there was setting up the connection, and then finding the bucket in question:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;require 'aws/s3'&lt;br /&gt;&lt;br /&gt;AWS::S3::Base.establish_connection!(:access_key_id =&gt; 'put-yer-key-here', :secret_access_key =&gt; 'put-ye-ole-secret-key-here')&lt;br /&gt;&lt;br /&gt;# Find the bucket the blunt way, by getting a list of the few I have, then picking the particular one (for me it was the second one in the array):&lt;br /&gt;&lt;br /&gt;buckets = AWS::S3::Service.buckets&lt;br /&gt;evil_bucket = buckets[1]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then, you need to blow everything away.  According to the docs, you should just be able to delete the bucket, passing the ":force =&gt; true" option, but that didn't work for me - it complained that the bucket didn't exist.  So, instead I decided I'd delete everything in the bucket using the Bucket#delete_all call.  That appeared to work, but it wasn't actually empty.  Then I found that the library only pulls down 1000 files at a time (this is a standard S3 limitation in a listing call - although you'd think the library would realize this and loop until it was truly done), so it was only deleting 1000 files.  So, the trick then was to do:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;while !evil_bucket.empty?&lt;br /&gt;  puts "."&lt;br /&gt;  evil_bucket.delete_all&lt;br /&gt;end&lt;br /&gt;evil_bucket.delete&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I have the puts in there, simply to observe progress (and it's also sort of fun to see how many files there really were).  Obviously this is quick and dirty, but it wound up being far more effective, and nearly as simple as I had expected Interarchy to be.  One note, if you do have a lot of files, this is not something that goes quick - it was taking about a minute per 1000 files (i.e. per delete_all call) on my system.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-6254911487194600247?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/6254911487194600247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=6254911487194600247' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6254911487194600247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6254911487194600247'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/02/delete-s3-bucket-containing-thousands.html' title='Delete an S3 Bucket Containing Thousands of Files'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4453226076617464530</id><published>2008-01-28T15:32:00.001-08:00</published><updated>2008-01-28T15:32:22.674-08:00</updated><title type='text'>Alpine Navigation DVD's: Alpine are idiots</title><content type='html'>We have a Honda Odyssey which has an Alpine navigation system in it that runs off DVD.  They only update the DVD annually.  Fine.  But get this, they prioritize new cars, sitting on a dealer's lot over their existing customers who are actually using the darn thing every day!  No joke.&lt;br /&gt;&lt;br /&gt;I called and talked to them today about it, and that's what I was told.  They told me that until that process is done, only dealers can order the DVD (it's been out since the fall of 2007), and only once all the dealers have done it will they make it something you can order on the web site.&lt;br /&gt;&lt;br /&gt;How ridiculous is this in this day and age?  It's a DVD, burn a few more, or heck, burn on demand!  I fail to see how there is any logic, any value to their customers, etc.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4453226076617464530?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4453226076617464530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4453226076617464530' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4453226076617464530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4453226076617464530'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/01/alpine-navigation-dvd-alpine-are-idiots.html' title='Alpine Navigation DVD&amp;#39;s: Alpine are idiots'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-8252825373221683539</id><published>2008-01-27T23:18:00.001-08:00</published><updated>2008-01-27T23:25:11.721-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyCocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Air'/><title type='text'>RubyCocoa Rocks</title><content type='html'>My infatuation with RubyCocoa continues.  I've been working on a small app for the &lt;a href="http://buildingwebapps.com"&gt;Building Web Apps&lt;/a&gt; folks.  I'd originally been tasked with a feature that was to be done 100% within the web app.  However, some of our requirements changed, and the workflow was not efficient enough.  So, essentially what we moved forward on was a desktop Mac application that could interface with NetNewsWire, as well as the Building Web Apps site. The desktop app gives us a faster way to add data into the system - rapidly processing a ton of content and injecting what is desired into the web app, yet without getting slowed down by a web app interface.  AJAX or Flex, or some other web UI tech wouldn't make it any faster in this particular situation.&lt;br /&gt;&lt;br /&gt;Thus, &lt;a href="http://codeintensity.blogspot.com/2008/01/building-my-first-rubycocoa-app-some.html"&gt;I pursued building a Cocoa app&lt;/a&gt;, but this time using RubyCocoa.  I've written Objective-C apps &lt;a href="http://cobaltedge.com/index.php/visionary-saver/"&gt;before&lt;/a&gt;, and spend the bulk of my time in Ruby, but this was my first opportunity to use RubyCocoa.  The combination, much like JRuby, Jython and other hybrid systems, gives you "the best of both worlds."  There are cons of course (slower, a few Cocoa things you can't do, debugging is harder, etc.), but for the most part, it's really nice.&lt;br /&gt;&lt;br /&gt;For me, the infatuation stems from letting me use the aspects of each system that I am either more efficient with, or that are easier for a particular piece of functionality, all yielding a faster, and better end result.  I can iterate on the app more quickly, and get a solution to BWA faster.  And, one step further in the case of RubyCocoa: having the native OS integration abilities at hand.&lt;br /&gt;&lt;br /&gt;What's been great is the ability to use Ruby's more effective (for me at least) string processing, XML processing, and networking features; create a native Mac application - using any cool Cocoa/native features; and support for AppleScript, which was critical for this particular application.  This latter feature ruled out using something like Adobe Air.&lt;br /&gt;&lt;br /&gt;This evening I setup the second use of AppleScript/Apple Events in this app: registering a custom URL protocol for the app.  Applications like &lt;a href="http://codesorcery.net/pukka/"&gt;Pukka&lt;/a&gt; and &lt;a href="http://mailplaneapp.com/"&gt;Mailplane&lt;/a&gt; do this.  What for?  Well, in this case, it allows me to create a web browser bookmarklet, that can send data from the browser to our app.  It also means that it works in basically any browser on the Mac (as opposed to AppleScript not working for Firefox).  Further, it allows a simple "push a button" in the browser to send the data over to the app, as opposed to having to switch to the app, pick a menu item to pull the data, or horror of horrors, copy-paste.&lt;br /&gt;&lt;br /&gt;How do you do this?  &lt;a href="http://www.cocoadev.com/index.pl?HowToRegisterURLHandler"&gt;This article&lt;/a&gt; is short and covers how to do it in Objective-C.  It's just as easy in RubyCocoa: You need to add an entry into your Info.plist file to specify the name of your URL protocol as described in the article.  Then, you need to register your app as a handler for that protocol:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;NSAppleEventManager.sharedAppleEventManager.&lt;br /&gt;  setEventHandler_andSelector_forEventClass_andEventID_(&lt;br /&gt;    self, :getUrl_withReplyEvent, fourcharcode('GURL'), fourcharcode('GURL'))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;fourcharcode&lt;/code&gt; method is my way of translating four character codes for use in Ruby.  I discussed this in more detail in &lt;a href="http://codeintensity.blogspot.com/2008/01/building-my-first-rubycocoa-app-some.html"&gt;my last post about RubyCocoa&lt;/a&gt;, but here's the actual method for your pleasure:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;def fourcharcode(character_code)&lt;br /&gt;  character_code.unpack('N').first&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ok, so now that you've registered your app to handle its custom URL protocol, you will get an Apple Event sent to you with the URL whenever one is opened.  This is handled (as per the parameter in the registration function above), by the &lt;code&gt;getUrl_withReplyEvent&lt;/code&gt; method:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;def getUrl_withReplyEvent(event, reply)&lt;br /&gt;  url = event.paramDescriptorForKeyword(fourcharcode('----')).stringValue&lt;br /&gt;  # url now contains the complete URL as a string&lt;br /&gt;  # do your processing of the URL/content...&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's it.  Pretty cool eh?  &lt;a href="http://ranchero.com/netnewswire/developers/externalinterface.php"&gt;Handling events from NetNewsWire&lt;/a&gt; is almost identical (register for them, write a handler function).&lt;br /&gt;&lt;br /&gt;And, one more great thing I could integrate: &lt;a href="http://sparkle.andymatuschak.org/"&gt;Sparkle&lt;/a&gt;.  Sparkle is a superb Cocoa library that does automatic application updates.  It checks the web for a newer version of your app, downloads it, and installs it.  Integrating it is simple, and in fact, depending on your needs, you don't have to write a single line of code.  The only code I wrote for it was actually a Rake task to build the appcast and upload it to the server.  Slick.&lt;br /&gt;&lt;br /&gt;All this could only be done as a native Mac app, which means Cocoa.  But, as said above, doing it with RubyCocoa gives me access to all these abilities, yet, I can do all the more heavy string and XML processing I need to do using Ruby, which is much more effective for me.  Also, the web services calls and code is a lot easier for me to do in Ruby than Cocoa.&lt;br /&gt;&lt;br /&gt;Furthermore, this is plain fun!  Unlike some, I feel desktop apps still have a place, but love webapps at the same time.  With RubyCocoa I can build super cool Mac apps, but do so in a language I'm happier using, yet have the power of Cocoa available to me.  For me, some of the best "applications" these days are such hybrids: a web app that does your primary data storage, and gives you access to the app from "anywhere" (i.e. anywhere you can get to a browser and net connection), but a desktop app to use most of the time for faster interaction, potentially better integration on your desktop system, and so on.  It's the same reason I use Mailplane (desktop app for Gmail), or &lt;a href="http://infinitenil.com/packrat/"&gt;PackRat&lt;/a&gt; (desktop app for Backpack).  I suspect it's the same reason we're seeing other solutions like Adobe Air, or Google Gears.  Technology is so cool, isn't it?!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-8252825373221683539?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/8252825373221683539/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=8252825373221683539' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8252825373221683539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/8252825373221683539'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/01/rubycocoa-rocks.html' title='RubyCocoa Rocks'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7993236103194001990</id><published>2008-01-18T19:19:00.001-08:00</published><updated>2008-01-18T19:19:10.777-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyCocoa'/><title type='text'>Building My First RubyCocoa App - Some Notes</title><content type='html'>Today I started work on my first app built using RubyCocoa, which is now a first class citizen in MacOS X 10.5/Leopard.  I had read the docs and tutorial found &lt;a href="http://developer.apple.com/documentation/Cocoa/Conceptual/RubyPythonCocoa/Introduction/Introduction.html"&gt;here&lt;/a&gt;.  I proceeded, and ran into a few bumps along the way, so here are some notes maybe someone else will find useful...&lt;br /&gt;&lt;br /&gt;The code for the example app RSSPhotoViewer, is not quite the same as that shown in the tutorial.  Specifically:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;The tutorial says you need to put "&lt;tt&gt;ib_action :method_name&lt;/tt&gt;" after your methods that are Actions.  The example code does not do that, and I found I didn't need to do it either.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;The example code does not &lt;tt&gt;require osx/cocoa&lt;/tt&gt; or &lt;tt&gt;include OSX&lt;/tt&gt;, yet I had to do this in my Ruby source code in order for it to recognize the class names properly (or at least so I didn't have to prefix them with OSX).&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I couldn't get Interface Builder to recognize my Ruby window controller class - i.e. it didn't show it's outlets and actions.  I tried a variety of things here, but basically I finally had to go to the command line and run "rake" and let it do a command line build.  I have no idea what that did differently, as I can't see any new files it generated, etc., but that resolved it - now IB can see all my outlets and actions.&lt;br /&gt;&lt;br /&gt;My app wouldn't run, and I got a strange error in Xcode saying "The debugger is still running" etc.  It appears that if your app crashes this will be the case.  And, in this case, Console is your friend.  Open up Console and you should see messages that will help you assess what's gone wrong.  &lt;br /&gt;&lt;br /&gt;And now for the win... dealing with Apple Events.  My app wants to receive a particular apple event from NetNewsWire.  NNW documents this protocol nicely, however, when registering as a handler for the event (using &lt;tt&gt;NSAppleEventManager.sharedAppleEventManager.setEventHandler_andSelector_forEventClass_andEventID_&lt;/tt&gt;), you need to pass in the class and event ID that are not standard ones (they're defined by NNW/external blog protocol).  Well, in Cocoa code, these are just a four character string, but as I found, a string that an unsigned long via string packing.  So, it was a question of how I get these ID's in via Ruby.  Luckily this turned out to be rather simple, as you can use String#unpack.  And, in this case, you pass unpack "N" as the format, which is an unsigned long packed in &lt;b&gt;n&lt;/b&gt;etwork byte order.&lt;br /&gt;&lt;br /&gt;Lastly, debugging.  As mentioned above, Console and such are your friend.  I haven't tried any shenanigans with ruby-debug or such from the command line, so that might work.  But, Xcode can't debug into the Ruby code in your project (it can into the code in main.m just fine though).  So, if you have weird crashes and such, check Console.  Also, use NSLog, or pop alerts or what not.  If someone knows a better way &lt;em&gt;please&lt;/em&gt; do tell.&lt;br /&gt;&lt;br /&gt;Regardless, I'm quite excited by RubyCocoa and have another couple apps that I may do with it.  This app was a small one, and of course is not done in just a couple hours, but it's going to be a nice addition to the tool belt.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7993236103194001990?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7993236103194001990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7993236103194001990' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7993236103194001990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7993236103194001990'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/01/building-my-first-rubycocoa-app-some.html' title='Building My First RubyCocoa App - Some Notes'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-9007591224750422431</id><published>2008-01-17T00:15:00.001-08:00</published><updated>2008-01-17T00:15:03.794-08:00</updated><title type='text'>Sending SMS (Text Message) to Your Phone Using Ruby and iChat</title><content type='html'>Tonight I took a bit more of a look into the various Scripting Bridge and RubyOSA features in MacOS X 10.5/Leopard.  This originated with a quick bit of research on a script that would pull data from the current article being read in NetNewsWire, and send it off somewhere else.  But then seeing a Tweet from a friend, and how he's using Twitter and such, I thought, why not just send SMS directly (more robust in his case).  This led me to the fact that the latest iChat can send SMS's, and knowing that I could drive iChat via Ruby (instead of AppleScript), I investigated.&lt;br /&gt;&lt;br /&gt;With no further ado, here's a simple script to send an SMS to a phone that's in your buddy list (i.e. you've had to sent an SMS to it from iChat previously):&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;    require 'rubygems'&lt;br /&gt;    require 'rbosa'&lt;br /&gt;    &lt;br /&gt;    ichat = OSA::app('iChat')&lt;br /&gt;    myphone = ichat.buddies.select {|buddy| buddy.name == "+18005551212"}.first&lt;br /&gt;    ichat.send2("from ruby!", myphone)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Obviously put in the correct phone number.  You'll need to install the RubyOSA gem:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;    sudo gem install rubyosa&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Anyway, I think this is pretty cool.  One other thing I learned was that you can leverage a neat tool called rdoc-osa that will generate rdoc for a scriptable application!  For example:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;    rdoc-osa --name iChat&lt;br /&gt;    open doc/index.html&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This will generate the docs (placing them in a directory called "doc" in your current directory - you likely want to put it elsewhere if you plan to keep it around), and then the second command obviously will open those up in your browser.  The docs are more of a way to get started, and you'll likely want to combine those (for the Ruby syntax/naming), with the docs from the app's scripting dictionary (pull that up by running Script Editor, and then opening the scripting dictionary of the app you're interested in).&lt;br /&gt;&lt;br /&gt;I should note, you can also do this via the osx/cocoa Ruby library, if for example, you have a full fledged Cocoa app written in Ruby (another super cool thing introduced in/built into Leopard).  But, I find using the RubyOSA stuff just slightly nicer if all you are doing is driving an app via scripting, and aren't doing Cocoa stuff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-9007591224750422431?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/9007591224750422431/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=9007591224750422431' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/9007591224750422431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/9007591224750422431'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/01/sending-sms-text-message-to-your-phone.html' title='Sending SMS (Text Message) to Your Phone Using Ruby and iChat'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-5082470420438696984</id><published>2008-01-11T09:53:00.001-08:00</published><updated>2008-01-11T09:53:09.677-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='GTD'/><category scheme='http://www.blogger.com/atom/ns#' term='Backpack'/><title type='text'>Things: the Ultimate Todo/GTD App?</title><content type='html'>I've finally struck gold when it comes to a todo list/GTD app!  I've recently switched to a new Mac app called &lt;a href="http://culturedcode.com/things/"&gt;Things&lt;/a&gt;, and I couldn't be happier.  Finally, a system that works the way I do, is fast, looks nice, and has everything I need.  Things is produced by &lt;a href="http://culturedcode.com/"&gt;Cultured Code&lt;/a&gt;, who also happen to make the excellent &lt;a href="http://culturedcode.com/xyle/"&gt;Xyle Scope&lt;/a&gt; product.&lt;br /&gt;&lt;br /&gt;For the longest time, I used &lt;a href="http://backpackit.com/?referrer=BPL7B"&gt;Backpack&lt;/a&gt; to manage my todo lists, and I've worked in a semi &lt;a href="http://en.wikipedia.org/wiki/Getting_Things_Done"&gt;GTD&lt;/a&gt; way.  I originally chose Backpack as it was relatively simple, I was using it for other things, and it provided access to my lists anywhere I had access to the 'net.  When I was working at Adobe, and had many computers, plus my home machines, this was valuable.  But, I disdained having to always keep a browser tab open for it, and have it mixed in with other browser use.  I started working on an Apollo app to have a dedicated system for it, but that was in the early days of Apollo when the HTML view was buggy and prevented this app from working effectively.  Along came &lt;a href="http://infinitenil.com/packrat/"&gt;Packrat&lt;/a&gt; and solved it, making a dedicated Backpack app, as well as providing offline storage, and much faster access.  Yea!  I still use this combo today, and that will be the subject of an upcoming post.  But, alas, I was not happy with my todo system.&lt;br /&gt;&lt;br /&gt;Now that I'm using essentially a single machine, and I wanted further speed for this commonly used app, as well as a better overall functionality, I started looking.  This was stimulated when I saw &lt;a href="http://anxietyapp.com/"&gt;Anxiety&lt;/a&gt;, which was a nice HUD implementation of a display for your iCal todos, which I'd been thinking about using to sync to my phone.  I switched and tried it a while.  Not bad, but definitely some issues (Anxiety was a pure viewer (you can add items) - you can't re-order, it doesn't pay attention to priority, and so on).  But I'm babbling, get on with it right?&lt;br /&gt;&lt;br /&gt;I found out about Things, I believe via Twitter I think.  I watched the &lt;a href="http://culturedcode.com/things/screencast.html"&gt;screencast&lt;/a&gt;, which starts a bit slow, but is a good display of the app.  What immediately attracted me was the "Today" view, and it's separation from Next, as well as the abilities to tag, to postpone (with a timered re-add/check for re-add), and the whole Someday system.  &lt;br /&gt;&lt;br /&gt;I had been organizing my stuff more manually into a "to do today" list, and everything else.  It was actually somewhat tedious to manage in Backpack, until they added dragging between lists.  But still, Things just does it naturally and really well.  Simple buttons to move things back and forth between Today and Next, or you can drag.  Also, it pays attention to due dates on tasks, and automatically moves them into Today if they are due today. &lt;br /&gt;&lt;br /&gt;Also, I really like the Areas of Responsibility and the Projects.  I use Areas heavily, and Projects much less, but they are both useful and distinct.  In general I organize all my different "work" items into areas (by client or project, or various other ways), and my personal stuff is area-less, with some exceptions.  The Areas show up as distinct lists, or as separate lists in the Next and Today views.  I could tell you more, but just check out the web site and/or the screencast.&lt;br /&gt;&lt;br /&gt;So, what about web/network storage, and access from multiple machines?  Nope, Things doesn't have this (yet?).  Hasn't bothered me a bit though.  It is an extremely rare day that I don't use Packrat to for Backpack, and with my single computer setup now, I just have much less need.  Things will supposedly have some Export options later, and it's data is stored in an easily accessible and readable XML file, so I could create a simple solution for read-only data if I wanted to at least have it on the web, but I just haven't had the need or desire.  The app itself works so darn well, that this aspect has barely even been on my radar.&lt;br /&gt;&lt;br /&gt;I've looked at a variety of other apps and solutions over the last couple years, but hands down, &lt;a href="http://culturedcode.com/things/"&gt;Things&lt;/a&gt; is the best.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-5082470420438696984?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/5082470420438696984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=5082470420438696984' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5082470420438696984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5082470420438696984'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/01/things-ultimate-todogtd-app.html' title='Things: the Ultimate Todo/GTD App?'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-6268269768716552267</id><published>2008-01-09T14:10:00.001-08:00</published><updated>2008-01-11T15:58:47.123-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visionary'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><category scheme='http://www.blogger.com/atom/ns#' term='screensaver'/><title type='text'>Cocoa Screen Saver Prefs and Bindings (or Not)</title><content type='html'>In my latest work on my &lt;a href="http://cobaltedge.com/index.php/visionary-saver/"&gt;Visionary Saver&lt;/a&gt; screen saver, I had tried switching all my preferences to use Cocoa Bindings, to make it super easy to manage the prefs.  After doing this, and having it appear to work, I realized that it does not.  &lt;br /&gt;&lt;br /&gt;The problem is that screen savers are supposed to use the ScreenSaverDefaults class to manage their preferences.  This is a special Defaults class that namespaces a screen savers defaults/preferences within the defaults system, given that a screen saver is a bundle, and works within System Preferences (as opposed to being its own application).  The reason it doesn't work with bindings is that you can't tell the Bindings system about ScreenSaverDefaults (to my knowledge), in the same way as you can bind to the Shared Defaults Controller.  ScreenSaverDefaults requires a module name, and so on.  If there's a workaround, I'd love to hear it.&lt;br /&gt;&lt;br /&gt;I thus had to go back to manually getting and setting the preferences for Visionary.  This did simplify one thing, which is the preferences settings for an NSPopUpButton, where the content values come from an array, yet the selection and setting should go to preferences.  Personally, NSPopUpButtons, for simple use, are a real pain.  I'm not an Interface Builder expert, but it's odd that you can set up to 3 values into an NSPopUpButton in the UI, as generic text, but if you want more, you have to setup the whole NSArrayController and its content array, and so on, then bind that to the popup, etc, etc.  It's not awful, but the documentation is pretty weak in terms of a straight forward use of something like this.  I suspect many other folks don't have complicated data models behind the values for some of their popup buttons, and a cleaner way to do all this would be nice.&lt;br /&gt;&lt;br /&gt;Anyway, it's all good now, or well, it's all fixed up, and there's a new version of &lt;a href="http://cobaltedge.com/index.php/visionary-saver/"&gt;Visionary Saver&lt;/a&gt; out.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-6268269768716552267?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/6268269768716552267/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=6268269768716552267' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6268269768716552267'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6268269768716552267'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2008/01/cocoa-screen-saver-prefs-and-bindings.html' title='Cocoa Screen Saver Prefs and Bindings (or Not)'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7836085883754109552</id><published>2007-12-28T21:50:00.000-08:00</published><updated>2007-12-28T21:55:30.790-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visionary'/><category scheme='http://www.blogger.com/atom/ns#' term='screensaver'/><title type='text'>New Visionary Saver Version, and Updates</title><content type='html'>The &lt;a href="http://cobaltedge.com/index.php/visionary-saver/"&gt;Visionary Saver&lt;/a&gt; screen saver now has an official home, on my new (and barely going) business site (&lt;a href="http://cobaltedge.com"&gt;Cobalt Edge LLC&lt;/a&gt;).  There is a new version (1.3) out, which mainly adds some additional visualizations.  It is built for Leopard only, and will be this way going forward.  My apologies to anyone running MacOS X versions prior to 10.5.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7836085883754109552?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7836085883754109552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7836085883754109552' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7836085883754109552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7836085883754109552'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/12/new-visionary-saver-version-and-updates.html' title='New Visionary Saver Version, and Updates'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-952527883667488616</id><published>2007-12-28T10:13:00.001-08:00</published><updated>2007-12-28T10:13:09.404-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Slicehost'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Litespeed'/><title type='text'>Installing Litespeed on Slicehost</title><content type='html'>I was trying to install Litespeed on a new slice at Slicehost.  This is an Ubuntu 7.10 setup.  It all seemed to work until I tried to start it up.  It said it couldn't find the binary for lshttpd, but it was there.  Doing some searching finally yielded this &lt;a href="http://www.litespeedtech.com/support/forum/archive/index.php/t-575.html"&gt;thread&lt;/a&gt;, where I realized I just needed to install the 32-bit compatible libraries (since Litespeed is 32-bit).  So, a simple &lt;code&gt;sudo aptitude install ia32-libs&lt;/code&gt; and a re-install of Litespeed did the trick.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-952527883667488616?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/952527883667488616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=952527883667488616' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/952527883667488616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/952527883667488616'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/12/installing-litespeed-on-slicehost.html' title='Installing Litespeed on Slicehost'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-1934247568805897834</id><published>2007-12-22T22:06:00.001-08:00</published><updated>2007-12-22T22:06:04.300-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Drupal'/><title type='text'>Use every tool you can</title><content type='html'>I just spent a chunk of time figuring out a problem with the way the content of one of the sites I work on flows.  We have theme templates, and so on, but all of a sudden the sidebars of the &lt;a href="http://basecampsilverton.com"&gt;site&lt;/a&gt; were no longer sidebars, but shown at the bottom of the page, and there were a few other oddities.  &lt;br /&gt;&lt;br /&gt;We couldn't figure out anything that had been recently changed that would affect this, so I basically had to start sifting through the HTML to try to see what it could be.  I suspected a missing ending div tag or similar, that would thus pull the sidebars into the main content area's div.&lt;br /&gt;&lt;br /&gt;To solve this, I started with the Web Developer plugin in Firefox, but that wasn't leading anywhere.  I checked some things in CSS Edit.  I then used Web Developer's View Source with my associated editor (TextMate) and pulled up the code.  The code was messy as hell (no thanks Drupal and the theme we are using), and using code folding, re-indenting and various things was going to take forever.&lt;br /&gt;&lt;br /&gt;Next up was Dreamweaver.  Voila!  This is probably the third time I've used Dreamweaver in my life, but I opened up the source for the page in it, and turned on it's ability to "Highlight Invalid Code".  Immediately it showed two div tags that did not have closing tags.  Just as I suspected!  Now, how to figure out what code within that was eating the ending div (i.e. that itself did not have ending div's, because I could see that the matching ending div for these particular two divs was there (I'd edited the theme to put in comments showing the matching ending divs).&lt;br /&gt;&lt;br /&gt;Now it was back to TextMate to manually look at the enclosed HTML.  This was tedious for sure, but after some time, I found what looked like some missing closing div's.  I identified which blog entry it was in, went to the site and looked at the content for that blog entry, and voila, wacky use of divs!  This appeared to have been remnants from some kind of formatting the TinyMCE WYSYWYG editor had been doing.  Thankfully we've bailed on TinyMCE and are now using FCKeditor which appears to work much better so far. &lt;br /&gt;&lt;br /&gt;Anyway, wrapping up, I fixed up the two blog entries that had these weird div uses, and voila, that fixed the site layout!  For me at least, I found a new useful tool, which is Dreamweaver, or specifically Dreamweaver's "Highlight Invalid Code" feature.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-1934247568805897834?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/1934247568805897834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=1934247568805897834' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/1934247568805897834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/1934247568805897834'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/12/use-every-tool-you-can.html' title='Use every tool you can'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-2146909961446455648</id><published>2007-12-22T12:09:00.001-08:00</published><updated>2007-12-22T12:09:33.762-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monitoring'/><title type='text'>Monitoring</title><content type='html'>For some of the sites I work on, that are either personal projects, or small, where I'm not going to setup Nagios, Monit, or some other internal or serious solution, I've been looking for monitoring services.  What I've found, and signed up for (all of these), and will compare over the next few weeks are:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://montastic.com"&gt;Montastic&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://mon.itor.us"&gt;mon.itor.us&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://site24x7.com"&gt;Site 24x7&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://monitwitter.com"&gt;MoniTwitter&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Have others to recommend?  Please do tell.  Note, they basically have to be free, or super cheap (which for me right now translates to maybe a couple bucks a month if, and only if, they are providing something more than simple uptime watching and monitoring intervals 10 mins or less (less is great, most of the above range from 5-60 minutes depending).&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-2146909961446455648?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/2146909961446455648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=2146909961446455648' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2146909961446455648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2146909961446455648'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/12/monitoring.html' title='Monitoring'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7032732639696218818</id><published>2007-12-20T17:08:00.001-08:00</published><updated>2008-01-01T14:41:05.983-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Books'/><category scheme='http://www.blogger.com/atom/ns#' term='Amazon'/><title type='text'>Amazon Kindle: First Use Thoughts</title><content type='html'>I received my &lt;a href="http://www.amazon.com/gp/product/B000FI73MA/?tag=codeintensity-20"&gt;Kindle&lt;/a&gt; the other day, and have had a chance to read with it for several hours now.  So far, so great!  I like it quite a bit.  I'm going to keep this short, because the Kindle has been covered a lot elsewhere. &lt;br /&gt;&lt;br /&gt;Things I like:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Trivial setup.  The unit comes completely setup, tied to your account, and included all the books I'd already bought.  All I had to do was turn the thing on and start using it.  I did follow directions and plug it in to charge, which reached full within maybe 15 minutes.  Also, the unit starts right into a quicky getting started, that I found to be just the right length and usefulness.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;The "electronic ink" display is awesome.  You can read this thing in any kind of light, no problems like you'd have with a laptop screen or many other devices.  Very pleasant to read to as well, did not tire my eyes at all after several hours!&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Easy to use UI.  Basically, learn a couple buttons and the scroller and you're done.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Neato features like clippings, search, and bookmarks.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;When the unit is in sleep mode, the display actually has an image on it, and it tells you how to wake it up (in case you forgot ;-)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;What I don't like...  I can really only think of two things to start off:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;No PDF support.  This is a pretty big deal.  I knew this going in, but had read you could convert documents.  You can, but have to use a Windows app, and it's unclear how well it works.  I haven't tried it yet, but plan to.  I was hoping to place some of the existing ebooks I have onto the Kindle this way.  This is hands down my #1 complaint and the thing I truly hope Amazon can remedy.  I understand the reasons, but I'd like to see them solve it, even if it's not ideal.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;The price of subscribing to blogs.  Usually it's cheap, such as $1/month, but really, blogs are free, and yes, obviously this is partially to cover Whispernet fees (which Amazon always says they cover in their docs, but obviously it's built into the price you're paying), and to cover management on your account, but seriously, it's a blog.  How about you give us at least 10 for free, and then make them dirt cheap thereafter.  Or at least don't tell us that you're covering the Whispernet fees.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;All in all, I love this thing so far, and am really excited to see how I use it going forward.  I very much like the idea that I can take this one thing when I travel, instead of having to either figure out what I might want to read ahead of time (I'm usually in the middle of a few books), or take multiple books with me.  Also, nice to have even around the house, for just the ability to grab it and know I've got various reading material on it.&lt;br /&gt;&lt;br /&gt;I will be most curious to see if I try blogs, newspapers, or magazines on it.  Cost wise I probably won't, and I don't get a newspaper as it is (blogs, newspapers/news, I get all online).  Magazines maybe, although most of the ones I read have a good visual component (various cycling mags, National Geographic Adventure and Outside, techy mags which typically don't translate to something like this very well, Wired, or whatever).  Time will tell, but it's pretty cool so far.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7032732639696218818?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7032732639696218818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7032732639696218818' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7032732639696218818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7032732639696218818'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/12/amazon-kindle-first-use-thoughts.html' title='Amazon Kindle: First Use Thoughts'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-9096989023482456621</id><published>2007-11-26T11:57:00.001-08:00</published><updated>2007-11-26T11:57:32.671-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Books'/><category scheme='http://www.blogger.com/atom/ns#' term='Amazon'/><title type='text'>Ordered an Amazon Kindle</title><content type='html'>I bit the bullet and ordered up an &lt;a href="http://amazon.com/gp/product/B000FI73MA/ref=amb_link_5873612_2?pf_rd_m=ATVPDKIKX0DER&amp;amp;pf_rd_s=gateway-center-column&amp;amp;pf_rd_r=0Y9DVYBQ1D126PRJDQRH&amp;amp;pf_rd_t=101&amp;amp;pf_rd_p=329252801&amp;amp;pf_rd_i=507846"&gt;Amazon Kindle&lt;/a&gt; ebook reading device.  I'm a big reader and this thing has serious appeal.  As &lt;a href="http://blogs.smugmug.com/don/2007/11/20/kindle-review/"&gt;Don MacAskill says&lt;/a&gt;, I am often into several books at a time, and don't know what mood I'll be in, so when traveling it's hard to trim down the list to something easy to travel with.  &lt;br /&gt;&lt;br /&gt;I am also very intrigued by its ability to send documents to it, in particular PDF.  The PDF translation (to the MOBI format the Kindle needs) is apparently not perfect, but this is huge, as it'll allow me to take all the ebook versions of tech books I have and use with me.  I always have these on my laptop, but there are times when I want to actually sit down and read some of them (as opposed to just do a quick lookup while coding).&lt;br /&gt;&lt;br /&gt;It's pretty promising, and I promise to review it once I have it, which won't be for a few weeks (mid-December is my approx ship date).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-9096989023482456621?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/9096989023482456621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=9096989023482456621' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/9096989023482456621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/9096989023482456621'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/11/ordered-amazon-kindle.html' title='Ordered an Amazon Kindle'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7496794952690977292</id><published>2007-11-17T22:55:00.001-08:00</published><updated>2007-11-17T22:55:25.370-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kitchen'/><category scheme='http://www.blogger.com/atom/ns#' term='cooking'/><category scheme='http://www.blogger.com/atom/ns#' term='food'/><title type='text'>Killer New Cooking Tools</title><content type='html'>Well, really, I hope they aren't actually "killer", but I am talking about knives, and spinning blades...&lt;br /&gt;&lt;br /&gt;I recently attended a knife skills class, and during the class got to try a slew of different types and brands of knives.  I came away very impressed with &lt;a href="http://shuncutlery.com/products.php?brand=shun"&gt;Shun&lt;/a&gt; knives.  Great feel, cut briliantly, and the food just falls off - no need for the hokey hollow ground divots, etc.  Also, I was able to try the &lt;a href="http://shuncutlery.com/productdetails.php?id=4"&gt;"Ken Onion" Shun knife&lt;/a&gt; in particular.  This knife has a specially designed bolster/handle area, where your fingers can sit in the proper style.  It also rocks really well while cutting.  And technically, there is a whole range of Ken Onion knives know, it just seems that this one was the first and thus is what folks refer to as the Ken Onion.&lt;br /&gt;&lt;br /&gt;A few weeks later I picked up a Ken Onion, a paring knife, and their cool new serrated "&lt;a href="http://www.cooking.com/products/shprodde.asp?SKU=582612"&gt;Ultimate utility knife&lt;/a&gt;" (I couldn't find this on Shun's site, so the link is to the online store of the place I bought it from).  I also took in my Wusthof Grand Prix knifes to be sharpened.  These have been great knives, but I actually think I will sell the two cook's knives and paring knife now that I have the Shuns.  Eventually I will replace the others as well.&lt;br /&gt;&lt;br /&gt;I returned a bit later to pick up my Wusthof's, and low and behold, the Shun rep was there for the day.  I talked to him for maybe 10 minutes (I was actually in a hurry at the time).  Luckily he clued me in that "diamond fingers" sharpeners, which work rally well on German/stainless steel, shouldn't be used on VG10 steel of Shun knives.  I thus got &lt;a href="http://shuncutlery.com/productdetails.php?id=265"&gt;Shun's sharpening steel&lt;/a&gt;, which handily has a properly angled bolster on it to help you be certain you are maintaining the proper angle on your edge.&lt;br /&gt;&lt;br /&gt;Finally, somewhere in all this, I also picked up a &lt;a href="http://www.vikingrange.com/consumer/products/category_microcategory.jsp?id=cat5130003"&gt;Viking immersion/hand blender&lt;/a&gt;.  I got a chance to use it for the first time tonight, and WOW, that thing rocks!  Made itself worth it in one use.  I was making potato leek soup, which needs to get pureed, and previously I had to do this by taking stuff out in batches and putting it in a food processor/blender - a total pain.  With the immersion blender, obviously, you just pop the thing in the soup pot, and blend for seconds (it probably took me 20 seconds).  This is going to be one nice addition to the kitchen tool chest.&lt;br /&gt;&lt;br /&gt;Oh, one note on the Viking vs. others.  The Viking is extra powerful and has two speed settings.  The first speed setting is what most immersion blenders can dole out, the second is turbo.  Also, it's blade guard/bottom area is a nice design that lets the food flow out much better than many of the others that have holes, but where those holes aren't open to the bottom.  It also comes with a whisking attachment, and others are available (I got a mini-chopper one with mine due to a current promotion). &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7496794952690977292?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7496794952690977292/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7496794952690977292' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7496794952690977292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7496794952690977292'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/11/killer-new-cooking-tools.html' title='Killer New Cooking Tools'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-9072707920870866819</id><published>2007-11-12T10:46:00.001-08:00</published><updated>2007-11-12T10:46:09.070-08:00</updated><title type='text'>Open Source, Linux-based, New Wireless Protocol Bike Computer</title><content type='html'>This is really amazing - an open source, Linux based, bike computer/cyclometer, that does GPS, heart rate, power metering, and all the usual other cyclometer stuff (speed, distance, etc.).  The system is fully hackable, an intended to be hacked.  They are also using Ant +Four, which is like Bluetooth for bikes.  I blogged about this more, including the link to the video showing it, the company, etc, etc., on my &lt;a href="http://mountain-monkeys.com/2007/11/12/incredible-new-bike-gpspower-metercyclometer-open-source/"&gt;Mountain Monkeys&lt;/a&gt; blog.  Check it out, quite cool.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-9072707920870866819?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/9072707920870866819/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=9072707920870866819' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/9072707920870866819'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/9072707920870866819'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/11/open-source-linux-based-new-wireless.html' title='Open Source, Linux-based, New Wireless Protocol Bike Computer'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-1537876668592828669</id><published>2007-11-11T18:27:00.001-08:00</published><updated>2007-11-12T15:36:07.953-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><category scheme='http://www.blogger.com/atom/ns#' term='Leopard'/><title type='text'>What Leopard Changed for Me</title><content type='html'>I've been running Leopard for about two weeks or so now.  It has not been the usual OS update where it has some nice eye candy improvements and some underpinning changes, but doesn't essentially affect the apps I run.  Leopard has directly impacted the apps I run.  There are also some that I've chosen not to switch to.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Documentation?!&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;But first, wow, the little printed booklet that comes with Leopard... wow, a) I actually read it, and b) the info in it was actually useful!  Hath hell froze over?!  Printed documentation of value?!  Woah nelly!  Even better, it was short, easy to read, and to the point, with almost zero fluff.  Way to go Apple.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The app changes...&lt;/h3&gt; &lt;br /&gt;&lt;br /&gt;Not a lot, but a couple key ones.  As I mentioned in a &lt;a href="http://codeintensity.blogspot.com/2007/11/new-tools.html"&gt;previous post&lt;/a&gt;, I am no longer using Path Finder, because regular Finder has some great improvements, picks up some of the key features I used Path Finder for, and it eliminates needing an additional app, that didn't integrate as seamlessly as you'd hope.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;b&gt;Update (12 Nov 2007):&lt;b&gt; A &lt;a href="http://feeds.tuaw.com/~r/weblogsinc/tuaw/~3/183668444/"&gt;new version of Path Finder&lt;/a&gt; has been released that integrates MUCH better with Leopard, including supporting Quick View, and having an "Open in Finder" replacement that works completely.  I'll have to see if I go back again to using Path Finder...&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Second is iChat.  The jury is still out on this one to be honest, but the fact that you can now login to multiple accounts on a single network (Jabber for me), all the video and screen sharing enhancements, and again, one less app to install and keep up to date, has led me to stop using Adium for now.  We'll see.  I've tried before, and iChat was not up to par, but this time it's looking like a replacement.&lt;br /&gt;&lt;br /&gt;Other bits...  Stacks are pretty cool, especially when you add &lt;a href="http://t.ecksdee.org/post/19001860"&gt;overlays&lt;/a&gt; to keep them straight.  Quick View rocks.  Safari is definitely better, and thankfully the one feature Safari cannot seem to implement, for who knows what reason, is still solved by Saft.  This is the feature of it remembering all the tabs you had open when you close the browser, and re-opening it with that.  Saft also adds a great feature, which is to allow you to edit Text Area's with your favorite editor.  This is key for me (I use(d) a similar plugin with Firefox).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What hasn't changed...&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Time Machine.  Yep, I am not a convert.  Admittedly I haven't looked at every option, etc., but I'm a &lt;a href="http://www.shirt-pocket.com/SuperDuper/"&gt;Super Duper!&lt;/a&gt; fan.  Why?  First I don't really need multiple revisions of files - any files I do need that for are already in a version control system.  Second, one of the key features of Super Duper (or similar) backups, is that I have a complete clone of my drive, that I can boot off of.  This has saved me a few times.  What happens if your hard drive goes bad or something happens to your system.  Fine, you restore from backup.  But, what if you are in a time bind and you really need access to your files?  Well, you can just boot off your backup, work there for a short bit, and then perform your restore/redo when time permits.  No biggy.  Yes, you lose whatever was changed between the time you did you clone backup and the current time, but for me that is often very little (due to what really matters being in version control, or being backed up by Jungle Disk every 15 minutes).&lt;br /&gt;&lt;br /&gt;I still don't use Apple Mail.  In fact, these days I don't use a desktop mail program, or rather, one that I POP or IMAP mail with.  I use Mailplane, and all my email accounts are Gmail accounts (I have a half dozen or more at this point).  Works extremely well for me.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-1537876668592828669?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/1537876668592828669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=1537876668592828669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/1537876668592828669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/1537876668592828669'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/11/what-leopard-changed-for-me.html' title='What Leopard Changed for Me'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-6113427743672110363</id><published>2007-11-11T00:06:00.001-08:00</published><updated>2007-11-11T00:06:18.904-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><title type='text'>XD</title><content type='html'>&lt;p&gt;The blog post, &lt;a href="http://t.ecksdee.org/post/19001860"&gt;Dock Stack Overlays&lt;/a&gt; on the XD blog is really cool.  It shows you how to put an overlay icon on your dock stacks, so that you always know which stack is which.  This is incredibly useful if you use stacks (or more than one stack anyway).  Great stuff.&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-6113427743672110363?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/6113427743672110363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=6113427743672110363' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6113427743672110363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6113427743672110363'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/11/xd.html' title='XD'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-3512979999518915949</id><published>2007-11-10T20:49:00.001-08:00</published><updated>2007-11-12T15:35:53.866-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySQL'/><category scheme='http://www.blogger.com/atom/ns#' term='mind mapping'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='fonts'/><category scheme='http://www.blogger.com/atom/ns#' term='Flickr'/><category scheme='http://www.blogger.com/atom/ns#' term='Backpack'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>New Tools</title><content type='html'>I've been using a few new tools lately, and also got rid of one I've used a long time.  First up, now that I'm running Leopard on my Macs, I've found I just don't need or want Path Finder.  Path Finder has been great, I've used it for a few years now.  But, with the new features in Finder, and the niggling issues I've had with Path Finder, it was finally time to end my use.  The Finder's new sidebar, stacks, quick look, and the fact that you can show the directory path at the bottom of Finder windows (this was a big-little feature in Path Finder for me), brought me back to using it.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;b&gt;Update (12 Nov 2007):&lt;b&gt; A &lt;a href="http://feeds.tuaw.com/~r/weblogsinc/tuaw/~3/183668444/"&gt;new version of Path Finder&lt;/a&gt; has been released that integrates MUCH better with Leopard, including supporting Quick View, and having an "Open in Finder" replacement that works completely.  I'll have to see if I go back again to using Path Finder...&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Some new tools, both web and Mac that I've been using a fair bit lately include:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;a href="http://www.mindmeister.com/"&gt;Mind Meister&lt;/a&gt;&lt;/h3&gt;&lt;br /&gt;I haven't used mind mapping tools much in the past.  I've tried various ones several times, but they either were too cumbersome, too slow, or just didn't seem useful.  I found out about MindMeister from someone on Twitter, and have a couple mind maps running on it now.  I'm also collaborating on one of them with others.  MM is fairly preferment, quite easy to use, nice to look at, and the collaboration bit is super nice.  I'd like to see them add a way to insert a URL/link, where that link could be clicked on, but that's about the only issue I have so far.  Interesting to note, if you get the Premium account (a measly $4/month!), they have offline editing.  They are using Google Gears for this.  Another intriguing bit is that they have an API.  I haven't looked into this yet, or haven't thought about how I'd use it, but I always like to see services that have this as an option.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;a href="http://www.red-sweater.com/marsedit/"&gt;Mars Edit 2&lt;/a&gt;&lt;/h3&gt;&lt;br /&gt;The 2.0 version, now produced by Red Sweater Software is quite nice.  In days of old, I'd preferred ecto, but this new version is simple, effective, fast, and quite nicely, has great Flickr integration.  I've been using Flickr quite a bit, especially with my other blog, and often put multiple photos in a post.  Mars Edit makes this trivial.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;a href="http://www.navicat.com/"&gt;Navicat&lt;/a&gt;&lt;/h3&gt;&lt;br /&gt;Navicat is a GUI database tool.  I used to use CocoaMySQL, and YourSQL and such on Mac, but YourSQL doesn't seem to work these days, and CocoaMySQL seems out of date, and I think wasn't under development anymore(?).  Navicat, while a commercial product, has been rock solid, and I've found to be quite useful.  Admittedly, I use it a lot of simple browsing, simple queries and value changes, etc., but the dependability and quality of it have kept it in my tool chest (and got me to buy it).  One other nice thing here is that while it has a real Mac UI, it is a tool also available on Linux and Windows.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;a href="http://flyingmeat.com/acorn/"&gt;Acorn&lt;/a&gt;&lt;/H3&gt;&lt;br /&gt;Acorn is a slick, simple new image editor by Gus Mueller of Flying Meat Software (likely better known for VoodooPad).  It's extremely fast to load up, and I'm finding it's my top pick to do things like saving images in another format (if they aren't in my &lt;a href="http://www.adobe.com/products/photoshoplightroom/"&gt;Lightroom&lt;/a&gt; library - otherwise I use Lightroom), make minor tweaks, crops, etc.  The speed is one of the best things - it launches super fast, and is very fast to use, so it's an excellent tool for quick work.  Interesting note: you can write plugins in Python or Objective-C.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;a href="http://infinitenil.com/packrat/"&gt;Pack Rat&lt;/a&gt;&lt;/h3&gt;&lt;br /&gt;I use 37 Signals &lt;a href="http://backpackit.com/?referrer=BPL7B"&gt;Backpack&lt;/a&gt; extensively.  It's my GTD system, and I keep tons of notes and information I need in it.  Backpack's web interface is somewhat slow, especially if you switch between various pages a lot (and don't want to keep said pages in lots of browser tabs).  I have a half completed AIR app to be my Backpack client, but Pack Rat seems to be the ticket now.  It has synchronization, offline editing, and so on.  I am sold, and have essentially not used my browser for Backpack since.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Panic Sans font&lt;/h3&gt;&lt;br /&gt;Last, but certainly not least, is the Panic Sans font.  This is a fixed width font, great for coding.  I've been using the Bitstream Vera Sans Mono font for quite some time, but &lt;a href="http://duncandavidson.com/archives/654"&gt;Duncan's recent post&lt;/a&gt; about this discovered a few new ones.  Panic Sans is actually a font found inside the &lt;a href="http://www.panic.com/coda/"&gt;Coda&lt;/a&gt; app's package.  It's very similar to Bitstream Vera Sans Mono, but slightly nicer.  Duncan's post has good info in that particular post, but also see some of his &lt;a href="http://duncandavidson.com/archives/659"&gt;followup&lt;/a&gt; &lt;a href="http://duncandavidson.com/archives/657"&gt;posts&lt;/a&gt; on the subject.&lt;br /&gt;&lt;br /&gt;What's new in your tool chest?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-3512979999518915949?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/3512979999518915949/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=3512979999518915949' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3512979999518915949'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3512979999518915949'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/11/new-tools.html' title='New Tools'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-594642149065766116</id><published>2007-11-07T20:42:00.001-08:00</published><updated>2007-11-07T20:42:41.093-08:00</updated><title type='text'>lselect: great Finder toolbar addition</title><content type='html'>&lt;a href="http://anoved.net/lselect.html"&gt;lselect&lt;/a&gt; is a really handy Finder toolbar addition.  It lets you select files, in Finder, using globs, just as you would on the command line.  On the lselect page, if you download the "lselect-toolbar-app.zip", expand that somewhere (e.g. where they suggest on the web page), then drag it up to your Finder's toolbar to add it.  Now, wherever you are in Finder, if you click this new toolbar button, it'll show you a dialog that lets you type in a glob pattern, and will then select all the files in your current location based on that glob.  Pretty slick.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-594642149065766116?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/594642149065766116/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=594642149065766116' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/594642149065766116'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/594642149065766116'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/11/lselect-great-finder-toolbar-addition.html' title='lselect: great Finder toolbar addition'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-2220597230368305862</id><published>2007-11-05T16:35:00.000-08:00</published><updated>2007-11-05T16:41:55.952-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='coffee'/><category scheme='http://www.blogger.com/atom/ns#' term='Espresso'/><title type='text'>WBC Champ Makes More Coffee Than Espresso - What's Happening?!</title><content type='html'>In Jimseven's (aka James Hoffman) &lt;a href="http://www.jimseven.com/2007/11/04/my-increasing-reliance-on-scales/"&gt;latest blog entry&lt;/a&gt;, he says that he makes very little espresso these days in comparison to how much &lt;a href="http://www.chemexcoffeemaker.com/"&gt;Chemex&lt;/a&gt; or press coffee he makes.  This caught my attention as he's mentioned the Chemex a lot.  I of course take note, given that this guy (jimseven is James Hoffman) is the 2007 World Barista Champion.  Not that baristas don't make "regular coffee", but the WBC is all about espresso, and so on.&lt;br /&gt;&lt;br /&gt;I like experimenting, and am tempted to get a Chemex just to see, but it seems almost every time I drink "coffee", it is rarely enjoyable (of course most espresso from cafes here in the US at least sucks as well).  The other thing that is a big discussion in the coffee world these days is the &lt;a href="http://cloverequipment.com/home/Default.aspx"&gt;Clover&lt;/a&gt; machine, which is basically sort of like an espresso machine, but for coffee, in that it makes one cup of coffee at a time, with grounds made separately, measured precisely, and so on.  Some of the higher end coffee houses are getting them (Ritual in SF had one when I was there a few weeks ago, so I got to see it in person ;-)  They are also a machine you can put on the net, and you can have it track all the coffees you make, as well as program it with various settings so you can just say, make a #3, which you know is all the settings you use with a particular coffee, etc.  I think the machines cost several thousand bucks, so they aren't likely a home machine (and they may require a water connection).  Of course Mark Prince of CoffeeGeek doesn't really like Clover coffee, for many of the same reasons I tend to not like coffee in general, which is that he claims it has almost no "body".  &lt;br /&gt;&lt;br /&gt;That's like coffee in general for me, in that espresso is this complete mouth experience, in that it has real density to it, and does all sorts of things to your tongue, much in the same way wines do, etc.  Maybe I've just had too few good cups of "coffee", but coffee usually just winds up tasting like flavored brown water to me, as opposed to a liquid in its own category.&lt;br /&gt;&lt;br /&gt;Note, I mean no offense at any of this, as one thing I love about the coffee world is the range of different preparations and opinions on what is great, etc.  So, any of you espresso lovers out there, should I bother trying a Chemex?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-2220597230368305862?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/2220597230368305862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=2220597230368305862' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2220597230368305862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2220597230368305862'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/11/wbc-champ-makes-more-coffee-than.html' title='WBC Champ Makes More Coffee Than Espresso - What&apos;s Happening?!'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-2048994299294730478</id><published>2007-10-31T21:53:00.000-07:00</published><updated>2007-10-31T21:59:55.122-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CSA'/><category scheme='http://www.blogger.com/atom/ns#' term='food'/><category scheme='http://www.blogger.com/atom/ns#' term='Eugene'/><title type='text'>First CSA a Hit So Far</title><content type='html'>I only learned about CSA's (Community Supported Agriculture) this year.  They are beyond plentiful in Eugene, with I think something like 40-60 providers.  We signed up for a fall CSA with &lt;a href="http://groundworkorganics.com/"&gt;Groundwork Organics&lt;/a&gt;.  What this is, is a weekly delivery of locally, and with our choice, organically grown produce.  In the spring we will likely sign up for multiple of them, with potentially one doing dairy and/or meat as well.  Anyway, it's been really great so far.  They provide a bunch of things that we wouldn't usually buy, or in some cases, have never even heard of!&lt;br /&gt;&lt;br /&gt;We've had I think 3 deliveries now.  Each week we've gotten 1-2 pounds of lettuce/greens (lots of spinach, field greens), a bunch or three of carrots, and then things like parsnips, beets, dill, Italian parsley, watercress, squash, potatos, onions, arugala, garlic, leeks, and more.  The apples we got last week are the most flavorful apples I've had in a long time (they were "Liberty" apples I believe).&lt;br /&gt;&lt;br /&gt;The delivery we got today included leeks, red potatos, and dill, with a recipe to go along with it (they always include recipes).  It also included "Delicata squash" (roughly 8-10" long, white with green veins, and tubular, maybe 4" in diameter), with a recipe, and we'll try that out.  I don't think we've bought salad greens at the market for a month due to this, which is great.&lt;br /&gt;&lt;br /&gt;We've tried several things we have either never had, or needed to go find recipes to figure out what to do with it, etc. (the roasted parsnips were yummy).  We used a bunch of the salad greens, carrots, etc. tonight, and I roasted up 4 heads of garlic as well.&lt;br /&gt;&lt;br /&gt;I can't wait to see what the next one brings us, as well as what we sign up for in the spring (when the real CSA season occurs).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-2048994299294730478?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/2048994299294730478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=2048994299294730478' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2048994299294730478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2048994299294730478'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/10/first-csa-hit-so-far.html' title='First CSA a Hit So Far'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-2224264136606943244</id><published>2007-09-25T16:51:00.001-07:00</published><updated>2007-09-25T16:51:16.376-07:00</updated><title type='text'>New Espresso Machine Update</title><content type='html'>&lt;div style="float: right; margin-left: 10px; margin-bottom: 10px;"&gt; &lt;a href="http://www.flickr.com/photos/chrisrbailey/1440302068/" title="photo sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1261/1440302068_4cabd923b2_m.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt; &lt;br /&gt; &lt;span style="font-size: 0.9em; margin-top: 0px;"&gt;  &lt;a href="http://www.flickr.com/photos/chrisrbailey/1440302068/"&gt;VivaceFirstPours-3&lt;/a&gt;  &lt;br /&gt;  Originally uploaded by &lt;a href="http://www.flickr.com/people/chrisrbailey/"&gt;Christopher Bailey&lt;/a&gt; &lt;/span&gt;&lt;/div&gt;So things have been continuing to improve in terms of my shots out of the new espresso machine.  I've been getting more consistent and higher overall level of shots these days.  A few things I'm finding important (some of this is obvious, well documented, etc., some slightly different, etc.)...&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;The grind is super important.  I haven't been making hardcore truly micro adjustments yet (I haven't sat down and pulled zillions of shots in a row to experiment at that level yet), but I am making smaller adjustments and dialing things each day, etc.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The freshness of the beans makes a huge difference!  This may seem obvious, but I'm finding that I now won't even bother with anything that isn't dated, and current&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The roast of the beans is critical as well.  Anything "over roasted" (extra dark and oily), is just pointless for me.  I've yet to pull a good cup with one of those, and I have no interest in them it seems, since they seem to lose the caramel and subtle flavors, and enhance the roast/smoky flavor.  As I've known, but now proved further, I too am in the "Northern Italian" camp for bean choice.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I've had great success using a grounds distribution technique I saw at Wandering Goat: I use the side of the palm of my hand to distribute the grounds, and mostly just back and forth, but ensuring that I get a really even distribution, and proper amount of grinds.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Better on my tamp pressure, and more consistent.  Don't tamp the crap out of it, do indeed stick to the ~30lbs force, which is not as much as it seems.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Right now I'm awaiting arrival of my bottomless/crotchless portafilter, as well as a custom handmade tamper from Thor Tampers.  &lt;br /&gt;&lt;br /&gt;The best shot I've made to date is from &lt;a href="http://www.zokacoffee.com/product.php/23/6/"&gt;Zoka Paladino&lt;/a&gt; beans, later in their life (probably about 10 days I think).  Great taste, and then brilliant aftertaste, with the effect on your tongue the same as a wine with heavy tannins (sort of drys it out), and superb chocolate flavors coming out.  This is pretty cool because usually Zoka is more on the smoky side for me, so this was a real transition.  The shot in this picture used &lt;a href="http://www.espressovivace.com/for_home.html"&gt;Vivace Dolce&lt;/a&gt;.&lt;br clear="all" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-2224264136606943244?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/2224264136606943244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=2224264136606943244' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2224264136606943244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/2224264136606943244'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/09/new-espresso-machine-update.html' title='New Espresso Machine Update'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm2.static.flickr.com/1261/1440302068_4cabd923b2_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-6593186231823649181</id><published>2007-09-24T21:01:00.000-07:00</published><updated>2007-12-10T22:00:38.144-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Installing Ruby MySQL Gem with MacPorts MySQL</title><content type='html'>Blogging this more for my own record, but maybe others will find it useful...  Tonight I was having a hard time getting the MySQL Ruby Gem installed on a new MacBook Pro.  I have installed Ruby, Rails, RubyGems, MySQL, etc. via MacPorts (or via the Ruby that was installed via MacPorts).  Anyway, this is the command that finally got it to work:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;sudo gem install mysql -- --with-mysql-include=/opt/local/include/mysql5 --with-mysql-lib=/opt/local/lib/mysql5 --with-mysql-config=/opt/local/lib/mysql5/bin/mysql_config&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Update: as I mention in my comment below (updating here in case folks don't read the comments), when doing this on Leopard/MacOS X 10.5, I needed to change it to:&lt;/span&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;sudo env ARCHFLAGS="-arch i386" gem install mysql -- --with-mysql-include=/opt/local/include/mysql5 --with-mysql-lib=/opt/local/lib/mysql5 --with-mysql-config=/opt/local/lib/mysql5/bin/mysql_config&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-6593186231823649181?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/6593186231823649181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=6593186231823649181' title='19 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6593186231823649181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6593186231823649181'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/09/installing-ruby-mysql-gem-with-macports.html' title='Installing Ruby MySQL Gem with MacPorts MySQL'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>19</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-394497017832643749</id><published>2007-09-12T21:40:00.001-07:00</published><updated>2007-09-12T21:40:54.959-07:00</updated><title type='text'>My New Espresso Setup</title><content type='html'>&lt;div style="float: right; margin-left: 10px; margin-bottom: 10px;"&gt; &lt;a href="http://www.flickr.com/photos/chrisrbailey/1369889626/" title="photo sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1004/1369889626_aaad9ba5e5_m.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt; &lt;br /&gt; &lt;span style="font-size: 0.9em; margin-top: 0px;"&gt;  &lt;a href="http://www.flickr.com/photos/chrisrbailey/1369889626/"&gt;My new espresso setup&lt;/a&gt;  &lt;br /&gt;  Originally uploaded by &lt;a href="http://www.flickr.com/people/chrisrbailey/"&gt;Christopher Bailey&lt;/a&gt; &lt;/span&gt;&lt;/div&gt;Today I finally got to getting the new espresso machine all setup, in its final (for now?) resting place, and started to pull some shots.  So far, average, but I'm just starting to learn to dial in the grinder, tamping, shot duration; and I'm not using a coffee I've liked that much (but it was free with the purchase, and I figured I might as well start out with something I didn't mind wasting a lot of shots of :)  Anyway, all the pictures are here:&lt;br /&gt;&lt;br /&gt;http://flickr.com/photos/chrisrbailey/sets/72157601979329896/&lt;br /&gt;&lt;br /&gt;Initial impressions...  First, I was pissed for a short while, because the machine didn't work out of the box!  It didn't heat up properly.  I called tech support, and they pointed me to instructions on how to reset the Hi Limit on the temperature.  Did that to no avail.  Then, as I simply looked around the insides of the machine, I saw a friggin wire was not connected!  It was just off the terminal (used those nice plastic enclosed flat connectors), so it was real obvious where it went.  Plugged that in, and voila, everything good now.  Phew.  Bad start though.&lt;br /&gt;&lt;br /&gt;Getting past that, holy shite... The first thing you notice is the weight!  Super heavy: 61 pounds!  The other thing that simply rocks is the sheer amount of metal, the entire thing is stainless steel, or brushed steel (the internals of the drip tray are brushed metal, seems like everything else is stainless).  It is incredibly beautiful at the same time as being totally kick ass industrial.  &lt;br /&gt;&lt;br /&gt;Next, nice big steam wand, dedicated hot water wand (very convenient for warming cups),  burly lever action, heavy portafilter with E61 grouphead, and simple to use (mechanically - putting aside the art and science of pulling a perfect shot).  On to the actual espresso...&lt;br /&gt;&lt;br /&gt;So, first I ran a bunch of pre-ground Illy through that I had from buying the an Illy cup collection (&lt;a href="http://www.illy.com/usa/expression/illy_collections/cup_gallery/No_Water_No_Coffee_2002.htm"&gt;No Water, No Coffee&lt;/a&gt;).  That simply gave me a feel for pulling a shot, but the results sucked (minimal, crappy crema).  After a half dozen of those, I fired up the new &lt;a href="http://www.chriscoffee.com/products/home/grinders/mc4"&gt;Macap MC4 doserless grinder&lt;/a&gt;.  I filled it up with Malabar Gold, as that came for free with the machine, and while this may seem odd to some, it was a roast I hadn't liked much in the past.  I figured I might as well waste a bunch of something I didn't care much for, while I started tuning the grinder, etc.  Instantly I was at least getting crema, and better shot times (I was pulling doubles for all these, so approx 25 seconds).  &lt;br /&gt;&lt;br /&gt;After a couple, I started futzing with the grind setting, dialing it finer, to slow the shots down a bit, and thicken things up.  I'm still playing, but I can at least pull something I find reasonable to drink.  I will by no means claim to be pulling stellar shots at this point.  It's at least thicker flavor and such than my super-auto, but it's definitely not honey yet.  &lt;br /&gt;&lt;br /&gt;I haven't even touched steaming yet, and probably won't for some time&lt;br /&gt;&lt;br /&gt;Finally, I'm reading &lt;a href="http://www.amazon.com/Espresso-Coffee-Professional-David-Schomer/dp/0897166159/ref=pd_bbs_sr_1/103-0100291-7012663?ie=UTF8&amp;s=books&amp;qid=1189658391&amp;sr=8-1"&gt;David Schomer's book&lt;/a&gt; (from what I understand, THE reference).  I'm not too far in yet, but so far it's an easy, and seemingly good read, and I assume I'll learn a ton. &lt;br /&gt;&lt;br /&gt;All in all, the journey has started.  Interestingly, I recently found out that the "&lt;a href="http://www.bestcoffeeschool.com/"&gt;Best Coffee School&lt;/a&gt;" is right here in Eugene.  That's the actual name of the place, and apparently people from all over the world come to get schooled here.  They offer courses that range from basics, up to the longest course which trains you to run your own cafe and on the last/graduation day, the class runs their cafe.&lt;br clear="all" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-394497017832643749?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/394497017832643749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=394497017832643749' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/394497017832643749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/394497017832643749'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/09/my-new-espresso-setup.html' title='My New Espresso Setup'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm2.static.flickr.com/1004/1369889626_aaad9ba5e5_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7990206240201320272</id><published>2007-09-06T13:07:00.001-07:00</published><updated>2007-09-06T13:11:43.808-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='startup'/><category scheme='http://www.blogger.com/atom/ns#' term='Indi'/><category scheme='http://www.blogger.com/atom/ns#' term='business'/><title type='text'>First Day of Being an Indi</title><content type='html'>Yesterday was my first day of being an "Indi", as in an independent contractor/web worker/having my own company, etc.  I'm working on some contracts, started the process on forming an LLC, etc.  I decided to use MyCorporation.com for the LLC formation, to lessen the amount I need to do.  They called me this morning to say everything was in order, and they're submitting my forms, etc.  I also bought the .com and .net domain names for the new company (name forthcoming, once I ensure the LLC goes through).  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I now need to get the logo worked on, bank account, and AMEX card, finish evaluating hosting providers and so on.  I plan to be building a few web apps of my own, with hopes that I can grow that into what makes my living, but will also be working part time for a company to start off (and have a guaranteed source of income).  I'm loving this already...&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7990206240201320272?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7990206240201320272/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7990206240201320272' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7990206240201320272'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7990206240201320272'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/09/first-day-of-being-indi.html' title='First Day of Being an Indi'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-6082412973744100137</id><published>2007-09-03T20:30:00.001-07:00</published><updated>2007-09-03T20:30:35.567-07:00</updated><title type='text'>Early September Sunsets</title><content type='html'>&lt;div style="float: right; margin-left: 10px; margin-bottom: 10px;"&gt; &lt;a href="http://www.flickr.com/photos/chrisrbailey/1316865179/" title="photo sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1241/1316865179_a26487c0a8_m.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt; &lt;br /&gt; &lt;span style="font-size: 0.9em; margin-top: 0px;"&gt;  &lt;a href="http://www.flickr.com/photos/chrisrbailey/1316865179/"&gt;EarlySeptSunsets-13&lt;/a&gt;  &lt;br /&gt;  Originally uploaded by &lt;a href="http://www.flickr.com/people/chrisrbailey/"&gt;Christopher Bailey&lt;/a&gt; &lt;/span&gt;&lt;/div&gt;We very frequently get amazing sunsets here at our house in Eugene.  Tonight's was another great one, and while I decided late to get my camera out, still got a few decent images.  &lt;br /&gt;&lt;br /&gt;Here's the &lt;a href="http://flickr.com/photos/chrisrbailey/sets/72157601851511471/"&gt;collection of five&lt;/a&gt; that I got tonight.&lt;br clear="all" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-6082412973744100137?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/6082412973744100137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=6082412973744100137' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6082412973744100137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6082412973744100137'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/09/early-september-sunsets.html' title='Early September Sunsets'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm2.static.flickr.com/1241/1316865179_a26487c0a8_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7439396964123044273</id><published>2007-09-03T09:49:00.000-07:00</published><updated>2007-09-03T10:04:14.706-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='coffee'/><category scheme='http://www.blogger.com/atom/ns#' term='Espresso'/><title type='text'>New Espresso Machine and Grinder</title><content type='html'>I'm finally stepping up to very serious espresso machine (and likely selling my super-auto).  I just purchased an &lt;a href="http://www.wholelattelove.com/Expobar/brewtus.cfm"&gt;Expobar Brewtus II&lt;/a&gt; machine.  My understanding is that this is the creme de la creme of machines, unless you can shell out over $4000 for a La Marzocco GS/3, which is the ultimate home machine (and would actually kick the ass of many of the machines used in cafes and so on).  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For a grinder, I finally decided on a &lt;a href="http://www.chriscoffee.com/products/home/grinders/mc4"&gt;Macap MC4C83R Doserless&lt;/a&gt;.  The big learning point was about going doserless, which is the way to go for a home machine, because you don't pull shots constantly, and thus extra grounds would get left in a doser, going stale quickly.  I looked at various grinders and discussed a lot with cafe folks I trusted, friends who'd researched it, a few key blogs, &lt;a href="http://www.coffeegeek.com"&gt;CoffeeGeek&lt;/a&gt;, &lt;a href="https://www.chriscoffee.com/"&gt;Chris Coffee&lt;/a&gt; (or specifically Chris, from Chris Coffee), etc.  The doserless Rocky is the usual starting point, but various reasons led me away.  First, the finish/appearance.  Sure, that's not the most important point, but when you have a beautiful chrome machine, you don't want a black, plastic grinder sitting next to it.  Second, it's burrs won't last as long, and aren't as good as those of a Macap or Mazzer.  How about a Mazzer Mini?  Well, they have a doser, and the doserless one, the Mini E, or Mini Electric costs $700 - so you are basically paying more than $200 MORE to go doserless (when in fact, you'd think you'd go less for not having a doser (although it does have extra electronics I guess).  The Macaps rival the Mazzers in grind quality, so no hesitation there.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I also picked up a Bumper tamper, knock box, and tamper stand, and some cleaning supplies, etc.  All this stuff should arrive this week, so I'm pretty excited.  &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7439396964123044273?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7439396964123044273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7439396964123044273' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7439396964123044273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7439396964123044273'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/09/new-espresso-machine-and-grinder.html' title='New Espresso Machine and Grinder'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-6421216803253624538</id><published>2007-09-01T22:15:00.000-07:00</published><updated>2007-09-02T08:52:29.121-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Oregon'/><category scheme='http://www.blogger.com/atom/ns#' term='Marche'/><category scheme='http://www.blogger.com/atom/ns#' term='restaurants'/><category scheme='http://www.blogger.com/atom/ns#' term='Eugene'/><title type='text'>Eugene Restaurant Review: Marché</title><content type='html'>I had been told that Eugene had a lot of great restaurants.  We've been here for a few months now, and I hadn't really felt that Eugene had lived up to that, in fact, I'd been fairly disappointed so far.  Tonight changed that in a big way.  My wife, parents, and I had dinner at &lt;a href="http://www.marcherestaurant.com/home.php"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Marché&lt;/span&gt;&lt;/a&gt;.  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Dinner was superb!  All of us thoroughly enjoyed it.  The atmosphere was great - clean, crisp, yet warm, and relatively casual.  We had reservations and were seated promptly at a nice corner table.  Our waitress was great, and was helpful with the wine choices.  She knew the wines on their list quite well, as well as knew California vs. Oregon characteristic differences and other points that helped.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We started off with some great cocktails, and placed our order:&lt;/div&gt;&lt;div&gt;&lt;ul id=""&gt;&lt;li&gt;My mom: Heirloom tomato and goat cheese salad, side of chard to split with my dad, and the fresh, Chinook salmon.&lt;/li&gt;&lt;li&gt;My dad: Heirloom tomato and goat cheese salad, and the pork chops.&lt;/li&gt;&lt;li&gt;My wife: Trio of bruschetta for appetizer, and then she went for the heirloom tomato salad, side of onion rings, and side of beans with bleu cheese, for her entrée.&lt;/li&gt;&lt;li&gt;Myself: Breaded/fried oysters, and the duck.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;First off, the heirloom tomato salad was absolutely outstanding, all of us couldn't stop raving.  The tomatoes were perfect, the goat cheese was outstanding, and at the proper temperature, and the light dressing was killer (so good we asked how they made it, and plan to try to reproduce it at home :)  I ate a chunk of my wife's salad, and again, just stellar.&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;The fried oysters were ok, and are something sort of unusual for me anyway.  I think slightly lacking in flavor, but honestly, with all the other awesome food we had, it was fine, and we ate them all.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As for the entree's, all of them were excellent.  My mom loved her salmon, and I tried the pork which was very good - very juicy and tender, so often restaurants dry out pork, but not at all in this case.  Also, the grilled peaches that went with it were a really great match, and a nice change from the the more typical apples.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The duck I had was hands down the best duck I've had in as long as I can recall.  I don't order duck all that often, but had it recently in the Bay area, and it was pretty average on that occasion.  The duck came sliced, rare, with a extremely tasty crust around the edges, and in the most wonderful sauce!  Everyone was going nuts for the sauce, and in fact, we had them bring a little extra bowl for dipping the onion rings, as we found that a great combo :)  The sauce was the perfect amount too - by no means swimming in it, but also, enough to coat some of the potatoes and chard.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Speaking of chard, yes, we had a lot, given two of our entrees came with it, and we had two sides.  It was so darn good though that we ate nearly all of it, and took the remainder home.  Perfectly cooked, great seasoning, oh, just so good.  I wish I had more room, as I'd have finished it off.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finally, we managed to save enough room to have some dessert.  My dad and I split the cheese plate, and my wife had the creme brulee.  First, thank you Marché for not putting berries in the creme brulee!  Very good.  The cheese plate had a small serving of the same goat cheese used on the heirloom tomato salad, and a Camembert I particularly liked.  Given the intent for this to be a dessert for one person, it was a good portion, but since we split it, I'd probably have liked to have one more cheese (not that our stomachs needed it!).  We also had some espresso.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The food was so good, I almost forgot we had wine.  Aside from a glass of malbec we sent back (and indeed, the waitress had told us it wasn't the best), the cab was good.  We had wound up going with just wine by the glass, as honestly, their wine prices are quite high - even by California standards.  They had a fair number of good wines, but with cocktails, and the prices of the wine, we just decided to skip it.  I guess that would be about my only knock.  Aside from that, outstanding.  Definitely the best meal I've had in Eugene, and Marché gets my vote as the best restaurant in town (that I've been to so far anyway).  I would highly recommend it.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Update: I also posted this review &lt;a href="http://www.yelp.com/biz/guWOm23cKFTTiGlgGHGkmw"&gt;here on Yelp&lt;/a&gt;.  I'm finding Yelp more useful for restaurant reviews than say Eugene Weekly's food thing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-6421216803253624538?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/6421216803253624538/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=6421216803253624538' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6421216803253624538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/6421216803253624538'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/09/eugene-restaurant-review-march.html' title='Eugene Restaurant Review: Marché'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-7149093210350765081</id><published>2007-08-22T15:50:00.000-07:00</published><updated>2007-08-22T15:51:31.414-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='meme'/><title type='text'>I am 73% Optimus Prime</title><content type='html'>&lt;a href="http://www.funflip.com/" style="color:white;text-decoration:none;font:normal normal bold 9px/normal Tahoma;padding:70px 0px 0px 21px;text-align:left;display:block;width:268px;height:73px;background:url('http://www.funflip.com/_images/quiz/transformers/btns/289x143_optimus.jpg') no-repeat;"&gt;I AM&lt;br /&gt;&lt;span style="font-size:24px;"&gt;73%&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:12px;line-height:20px;"&gt;OPTIMUS PRIME&lt;/span&gt;&lt;/a&gt;&lt;a href="http://www.funflip.com/"&gt;Take the Transformers Quiz&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-7149093210350765081?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/7149093210350765081/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=7149093210350765081' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7149093210350765081'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/7149093210350765081'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/08/i-am-73-optimus-prime.html' title='I am 73% Optimus Prime'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-9174354314626823815</id><published>2007-08-15T22:14:00.001-07:00</published><updated>2007-08-15T22:19:17.866-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe'/><category scheme='http://www.blogger.com/atom/ns#' term='environment'/><category scheme='http://www.blogger.com/atom/ns#' term='Photos'/><category scheme='http://www.blogger.com/atom/ns#' term='green'/><title type='text'>Green Buildings Story: My Adobe Building Photo Used</title><content type='html'>I was happy to receive email from &lt;a href="http://www.grist.org"&gt;Grist&lt;/a&gt;, which just did an article on &lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;a href="http://www.grist.org/news/maindish/2007/08/10/buildings/?source=flickr"&gt;15 Green Buildings&lt;/a&gt;&lt;/span&gt;.  They used one of my photos of the Adobe Systems buildings in San Jose (see building #8 in the article).  Here's the full &lt;a href="http://www5.flickr.com/photos/chrisrbailey/321086647/"&gt;photo on Flickr&lt;/a&gt;.  I myself have become very interested in being "green" and have been increasing my own efforts.  Good job to Grist for observing the Creative Commons license, and glad I could help with such an article.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-9174354314626823815?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/9174354314626823815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=9174354314626823815' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/9174354314626823815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/9174354314626823815'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/08/green-buildings-story-my-adobe-building.html' title='Green Buildings Story: My Adobe Building Photo Used'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4086754480045998258</id><published>2007-08-09T15:31:00.000-07:00</published><updated>2007-08-09T15:35:13.328-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visionary'/><category scheme='http://www.blogger.com/atom/ns#' term='screensaver'/><title type='text'>New Visionary Saver screensaver on the horizon</title><content type='html'>I've put a bit more work into the Visionary Saver screensaver, and should have a new version out soon.  I'm likely going to have delay on the multi-monitor stuff.  Getting all the preferences right for that is somewhat of a UI mess (especially for those of us who deal with multiple multi-monitor setups for a single computer). &lt;br /&gt;&lt;br /&gt;On another note, I've added the "&lt;a href="http://www.thisnext.com/activity/map/"&gt;ThisWorld&lt;/a&gt;" visualization.  Gary's &lt;a href="http://flickrticker.com/"&gt;FlickrTicker&lt;/a&gt; will be fully supported as well.&lt;br /&gt;&lt;br /&gt;Depending on what work I get done on it this weekend, or in the next evening or two, I plan to have a new version out early next week, or this weekend.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4086754480045998258?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4086754480045998258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4086754480045998258' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4086754480045998258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4086754480045998258'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/08/new-visionary-saver-screensaver-on.html' title='New Visionary Saver screensaver on the horizon'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-3090269649959307196</id><published>2007-07-30T11:01:00.001-07:00</published><updated>2007-07-30T11:06:23.164-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='laptop'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>New MacBook Pro Recommendations?</title><content type='html'>I'm planning to replace my dual G5 tower (personal machine) with a new MacBook Pro, 17".  I need to get down to a store and see if I can look at this in person, but doing so in Eugene, may be hard.  So, I'm soliciting advice on two issues:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Should I get matte or glossy display?  The glossy sure looks cool, but how susceptible is it to glare?  I don't have a lot of glare in my work environment, so maybe that's moot and the glossy is better?  What do folks think?  Does it make a difference in color correction?  I've found that Galbraith and such have tested with the matte displays, and that I really like having my monitors color corrected.&lt;/li&gt;&lt;li&gt;Since I'm going with the 17", I'm debating whether to go with the higher resolution version.  My primary work mode will be with a 24" (or larger) monitor hooked up, so I use the laptop screen either if I'm on the road, not at my regular desk, and as a secondary monitor at my desk (typically for IM windows and similar).  Is the higher res a lot harder to read, or?  What are the pros and cons?&lt;/li&gt;&lt;/ol&gt;In general, this will be my do-everything machine.  Personal stuff, as well as development projects of my own, etc.  Thus, everything from email and Quicken to heavy coding, Lightroom/photo work, etc.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-3090269649959307196?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/3090269649959307196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=3090269649959307196' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3090269649959307196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3090269649959307196'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/07/new-macbook-pro-recommendations.html' title='New MacBook Pro Recommendations?'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-3490865436677962016</id><published>2007-07-03T10:25:00.000-07:00</published><updated>2007-07-03T10:32:48.066-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='consulting'/><title type='text'>You don't always get what you pay for (IBM: $30m, 2 years; us: $3m, 1yr)</title><content type='html'>I just found out today, from the gentleman I did a consulting gig with a few years ago, that the company we did the architecture for (but who declined having us do the project), had IBM do it instead.  That's not the interesting part (especially since during this time the company hired an ex-IBMer).  The interesting part, as I was informed, is that IBM used our architecture (admittedly that's how it was explained, and we didn't get into details, but still), but took two years to do the project, and charged $30m!!!  As I recall, we'd bid it at around a year, and I think around $2-3m!  Either the project changed a lot, or that is just gross.  I suspect IBM went in and did some massively overdone EJB implementation (this was a Java project, and I'd done a very basic prototype using Spring, Hibernate, and Velocity or JSP).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-3490865436677962016?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/3490865436677962016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=3490865436677962016' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3490865436677962016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3490865436677962016'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/07/you-dont-always-get-what-you-pay-for.html' title='You don&apos;t always get what you pay for (IBM: $30m, 2 years; us: $3m, 1yr)'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4871746217338157141</id><published>2007-06-25T23:20:00.000-07:00</published><updated>2007-06-25T23:22:47.115-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GPS'/><category scheme='http://www.blogger.com/atom/ns#' term='cameras'/><title type='text'>GPS Data for Canon DSLR's?</title><content type='html'>&lt;a href="http://www.moosepeterson.com/moosenews/archives/2007/06/23/coolest-tool-ever-062307/"&gt;Moose Peterson recently blogged about this really cool mini-GPS&lt;/a&gt; that mounts on the hot shoe of Nikon DSLR's.  I'm wondering if there is anything like this for Canon's, in particular the Rebel XTi, or 30D, etc.  I would also be ok if there was a solution that connected my Garmin 60CSx to my XTi to automatically store GPS data in the EXIF info.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4871746217338157141?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4871746217338157141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4871746217338157141' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4871746217338157141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4871746217338157141'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/06/gps-data-for-canon-dslrs.html' title='GPS Data for Canon DSLR&apos;s?'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4450369223178840372</id><published>2007-06-20T19:55:00.000-07:00</published><updated>2007-06-20T19:57:53.558-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>iPhoneDevCamp at Adobe San Francisco (free event)</title><content type='html'>Check out the &lt;a href="http://barcamp.org/iPhoneDevCamp"&gt;iPhoneDevCamp&lt;/a&gt;, which is being held at Adobe's San Francisco office July 6-8.  This is a free event, and features presentations, development projects, and demos.&lt;br /&gt;&lt;br /&gt;&lt;div class="tag_list"&gt;Tags: &lt;span class="tags"&gt;&lt;a href="http://technorati.com/tag/iPhone" rel="tag"&gt;iPhone&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Adobe" rel="tag"&gt;Adobe&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Apple" rel="tag"&gt;Apple&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4450369223178840372?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4450369223178840372/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4450369223178840372' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4450369223178840372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4450369223178840372'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/06/iphonedevcamp-at-adobe-san-francisco.html' title='iPhoneDevCamp at Adobe San Francisco (free event)'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-3186987825642989695</id><published>2007-06-15T13:26:00.000-07:00</published><updated>2007-06-15T14:24:18.463-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perforce'/><category scheme='http://www.blogger.com/atom/ns#' term='Capistrano'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOnRails'/><title type='text'>Fixes for Capistrano 2's Perforce</title><content type='html'>&lt;p&gt;I'm starting to convert to Capistrano 2.  We use Perforce, and I've found a simple typo/bug in  Capistrano 1.99.1.  The fix is simple:On line 57 of recipes/deploy/scm/perforce.rb, change the use of "revno" to "rev_no".&lt;/p&gt;&lt;br /&gt;&lt;p style="text-decoration: line-through;"&gt;Now, the question is, where is the Capistrano bug DB, or where/how do I submit this to them?&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I reported this to the mailing list, and Jamis has already checked in the fix in SVN.  Capistrano lives in the Rails Trac.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-3186987825642989695?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/3186987825642989695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=3186987825642989695' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3186987825642989695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3186987825642989695'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/06/fixes-for-capistrano-2s-perforce.html' title='Fixes for Capistrano 2&apos;s Perforce'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-401707453264317012</id><published>2007-06-15T11:02:00.001-07:00</published><updated>2008-06-06T21:01:31.173-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CruiseControl'/><category scheme='http://www.blogger.com/atom/ns#' term='Perforce'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ContinuousIntegration'/><title type='text'>Perforce Implementation for CruiseControl.rb</title><content type='html'>While I haven't had a chance to clean up the code, folks have asked for it, so I'm making my Perforce implementation for CruiseControl available.  There are some important notes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You need to set up your project manually, you can't do an "add" via CruiseControl.&lt;/li&gt;&lt;li&gt;Some work needs to be done on the text retrieval for checkin messages, and how that's displayed on the CC.rb results pages.&lt;/li&gt;&lt;/ul&gt;However, so far it's been working fairly well for me.  Feel free to use this as you need.  I have not yet submitted it to the CC.rb folks, as I hadn't had time to clean it up yet.  So, if you dial it in better, please do submit it to them, or send me your changes, and I'll submit it, etc.&lt;br /&gt;&lt;br /&gt;To install/use it:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Put the &lt;a href="http://github.com/chris/cruisecontrolrb_perforce"&gt;perforce.rb&lt;/a&gt; file into your cruisecontrol/app/models directory.&lt;/li&gt;&lt;li&gt;Manually setup your project:&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create a directory under the cruisecontrol/projects directory.&lt;/li&gt;&lt;li&gt;Place a cruise_config.rb file in it.  It should contain something like the following in order to use Perforce:&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code&gt;Project.configure do |project|&lt;br /&gt;# Use Perforce for source control&lt;br /&gt;project.source_control = Perforce.new(&lt;br /&gt;:port =&gt; 'your.perforce.server:1666',&lt;br /&gt;:clientspec =&gt; 'clientspec-for-cruisecontrol',&lt;br /&gt;:user =&gt; 'buildusername',&lt;br /&gt;:password =&gt; 'builduserpassword',&lt;br /&gt;:path =&gt; '//depot/path/to/your/rails/app/...')&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;Sync your code once.&lt;/li&gt;&lt;li&gt;Fire up CruiseControl, and let the games begin.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;Usual disclaimer: I take no responsibility for your systems, code, etc.  Read the code, test it out, backup your systems, etc.&lt;div class="tag_list"&gt;Tags: &lt;span class="tags"&gt;&lt;a href="http://technorati.com/tag/ContinuousIntegration" rel="tag"&gt;ContinuousIntegration&lt;/a&gt;, &lt;a href="http://technorati.com/tag/CruiseControl" rel="tag"&gt;CruiseControl&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Perforce" rel="tag"&gt;Perforce&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Ruby" rel="tag"&gt;Ruby&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Update: I've now given this an official home on GitHub.  See the &lt;a href="http://github.com/chris/cruisecontrolrb_perforce"&gt;cruisecontrolrb_perforce&lt;/a&gt; project there.  Fork at will, and please do send me Pull requests if you enhance the code, or at least tell me about your version, and I'll put that in the README or on the wiki, etc.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-401707453264317012?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/401707453264317012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=401707453264317012' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/401707453264317012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/401707453264317012'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/06/perforce-implementation-for.html' title='Perforce Implementation for CruiseControl.rb'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4702751435841249030</id><published>2007-06-06T21:20:00.001-07:00</published><updated>2007-06-06T21:20:49.603-07:00</updated><title type='text'>Our Servers</title><content type='html'>&lt;div style="float: right; margin-left: 10px; margin-bottom: 10px;"&gt; &lt;a href="http://www.flickr.com/photos/glub/532787538/" title="photo sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1174/532787538_506354d46e_m.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt; &lt;br /&gt; &lt;span style="font-size: 0.9em; margin-top: 0px;"&gt;  &lt;a href="http://www.flickr.com/photos/glub/532787538/"&gt;Rack And Stack&lt;/a&gt;  &lt;br /&gt;  Originally uploaded by &lt;a href="http://www.flickr.com/people/glub/"&gt;• g l u b •&lt;/a&gt; &lt;/span&gt;&lt;/div&gt;Gary got a nice shot of some of the servers we've recently racked up.&lt;br clear="all" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4702751435841249030?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4702751435841249030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4702751435841249030' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4702751435841249030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4702751435841249030'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/06/our-servers.html' title='Our Servers'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm2.static.flickr.com/1174/532787538_506354d46e_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-4102650718285809563</id><published>2007-06-04T12:43:00.001-07:00</published><updated>2007-06-04T12:48:31.855-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visionary'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='Flickr'/><category scheme='http://www.blogger.com/atom/ns#' term='Twitter'/><title type='text'>Visionary Saver Updates Coming...</title><content type='html'>I've been swamped at work, so haven't had much time to work on Visionary Saver.  But, I should have an update in the next week or two.  Some of the things I'm working on:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Multi-monitor support: allowing you to pick which visualization(s) you want on each monitor (or fully random)&lt;/li&gt;&lt;li&gt;Adding a new Flickr visualizer: &lt;a href="http://flickrticker.com"&gt;FlickrTicker&lt;/a&gt;&lt;/li&gt;&lt;li&gt;More options for various visualizers&lt;/li&gt;&lt;li&gt;Looking into enabling use of the mouse while the screen saver is running&lt;/li&gt;&lt;/ul&gt;Thanks everyone for the support!&lt;br /&gt;&lt;br /&gt;In the mean time, to get the existing version, &lt;a href="http://codeintensity.blogspot.com/2007/05/new-version-of-twittervision-screen.html"&gt;click here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-4102650718285809563?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/4102650718285809563/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=4102650718285809563' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4102650718285809563'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/4102650718285809563'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/06/visionary-saver-updates-coming.html' title='Visionary Saver Updates Coming...'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-3816138738173470358</id><published>2007-06-02T00:48:00.001-07:00</published><updated>2007-06-02T00:57:31.530-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nuvo'/><category scheme='http://www.blogger.com/atom/ns#' term='HomeTheater'/><category scheme='http://www.blogger.com/atom/ns#' term='House'/><title type='text'>New Home AV Stuff</title><content type='html'>&lt;div style="float: right; margin-left: 10px; margin-bottom: 10px;"&gt; &lt;a href="http://www.flickr.com/photos/chrisrbailey/525966595/" title="photo sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1189/525966595_1e1ff6ca2f_m.jpg" alt="" style="border: 2px solid rgb(0, 0, 0);" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="margin-top: 0px;font-size:0;" &gt;  &lt;a href="http://www.flickr.com/photos/chrisrbailey/525966595/"&gt;New Nuvo Panel Master Bath&lt;/a&gt;&lt;br /&gt;Originally uploaded by &lt;a href="http://www.flickr.com/people/chrisrbailey/"&gt;Christopher Bailey&lt;/a&gt; &lt;/span&gt;&lt;/div&gt;Today the installers wrapped up the bulk of the new home theater and whole-house audio additions, changes, upgrades, etc.  The house had come with a Nuvo Concerto system for whole-house audio.  But, we wanted really good iPod control, so we upgraded (for cost difference) to the new &lt;a href="http://www.nuvotechnologies.com/concerto.htm"&gt;Grand Concerto&lt;/a&gt; system, that has these improved touch pads (instead of keypads), and does full metadata display for iPods, radio, XM radio, and so on.  They are really nice and we're stoked to have XM now (before it was a dual AM/FM tuner, which we swapped out for a dual AM/FM + XM).  The &lt;a href="http://www.nuvotechnologies.com/iPod_docks.htm"&gt;iPod dock&lt;/a&gt; part shows up next week, can't wait for that.&lt;br /&gt;&lt;br /&gt;They also installed the new Samsung 50" plasma, wall mounted, and then racked up the equipment in the little AV closet in our bonus room.  Nice setup, but I think we'll likely have to get more ventilation in the little closet, it gets pretty hot in there.&lt;br /&gt;&lt;div style="float: left; margin-right: 10px; margin-bottom: 10px;"&gt; &lt;a href="http://www.flickr.com/photos/chrisrbailey/525966585/" title="photo sharing"&gt;&lt;img src="http://farm1.static.flickr.com/221/525966585_1df4e6c79e_m.jpg" alt="" style="border: 2px solid rgb(0, 0, 0);" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="margin-top: 0px;font-size:0;" &gt;  &lt;a href="http://www.flickr.com/photos/chrisrbailey/525966585/"&gt;Our new rack setup in the bonus room&lt;/a&gt;&lt;br /&gt;Originally uploaded by &lt;a href="http://www.flickr.com/people/chrisrbailey/"&gt;Christopher Bailey&lt;/a&gt; &lt;/span&gt;&lt;/div&gt;&lt;br /&gt;They still have a bunch of othe wiring to do in the house, as we're having some ethernet and other stuff re-jiggered, and they didn't finish programming the killer &lt;a href="http://www.universalremote.com/product_detail.php?model=34"&gt;Universal Remote Control MX-3000&lt;/a&gt;.  Of course, I'll want to get my hands on programming this as well.  You can do all sorts of crazy stuff with it.&lt;br /&gt;&lt;div style="float: right; margin-left: 10px; margin-bottom: 10px;"&gt; &lt;a href="http://www.flickr.com/photos/chrisrbailey/525966597/" title="photo sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1232/525966597_42a14e9ddb_m.jpg" alt="" style="border: 2px solid rgb(0, 0, 0);" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="margin-top: 0px;font-size:0;" &gt;  &lt;a href="http://www.flickr.com/photos/chrisrbailey/525966597/"&gt;New Nuvo Panel In Kitchen&lt;/a&gt;&lt;br /&gt;Originally uploaded by &lt;a href="http://www.flickr.com/people/chrisrbailey/"&gt;Christopher Bailey&lt;/a&gt; &lt;/span&gt;&lt;/div&gt;&lt;br /&gt;The funny part is we probably wouldn't have done half of this if the Nuvo system didn't already come with the house.  But now that we have it, boy is it nice.  Being able to have music all through the house (and different choices in different rooms), as well as on the deck (that's my favorite!) is just so nice.  We watched a movie on the new plasma tonight and it was great, plus super sound in that room.  There are better plasmas, but for the money this one is extremely nice.  BTW, we have a Loewe 42" plasma for sale if anyone is interested (no, you don't even want to know what that cost, it's rather embarrassing in fact).  Anyway, as you can tell, I'm pretty giddy about it all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-3816138738173470358?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/3816138738173470358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=3816138738173470358' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3816138738173470358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/3816138738173470358'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/06/new-home-av-stuff.html' title='New Home AV Stuff'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm2.static.flickr.com/1189/525966595_1e1ff6ca2f_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29194345.post-5804196494425328078</id><published>2007-06-01T08:09:00.000-07:00</published><updated>2008-01-27T23:25:11.723-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Air'/><title type='text'>Online/Offiline Web Apps: Why Does the Browser Matter?</title><content type='html'>For a few months now we've been seeing more offline web app support.  This includes technologies like &lt;a href="http://labs.adobe.com/technologies/apollo/"&gt;Apollo&lt;/a&gt;, some of the tricks people are using with Firefox (like ), http://www.blogger.com/img/gl.link.gif&lt;a href="http://www.zimbra.com/blog/archives/2006/11/taking_zimbra_offline.html"&gt;&lt;/a&gt;, and lately .http://www.blogger.com/img/gl.link.gif&lt;a href="http://code.google.com/apis/gears/?utm_campaign=en&amp;utm_source=en-ha-ww-google&amp;amp;utm_medium=ha&amp;utm_term=google%20gears"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;What amazes me is how much people want to seem to stay within a web browser.  They're trying so hard to cram a feature into a space that wasn't designed for it, not to mention is just a crappy solution.  No doubt there are a few nice uses of offline support for a pure browser-based app, but &lt;span style="font-weight: bold;"&gt;why haven't more people started to realize how much better they can do by going beyond the browser?&lt;/span&gt;  Why do you want the browsers UI to be your dominant surrounding UI?  Why do you want to be constrained to the browser's window, and force your user's to have your app running in another http://www.blogger.com/img/gl.link.gifapp, that doesn't have it's own dock/task bar icon or ability to interact with the OS? &lt;br /&gt;&lt;br /&gt;I also don't think it's an all or nothing situation.  I value having a browser-based UI available to me, so that when I'm not using one of my computers, I can still view my data.  I don't expect the experience to be as good, and it can lack features, but I can get to the data in a pinch.  But, I would much rather have dedicated applications for the "web applications" I use a lot.  Examples of this would be Backpack, project tracking systems (currently I use Scrumworks, which has a Java desktop client that works with their web app, and Basecamp), music players, weather watchers, &lt;a href="http://gotapi.com"&gt;GotAPI&lt;/a&gt;, Twitter, and many others.&lt;br /&gt;&lt;br /&gt;There are some examples popping up.  Twitter has &lt;a href="http://iconfactory.com/software/twitterrific"&gt;Twitterific&lt;/a&gt;, and &lt;a href="http://www.finetune.com/desktop/"&gt;FineTune has their Apollo player&lt;/a&gt;.  These are both excellent examples of how deficient the browser is for many web applications, and how much better you can do outside the browser. &lt;br /&gt;&lt;br /&gt;I admit that Apollo is really what took my thinking on this to the next level.  You no longer have the excuse that you don't know native code or native code toolkits and such.  Building an Apollo app can be done the same as you'd build a web app, and even gives you the choice of Flex or HTML, or a combination (this gets very powerful).  You can even simply pop an existing web app into an HTML view in an Apollo window, and thus have a dedicated application (doesn't give you much more but at least you aren't just a tab in your browser, and can display it on a different virtual desktop or size the window differently than your browser window, etc.).&lt;br /&gt;&lt;br /&gt;To make this more positive, this is a call to all web developers to think hard about this.  Even if you don't need offline support, or you don't need it right away, think about the user experience and how you might create that much better of an app by not being constrained to a browser.  I won't have anything in the next week, but yes, I'll be eating my own dogfood, and having some apps out soon enough (watch this space).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29194345-5804196494425328078?l=codeintensity.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeintensity.blogspot.com/feeds/5804196494425328078/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=29194345&amp;postID=5804196494425328078' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5804196494425328078'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29194345/posts/default/5804196494425328078'/><link rel='alternate' type='text/html' href='http://codeintensity.blogspot.com/2007/06/onlineoffiline-web-apps-why-does.html' title='Online/Offiline Web Apps: Why Does the Browser Matter?'/><author><name>Chris</name><uri>http://www.blogger.com/profile/14204551800123292694</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/101/303785277_fa1d447b35_s.jpg'/></author><thr:total>4</thr:total></entry></feed>
