<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/atom10full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>poocs.net - Home</title>
  <id>tag:poocs.net,2008:mephisto/</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  
  <link href="http://poocs.net/" rel="alternate" type="text/html" />
  <updated>2008-06-20T07:44:43Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/poocsnet" type="application/atom+xml" /><entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2008-06-20:682</id>
    <published>2008-06-20T07:41:00Z</published>
    <updated>2008-06-20T07:44:43Z</updated>
    <category term="Personal" />
    <category term="Rails" />
    <category term="bignerdranch" />
    <category term="course" />
    <category term="rails" />
    <category term="ruby" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/316037468/ruby-ruby-on-rails-bootcamp-2009" rel="alternate" type="text/html" />
    <title>Ruby &amp; Ruby on Rails Bootcamp 2009</title>
<content type="html">
            &lt;p&gt;&lt;img class="left" src="http://img.skitch.com/20080620-fbge8348ut5gimfe8ms4qer8jt.png" alt="Big Nerd Ranch" /&gt;&lt;/p&gt;

&lt;p&gt;I’ve recently been recruited as an &lt;a href="http://www.bignerdranch.com/instructors/lenz.shtml"&gt;instructor&lt;/a&gt; for the holy &lt;a href="http://www.bignerdranch.com/"&gt;Big Nerd Ranch&lt;/a&gt; and will be giving my first course, the 7-day &lt;a href="http://bignerdranch.com/classes/ruby_ruby_on_rails.shtml"&gt;Ruby &amp;amp; Ruby on Rails Bootcamp&lt;/a&gt;, in companion with &lt;a href="http://www.bignerdranch.com/instructors/quinn.shtml"&gt;Charles Brian Quinn&lt;/a&gt; of Highgrove Studios fame taking place in March 2009. I’ll take care of the first two days, which will be used to lay a solid foundation of Ruby programming before diving into the following 5 days where Charles teaches all things Rails.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/scoop/1303465358/" title="Sunlight by Patrick Lenz, on Flickr"&gt;&lt;img src="http://farm2.static.flickr.com/1077/1303465358_e8542ede9b.jpg" height="333" alt="Sunlight" width="500" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The course takes place near Frankfurt, Germany, at the beautiful monastery “Kloster Eberbach”. In fact, numerous Big Nerd Ranch courses have been held at this venue, the first one being held by no other than &lt;a href="http://www.vernix.org/marcel/"&gt;Marcel Molina Jr.&lt;/a&gt; in &lt;a href="http://flickr.com/photos/scoop/sets/72057594106718516/"&gt;April 2006&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the duration of the course you will stay directly at the monastery, delicious meals will be provided at the historic “Klosterschänke” and the course itself is held on the just as historic “Heuboden”, a truly amazing environment to learn and have a good time. Also included is a tour through the monastery accompanied by a wine tasting.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/scoop/128274738/" title="Weinkeller by Patrick Lenz, on Flickr"&gt;&lt;img src="http://farm1.static.flickr.com/51/128274738_392af44e84.jpg" height="332" alt="Weinkeller" width="500" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="http://www.bignerdranch.com/classes/ruby_ruby_on_rails.shtml"&gt;course page&lt;/a&gt; for additional course details as well as pricing information and registration form.&lt;/p&gt;

&lt;p&gt;See you at the monastery!&lt;/p&gt;

&lt;p&gt;PS: Not a beginner Rails developer but looking to advance your skills? Charles will be at the monastery for the &lt;a href="http://bignerdranch.com/classes/advanced_ruby_on_rails.shtml"&gt;Advanced Ruby on Rails Bootcamp&lt;/a&gt; at the end of August 2008.&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=4YzOxI"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=4YzOxI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=GQAT9I"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=GQAT9I" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=PpWoVI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=PpWoVI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=Chisii"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=Chisii" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=s6aBjI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=s6aBjI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=VuUGQi"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=VuUGQi" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/316037468" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2008%2F6%2F20%2Fruby-ruby-on-rails-bootcamp-2009</feedburner:awareness><feedburner:origLink>http://poocs.net/2008/6/20/ruby-ruby-on-rails-bootcamp-2009</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2008-05-22:655</id>
    <published>2008-05-22T10:21:00Z</published>
    <updated>2008-06-21T11:10:50Z</updated>
    <category term="Personal" />
    <category term="Rails" />
    <category term="book" />
    <category term="rails" />
    <category term="sitepoint" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/295722696/simply-rails-2-now-available" rel="alternate" type="text/html" />
    <title>Simply Rails 2 now available</title>
<content type="html">
            &lt;p&gt;&lt;img class="left" src="http://img.skitch.com/20080522-tbspwi2y6a67fumtm48ue5mncc.jpg" alt="cover3d-right" /&gt;&lt;/p&gt;

&lt;p&gt;I’ve been hard at work getting my Rails beginner’s book &lt;a href="http://www.sitepoint.com/books/rails1/"&gt;Build Your Own Ruby on Rails Web Applications&lt;/a&gt; updated to reflect the changes and additions in Rails 2. Part of this process was making everything work even simpler than it has been in the first edition, hence the title change to &lt;a href="http://www.sitepoint.com/books/rails2"&gt;Simply Rails 2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All of the chapters have been reworked to incorporate the partially massive simplifications that have shipped in Rails 2 and I’ve also changed the database used in the installation to be SQLite, aptly changed from the MySQL default in both the first edition of the book and in Rails 1.2.&lt;/p&gt;

&lt;p&gt;Shovell, the sample application developed over the course of the book, is also developed fully RESTful now, one of the complaints the first edition received.&lt;/p&gt;

&lt;p&gt;&lt;img class="right" src="http://img.skitch.com/20080522-paxghi2ju6qnd87hi7fqtwiwxh.jpg" alt="rubyRevealed" /&gt;&lt;/p&gt;

&lt;p&gt;The chapter on debugging incorporates the content from the former stand-alone article &lt;a href="http://www.sitepoint.com/article/debug-rails-app-ruby-debug"&gt;Debugging  Your Rails App with ruby-debug&lt;/a&gt; introducing you to the newly gained debugging powers from Kent Sibilev’s great debugging tool.&lt;/p&gt;

&lt;p&gt;The book finally came back from the printer last week and is now available for purchase from &lt;a href="https://sitepoint.com/bookstore/go/140"&gt;SitePoint&lt;/a&gt; in both PDF and hard copy form. They also sell a bundle of both as a special value pack. Of course the hard copy is also available for purchase from the &lt;a href="http://www.amazon.com/gp/product/0980455200?ie=UTF8&amp;amp;amp;tag=poocsde-21&amp;amp;amp;linkCode=as2&amp;amp;amp;camp=1638&amp;amp;amp;creative=6742&amp;amp;amp;creativeASIN=0980455200"&gt;usual&lt;/a&gt; &lt;a href="http://www.oreilly.com/catalog/9780980455205/"&gt;suspects&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;SitePoint also published an excerpt of the book as an article titled &lt;a href="http://www.sitepoint.com/article/rails-for-beginners"&gt;Rails For Beginners: All You Need To Know!&lt;/a&gt; and made a PDF of chapters 1 through 4 available as a &lt;a href="http://www.sitepoint.com/popup/popup.php?zone=2&amp;amp;amp;popupid=112"&gt;free download&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Have at it!&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=cnCk2e"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=cnCk2e" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=IejtkH"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=IejtkH" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=BA3lAH"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=BA3lAH" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=SzP58h"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=SzP58h" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=XSa3PH"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=XSa3PH" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=33fH1h"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=33fH1h" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/295722696" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2008%2F5%2F22%2Fsimply-rails-2-now-available</feedburner:awareness><feedburner:origLink>http://poocs.net/2008/5/22/simply-rails-2-now-available</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2008-04-19:640</id>
    <published>2008-04-19T15:24:00Z</published>
    <updated>2008-04-19T15:26:37Z</updated>
    <category term="Git" />
    <category term="git" />
    <category term="mephisto" />
    <category term="subversion" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/273585434/mephisto-change-from-svn-to-git" rel="alternate" type="text/html" />
    <title>Mephisto: Change from SVN to Git</title>
<content type="html">
            &lt;p&gt;The fine folks over at ENTP/ActiveReload have &lt;a href="http://mephistoblog.com/2008/4/18/mephisto-hits-0-8-moves-to-github"&gt;released version 0.8&lt;/a&gt; of Mephisto, the Rails application that powers this site. With this new release, they, as everyone these days, have actively shifted the remaining bits and pieces of Mephisto’s development from Subversion to Git. (And its main repository is hosted at &lt;a href="http://github.com"&gt;Github&lt;/a&gt;, where else.)&lt;/p&gt;

&lt;p&gt;I hardly remember ever installing Mephisto from a tarball. I always used to track its Subversion trunk for the 3 blogs I run, which made upgrading as easy as &lt;code&gt;svn up &amp;amp;&amp;amp; rake db:migrate RAILS_ENV=production&lt;/code&gt; most of the time. Well, that was then and this is now. Looking at this recent shift to Git, I wanted to convert my blogs to the new Git repository without excessively messing with whatever I did to my local installation (quickly approaching my 30s, I might not even recall most of what I did). I was pretty certain, however, that I did not have massive local modifications. If I had, this approach might’ve been a little simplistic. &lt;/p&gt;

&lt;p&gt;Here’s what I did.&lt;/p&gt;

&lt;h1&gt;Initializing&lt;/h1&gt;

&lt;p&gt;Starting out, you need to create a local Git repository within your local blog installation, which is as simple as:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd /your/blog
$ git init
Initialized empty Git repository in .git/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The next step is to setup technoweenie’s master repository on Github as a remote to your local repository and fetch what’s currently in there.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git remote add technoweenie git://github.com/technoweenie/mephisto.git
$ git fetch technoweenie
remote: Generating pack...
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will fetch both the master branch and all branches technoweenie might’ve created. (This includes, for example, a branch that holds the current 0.8 release, if you don’t dare to ride the edge of Mephisto’s development.)&lt;/p&gt;

&lt;h1&gt;Merging&lt;/h1&gt;

&lt;p&gt;At this point we need to merge one of the branches we just fetched into your local (totally empty, for what it’s worth) repository. (I’ve decided to stay on the master branch. If you prefer a release branch, substitute it as appropriate.)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git merge technoweenie/master
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since Subversion scatters its &lt;code&gt;.svn&lt;/code&gt; folders all over the place, we need to get rid of those. You can either do that manually or with a little &lt;code&gt;find&lt;/code&gt;-fu.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ find . -type d -name '.svn' -exec rm -rf {} \;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Excellent, that’s much better. Now it should be safe to check out the current state of affairs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git status
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Running this command will show you the currently untracked files. Those would be all files that existed locally before you started to create your own Git repository &lt;em&gt;and&lt;/em&gt; which are non-existent in technoweenie’s repository.&lt;/p&gt;

&lt;h1&gt;Tracking local modifications&lt;/h1&gt;

&lt;p&gt;As I mentioned above, I didn’t have a boatload of local modifications. My changes were limited to bit of configuration, a few third party plugins (and the accompanying CSS/Javascript) and my local Mint installation. The additional files and directories that may show up are the cached HTML files that Mephisto sticks in &lt;code&gt;public/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To actually add your local modifications to your Git repository, simple add and commit them.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git add config/mongrel_cluster.yml
$ git commit -m 'Mongrel configuration'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you’d prefer to rather ignore whatever else sits in your blog directory, add it to &lt;code&gt;.gitignore&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ echo "public/*.html" &amp;gt;&amp;gt; .gitignore
$ echo "public/200*" &amp;gt;&amp;gt; .gitignore
$ echo "public/mint" &amp;gt;&amp;gt; .gitignore
$ git commit -m 'Ignore cache and mint' .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;Cleaning up&lt;/h1&gt;

&lt;p&gt;I had a few files sitting in my directory that weren’t local modifications but seemed to have been removed from the official repository, too. Those weren’t caught by our merging of the Git branch since we started with zero history. To get rid of those, let’s take a look at &lt;code&gt;git-clean&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git clean -n -d
Would remove app/views/admin/article_comments/
Would remove app/views/admin/articles/approve.rjs
Would remove app/views/admin/articles/comments.rhtml
Would remove app/views/admin/articles/destroy_comment.rjs
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;-n&lt;/code&gt; argument prevents &lt;code&gt;git clean&lt;/code&gt; from actually doing anything. If you’re confident it wouldn’t do anything harmful, go ahread and remove it. (You do have backups, right? Do you?)&lt;/p&gt;

&lt;p&gt;At this point we’re down to regular upgrading business, so you might want to run the migrations and restart your Mongrel cluster. (Or whatever floats your deployment boat.)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rake db:migrate RAILS_ENV=production
$ mongrel_rails cluster::restart
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;Into the future&lt;/h1&gt;

&lt;p&gt;Now, whenever Mr. Weenie adds an exciting new feature to Mephisto you can grab that via:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git fetch technoweenie
$ git merge technoweenie/master
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or if you’d rather prefer to pick a specific commit:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git cherry-pick &amp;lt;SHA1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;Further reading&lt;/h1&gt;

&lt;p&gt;Since this is not a Git guide per-se, I’ll end the article at this point. There is plenty of &lt;a href="http://ktown.kde.org/~zrusin/git/git-cheat-sheet-medium.png"&gt;other&lt;/a&gt; &lt;a href="http://cheat.errtheblog.com/s/git"&gt;content&lt;/a&gt; &lt;a href="http://github.com/guides/cool-and-unusual-git-techniques"&gt;available&lt;/a&gt; &lt;a href="http://peepcode.com/products/git"&gt;online&lt;/a&gt; to bring you up to speed with Git.&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=QJDM5s"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=QJDM5s" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=axRHTI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=axRHTI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=dor7rI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=dor7rI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=zU0f2i"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=zU0f2i" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=vQ5Z4I"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=vQ5Z4I" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=G6qGvi"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=G6qGvi" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/273585434" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2008%2F4%2F19%2Fmephisto-change-from-svn-to-git</feedburner:awareness><feedburner:origLink>http://poocs.net/2008/4/19/mephisto-change-from-svn-to-git</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2008-04-05:626</id>
    <published>2008-04-05T14:53:00Z</published>
    <updated>2008-04-11T09:27:52Z</updated>
    <category term="Rails" />
    <category term="basecamp" />
    <category term="capistrano" />
    <category term="deployment" />
    <category term="git" />
    <category term="rails" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/264592523/post-deployment-log-to-basecamp" rel="alternate" type="text/html" />
    <title>Post deployment log to Basecamp</title>
<content type="html">
            &lt;p&gt;I guess many of you have been reading the recent Signal vs. Noise blog post titled &lt;a href="http://www.37signals.com/svn/posts/951-using-basecamp-to-automatically-keep-track-of-product-releases"&gt;Using Basecamp to automatically keep track of product releases&lt;/a&gt;. I found it rather inspiring so I started to work on something similar for my own projects.&lt;/p&gt;

&lt;p&gt;Out of that effort comes a super simple &lt;a href="http://capify.org/"&gt;Capistrano&lt;/a&gt; plugin that grabs the first line from each commit (the &lt;em&gt;subject&lt;/em&gt; in &lt;a href="http://git.or.cz/"&gt;Git&lt;/a&gt; lingo) that happened between the last deploy and the current one and posts it as a new message to a pre-defined project (and category) on your &lt;a href="http://basecamphq.com/"&gt;Basecamp&lt;/a&gt; account using the &lt;a href="http://developer.37signals.com/"&gt;Basecamp API&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;Installation&lt;/h1&gt;

&lt;pre&gt;&lt;code&gt;$ cd &amp;lt;yourapp&amp;gt;/vendor/plugins
$ git clone git@github.com:scoop/basecamp_notify.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It automatically hooks itself into your deployment process after &lt;code&gt;deploy:symlink&lt;/code&gt; has run. Here’s a &lt;a href="http://github.com/scoop/basecamp_notify"&gt;direct link to the GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you don’t have git, you can &lt;a href="http://github.com/scoop/basecamp_notify/tarball/master"&gt;download a tarball from GitHub&lt;/a&gt;, but read the caveat in the next section.&lt;/p&gt;

&lt;h1&gt;Configuration&lt;/h1&gt;

&lt;p&gt;The download ships with an example YAML configuration that needs to go into &lt;code&gt;&amp;lt;yourapp&amp;gt;/config/basecamp.yml&lt;/code&gt;. It takes your Basecamp URL, username, and password as well as the numeric IDs for the project and category to post to, respectively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caveat:&lt;/strong&gt; Since I wanted a fairly concise output in my posted messages (resembling what 37signals has in their example), I used a special command-line argument formatting thingamagick that only Git understands, so the plugin could be considered Git-only for now. Feel free to send in a patch that does the same for subversion.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://img.skitch.com/20080405-bqbrrf2gfaai7s1trqe5dhcm88.jpg" alt="basecamp_notify" /&gt;&lt;/p&gt;

&lt;h1&gt;Questions?&lt;/h1&gt;

&lt;p&gt;Email me at &lt;a&gt;pat&amp;#x72;i&amp;#x63;k&amp;#x40;limi&amp;#x74;&amp;#x65;d-&amp;#x6F;v&amp;#x65;rl&amp;#x6F;ad&amp;#x2E;d&amp;#x65;&lt;/a&gt; if you have questions. Hope it’s useful for some of you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE 04/11:&lt;/strong&gt; basecamp_notify now has support for Subversion repositories. Thanks &lt;a href="http://github.com/pyrat"&gt;pyrat&lt;/a&gt;.&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=6SsXLz"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=6SsXLz" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=ZAnhuI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=ZAnhuI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=9iaAAI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=9iaAAI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=m3KPki"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=m3KPki" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=4fmCmI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=4fmCmI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=3lfCHi"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=3lfCHi" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/264592523" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2008%2F4%2F5%2Fpost-deployment-log-to-basecamp</feedburner:awareness><feedburner:origLink>http://poocs.net/2008/4/5/post-deployment-log-to-basecamp</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2008-02-04:612</id>
    <published>2008-02-04T11:34:00Z</published>
    <updated>2008-03-05T21:09:02Z</updated>
    <category term="Rails" />
    <category term="fastcgi" />
    <category term="god" />
    <category term="monitoring" />
    <category term="rails" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/228846983/use-god-to-spawn-fastcgi-processes" rel="alternate" type="text/html" />
    <title>Use god to spawn FastCGI processes</title>
<content type="html">
            &lt;p&gt;For some reason we’re still on FastCGI with one of our apps and it’s not planned to change any time soon. But as is notorious about Ruby’s processes, they can get out of hand, both uptime wise and memory-usage wise. The former is greatly taken care of by the &lt;code&gt;script/spinner&lt;/code&gt; utility that Rails ships with. The latter? Not so much.&lt;/p&gt;

&lt;h1&gt;System monitoring in general&lt;/h1&gt;

&lt;p&gt;We’ve traditionally employed &lt;a href="http://nagios.org"&gt;Nagios&lt;/a&gt; as our cluster-wide monitoring tool. However, Nagios gets really clumsy dealing with anything that needs to happen locally on a machine like monitoring a specific process without outside connectivity (think &lt;code&gt;127.0.0.1&lt;/code&gt;) or something like restarting a service that’s unavailable for some reason (nagios-nrpe? Yech!).&lt;/p&gt;

&lt;h1&gt;A different approach&lt;/h1&gt;

&lt;p&gt;Then there are systems like &lt;a href="http://www.tildeslash.com/monit/"&gt;Monit&lt;/a&gt; and &lt;a href="http://god.rubyforge.org/"&gt;God&lt;/a&gt;. Monit attempts to address the issue of not being able to &lt;em&gt;do* anything when you *know&lt;/em&gt; something is wrong (like a service being down). And God, well, God is described by its author Tom Preston-Werner (of &lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt; and &lt;a href="http://gravatar.com/"&gt;Gravatar&lt;/a&gt; fame) as “like monit, only awesome”. &lt;/p&gt;

&lt;h1&gt;Enter god&lt;/h1&gt;

&lt;p&gt;God’s awesomeness (apart from its name) comes from the fact that it uses your favorite programming language (and all of its nice syntax tricks) for its config file. The &lt;a href="http://god.rubyforge.org/"&gt;god homepage&lt;/a&gt; has a plethora of configuration examples ranging from simple poll-based monitoring to using sophisticated event-based monitoring through its native support for kqueue/netlink, so I’m not going to repeat any of that here. In short: God rocks. (As if you didn’t know that already.)&lt;/p&gt;

&lt;h1&gt;Replacing the spinner/spawner duo&lt;/h1&gt;

&lt;p&gt;Here’s a short configuration recipe to replace an existing spinner/spawner configuration for FastCGI with God. Basically, I’m just writing this down for myself, since I’m probably the only one stuck with a FastCGI-based app. So you may just as well stop reading here and grab a latte.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# config.god
RAILS_ROOT = "/apps/yourapp/current"

7000.upto(7009) do |port|
  God.watch do |w|
    w.name  = "#{`hostname`.strip}-fastcgi-#{port}"

    w.pid_file = File.join(RAILS_ROOT, "tmp/pids/dispatch.#{port}.pid")

    w.start = "spawn-fcgi -f #{RAILS_ROOT}/public/dispatch.fcgi -p #{port} -P #{w.pid_file}"
    w.stop  = "kill -9 `cat #{w.pid_file}`"

    w.interval = 30.seconds

    w.start_if do |start|
      start.condition(:process_running) do |c|
        c.interval = 5.seconds
        c.running = false
      end
    end

    w.restart_if do |restart|
      restart.condition(:memory_usage) do |c|
        c.above = 200.megabytes
        c.times = [3, 5]
      end
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

This config spawns and monitors 10 FastCGi processes on the machine we’re running god on. The name god shows in its logs, status reports and email notifications is derived from the machine name plus its port number. The process is monitored every 5 seconds to make sure it’s running. It’s also monitored every 30 seconds (the default) whether it’s above or beyond the set memory limit of 200MB, which was what originally got me playing with god.

Of course you can then start weaving in all sorts of additional niftyness such as email notification, monitoring for maximum CPU usage, etc. But that’s beyond the scope of this post and it’s also nicely outlined on the god website.

Live monitoring
===============

Getting a quick overview what’s up:

&lt;pre&gt;
$ god status
http-3-fastcgi-7000: up
http-3-fastcgi-7001: up
http-3-fastcgi-7002: up
http-3-fastcgi-7003: up
http-3-fastcgi-7004: up
http-3-fastcgi-7005: up
http-3-fastcgi-7006: up
http-3-fastcgi-7007: up
http-3-fastcgi-7008: up
http-3-fastcgi-7009: up
&lt;/pre&gt;

&lt;p&gt;Fetching log entries for a specific port (sub-string match):&lt;/p&gt;

&lt;pre&gt;
$ god log 7004
I, [2008-02-04T12:31:30.361125 #20050]  INFO -- : http-3-fastcgi-7004 [ok] process is running (ProcessRunning)
I, [2008-02-04T12:31:30.372208 #20050]  INFO -- : http-3-fastcgi-7004 [ok] memory within bounds [92256kb, 92256kb, 92256kb, 92256kb, 92256kb] (MemoryUsage)
I, [2008-02-04T12:32:00.601712 #20050]  INFO -- : http-3-fastcgi-7004 [ok] process is running (ProcessRunning)
I, [2008-02-04T12:32:00.617895 #20050]  INFO -- : http-3-fastcgi-7004 [ok] memory within bounds [92256kb, 92256kb, 92256kb, 92256kb, 92256kb] (MemoryUsage)
I, [2008-02-04T12:32:30.816031 #20050]  INFO -- : http-3-fastcgi-7004 [ok] process is running (ProcessRunning)
I, [2008-02-04T12:32:30.923948 #20050]  INFO -- : http-3-fastcgi-7004 [ok] memory within bounds [92256kb, 92256kb, 92256kb, 92256kb, 92256kb] (MemoryUsage)
&lt;/pre&gt;

&lt;p&gt;Are you using God yet?&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=zSPIGq"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=zSPIGq" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=NCye5I"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=NCye5I" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=QuvS9I"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=QuvS9I" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=hwD34i"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=hwD34i" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=tQKRoI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=tQKRoI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=wHFa8i"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=wHFa8i" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/228846983" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2008%2F2%2F4%2Fuse-god-to-spawn-fastcgi-processes</feedburner:awareness><feedburner:origLink>http://poocs.net/2008/2/4/use-god-to-spawn-fastcgi-processes</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2008-01-27:589</id>
    <published>2008-01-27T00:37:00Z</published>
    <updated>2008-02-04T12:11:58Z</updated>
    <category term="Apple" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/223743528/drag-and-drop-file-upload" rel="alternate" type="text/html" />
    <title>Drag and drop file upload on a Mac</title>
<content type="html">
            &lt;p&gt;Uploading files to web applications via a browser an the accompanying web form is a necessity nowadays. It’s also a necessity to download things at &lt;em&gt;site A&lt;/em&gt; and upload them to &lt;em&gt;site B&lt;/em&gt;. Or upload something you’ve received in an email. Or upload a screenshot you just took.&lt;/p&gt;

&lt;p&gt;While the process in and of itself is fairly straightforward, it can sure be tedious. Especially if you’re hunting a download or a screenshot in the file chooser that seems to be the only way to get that pointer to the file in question down the web browsers virtual throat.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://poocs.net/assets/2008/1/26/Window.png" alt="File Upload" /&gt;&lt;/p&gt;

&lt;p&gt;Some site specific browsers such as &lt;a href="http://www.karppinen.fi/pyro/"&gt;Pyro&lt;/a&gt; (for 37signals’ &lt;a href="http://campfirenow.com/"&gt;Campfire&lt;/a&gt;) ease that process somewhat by implementing a drag-and-drop handler that allows you to drop files into the Pyro application window, which is then automatically uploaded. Dragging a file into a regular Safari or Firefox window will attempt to view that file, though, which is not what you want (most of the time).&lt;/p&gt;

&lt;p&gt;But here’s an interesting observation I made the other day, which I haven’t read about anywhere else.&lt;/p&gt;

&lt;p&gt;If you start dragging something into the OS dialog that you get to pick a file with, the dialog will automatically navigate to the folder enclosing the dragged (and dropped) something and pre-select that something so you just need to hit “Open” and submit the form to finish your upload. No hunting up and down folder hierarchies, no endless searching in packed download folders. Just simple drag and drop.&lt;/p&gt;

&lt;p&gt;(&lt;strong&gt;Please note:&lt;/strong&gt; This functionality could well be Leopard-only.)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://poocs.net/assets/2008/1/27/dnd_file_upload.mov"&gt;&lt;img src="http://poocs.net/assets/2008/1/27/dnd_file_upload-poster.png" alt="Drag and drop upload" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that &lt;em&gt;something&lt;/em&gt; could even be a file from your ‘Downloads’ folder fan out thingy that Leopard offers. Or the handy ‘Drag Me’ control offered by &lt;a href="http://plasq.com/skitch"&gt;Plasq’s Skitch&lt;/a&gt;, completely removing the need to store a one-off screenshot in a memorable place before uploading it somewhere.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://poocs.net/assets/2008/1/27/fan-out-1.png" alt="Dock fan-out" /&gt;&lt;/p&gt;

&lt;p&gt;Happy uploading.&lt;/p&gt;

&lt;p&gt;PS: This does work with any such dialog the OS presents to you, be it an ‘Open’ dialog in TextMate or Photoshop or the file chooser in Safari or Firefox.&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=BEv0KM"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=BEv0KM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=9iONwI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=9iONwI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=9zxTII"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=9zxTII" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=pu6gGi"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=pu6gGi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=jm4oNI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=jm4oNI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=tUaIhi"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=tUaIhi" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/223743528" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2008%2F1%2F27%2Fdrag-and-drop-file-upload</feedburner:awareness><feedburner:origLink>http://poocs.net/2008/1/27/drag-and-drop-file-upload</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2008-01-21:571</id>
    <published>2008-01-21T21:53:00Z</published>
    <updated>2008-01-21T21:55:02Z</updated>
    <category term="Rails" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/220603548/fighting-willpaginate-invalidpage-exceptions" rel="alternate" type="text/html" />
    <title>Fighting invalid page exceptions</title>
<content type="html">
            &lt;p&gt;The &lt;a href="http://rock.errtheblog.com/will_paginate"&gt;will_paginate&lt;/a&gt; plugin by Err The Blog feat. Mislav sure is one heck of a must have.&lt;/p&gt;

&lt;p&gt;But there’s a tiny thing that’s been bugging me for a while. In December of last year (yeah, last year, been a while..) Mislav &lt;a href="http://err.lighthouseapp.com/projects/466/tickets/129-will_paginate-should-make-sure-that-the-page-param-is-an-integer"&gt;committed a change&lt;/a&gt; to the plugin that changed the behavior of &lt;code&gt;WillPaginate::Collection&lt;/code&gt; to raise an exception if/when the &lt;code&gt;page&lt;/code&gt; argument converted to an integer is smaller than 1 (which, quite naturally, any non-integer will eventually end up as).&lt;/p&gt;

&lt;p&gt;This change was committed as an attempt to address the invalid SQL generation that happened before (you’d end up with something like &lt;code&gt;LIMIT -10, 10&lt;/code&gt; in the SQL given a non-integer &lt;code&gt;page&lt;/code&gt; argument), so this is first and foremost a good thing.&lt;/p&gt;

&lt;p&gt;If, however, the only thing that ever makes your &lt;code&gt;page&lt;/code&gt; argument a non-integer is during those times where your app is attacked by weird spam bots trying to exploit your PHP (&lt;em&gt;cough&lt;/em&gt;) application by shoving random strings down your URIs, things slowly start being annoying if you’re using the &lt;a href="http://svn.rubyonrails.org/rails/plugins/exception_notification/README"&gt;exception_notification&lt;/a&gt; plugin at the same time and end up with hundreds of exception notifications in your inbox (or, heaven forbid, tickets in your bug tracker) for the &lt;code&gt;WillPaginate::InvalidPage&lt;/code&gt; exception on a URL like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://eins.de/videos?page=http%3A%2F%2Fwww.****.info%2Fimages%2Flebun%2Fisexopo%2F
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(Obfuscation mine.)&lt;/p&gt;

&lt;p&gt;So what’s an annoyed Ruby hacker to do? Work around it!&lt;/p&gt;

&lt;h1&gt;The global problem&lt;/h1&gt;

&lt;p&gt;You can surely go ahead and hack a &lt;code&gt;rescue&lt;/code&gt; clause into all of your actions that make use of &lt;code&gt;will_paginate&lt;/code&gt; but actually you really shouldn’t. You want these things handled globally.&lt;/p&gt;

&lt;p&gt;Initially I was trying to go down the simple route, simply handling it via Rails 2.0’s &lt;code&gt;rescue_from&lt;/code&gt; macro:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# app/controllers/application.rb
class ApplicationController &amp;lt; ActionController::Base

  rescue_from WillPaginate::InvalidPage, :with =&gt; :invalid_page

  protected

    def invalid_page
      render :text =&gt; 'Invalid page requested', :status =&gt; 400
    end

end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But there are two problems with this approach.&lt;/p&gt;

&lt;p&gt;First of all, I actually wanted to serve a real page instead of an error page. Occasionally someone will mistype a URL or someone will link off of his page erroneously omitting something important and I don’t want him or her looking at an error page. I’d much rather have him look at the first page of the collection he’d like to paginate, which should be closer to the page s/he actually requested.&lt;/p&gt;

&lt;p&gt;The second problem is that the application in question isn’t running on Rails 2.0 yet. Yes, I know. Bear with me here.&lt;/p&gt;

&lt;h1&gt;Hacking the root of the problem&lt;/h1&gt;

&lt;p&gt;Instead of approaching the problem from the controller side I decided to work on it from the plugin’s perspective. I wanted a default of &lt;code&gt;page = 1&lt;/code&gt; unless a valid page was specified. So I ended up patching &lt;code&gt;WillPaginate::Collection#initialize&lt;/code&gt; like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# config/initializers/will_paginate_extension.rb
WillPaginate::Collection.send :include, WillPaginate::CollectionExtension

module WillPaginate
  module CollectionExtension

    def self.included(base)
      base.send :alias_method_chain, :initialize, :page_sanitizing
    end

    def initialize_with_page_sanitizing(page, per_page, total = nil)
      page = 1 if page.to_i.zero?
      initialize_without_page_sanitizing page, per_page, total
    end

  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will simply and quite effectively reset the page to view to 1 if anything that evaluates to a zero integer is passed in.&lt;/p&gt;

&lt;p&gt;Okay, enough babbling for such a basic thing. Thanks for reading (if you actually got this far).&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=l0yH2Y"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=l0yH2Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=zCV3iJ"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=zCV3iJ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=MwVXRJ"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=MwVXRJ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=2KioCj"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=2KioCj" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=4etoaJ"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=4etoaJ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=jmZexj"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=jmZexj" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/220603548" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2008%2F1%2F21%2Ffighting-willpaginate-invalidpage-exceptions</feedburner:awareness><feedburner:origLink>http://poocs.net/2008/1/21/fighting-willpaginate-invalidpage-exceptions</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2007-11-14:561</id>
    <published>2007-11-14T20:58:23Z</published>
    <updated>2007-11-14T20:58:23Z</updated>
    <category term="Rails" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/184866199/special-characters-and-nested-routes" rel="alternate" type="text/html" />
    <title>Special characters and nested routes</title>
<content type="html">
            &lt;p&gt;I might be the only crazy guy on the planet using strings as the primary record identifier in the URI and also allowing a bunch of special characters in it. And just in case I am, please move along. I’ll just keep this article around as a reference for myself.&lt;/p&gt;

&lt;p&gt;Say you’ve got a Rails web app from the early days. Way back when REST and Rails haven’t been spending day and night together. Back when we just had named routes.&lt;/p&gt;

&lt;p&gt;But actually, back when it was already popular to occasionally use something different from the numeric primary key to identify a resource in a URL. Example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/profile/show/scoop
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, as far as that would actually resemble a URI of my own profile, some people are way fancier with their nicknames and the punctuation therein. The most prominent punctuation character is probably the period (&lt;code&gt;.&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Back in the days, that was all dandy. Well, that was then and this is now.&lt;/p&gt;

&lt;h1&gt;Meet the Resource&lt;/h1&gt;

&lt;p&gt;With restful routes, we don’t need no stinkin’ named routes (for the most part). A simple declaration like&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# config/routes.rb
map.resources :users
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and we get a boatload of useful helpers such as &lt;code&gt;user_path&lt;/code&gt; and &lt;code&gt;new_user_path&lt;/code&gt; generating the appropriate URIs for us. But I digress.&lt;/p&gt;

&lt;p&gt;Rewiring our application to use restful routes for the &lt;code&gt;User&lt;/code&gt; model (after having seen the light), all’s well until you try to access a URI like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/users/mr.piggy
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Eek! Rails interprets the period as a designation of &lt;em&gt;format&lt;/em&gt;, like in &lt;code&gt;/users.xml&lt;/code&gt; to offer an XML representation of the requested resource.&lt;/p&gt;

&lt;p&gt;Now, who wants a piggy representation of a user?&lt;/p&gt;

&lt;p&gt;To allow a period in the &lt;code&gt;params[:id]&lt;/code&gt; part of the URL (which, after all, is what the username ends up in after routing is done chopping apart the requested URI), Rails 2 will have a way to re-use the &lt;code&gt;:requirements&lt;/code&gt; parameter as an argument to &lt;code&gt;map.resources&lt;/code&gt;, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# config/routes.rb
map.resources :users,
  :requirements =&gt; { :id =&gt; %r([^/;,?]+) }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(Note: This has been committed to the Rails trunk back in February of 2007 as changeset &lt;a href="http://dev.rubyonrails.org/changeset/6232"&gt;6232&lt;/a&gt;. I backported it as a patch to Rails 1.2 residing locally in my application (so I didn’t have to directly modify the Rails code. If there’s an interest in that I’ll post it as a separate article in a few days.)&lt;/p&gt;

&lt;p&gt;Boom, now &lt;code&gt;/users/mr.piggy&lt;/code&gt; nicely ends up having a &lt;code&gt;params[:id]&lt;/code&gt; value of &lt;code&gt;mr.piggy&lt;/code&gt; (instead of a value of &lt;code&gt;mr&lt;/code&gt; and a failing attempt to render a &lt;code&gt;piggy&lt;/code&gt; format).&lt;/p&gt;

&lt;h1&gt;What about nesting?&lt;/h1&gt;

&lt;p&gt;But our journey doesn’t end here. Coincidentally, if a site has users, those users tend to interact with it (in a true Web 2.0 fashion, you know).&lt;/p&gt;

&lt;p&gt;Adding further to &lt;code&gt;routes.rb&lt;/code&gt;, we now have a routing configuration like this&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# config/routes.rb
map.resources :users,
  :requirements =&gt; { :id =&gt; %r([^/;,?]+) } do |users|

  users.resources :interests
  users.resources :buddies
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Easy, right? Trying to access a URL like &lt;code&gt;/users/mr.piggy/buddies&lt;/code&gt; throws an exception though.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;No route matches "/users/mr.piggy/buddies" with {:method=&amp;gt;:get}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The fix would be to add the &lt;code&gt;:requirements&lt;/code&gt; constraint to all the nested routes as well.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# config/routes.rb
map.resources :users,
  :requirements =&gt; { :id =&gt; %r([^/;,?]+) } do |users|

  users.resources :interests,
    :requirements =&gt; { :id =&gt; %r([^/;,?]+) }
  users.resources :buddies,
    :requirements =&gt; { :id =&gt; %r([^/;,?]+) }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Such a nasty repetition. Especially considering we might add a bunch of additional resources in there. &lt;code&gt;Object#with_options&lt;/code&gt; to the rescue. Here’s the refactored version:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
# config/routes.rb
map.resources :users,
  :requirements =&gt; { :id =&gt; %r([^/;,?]+) } do |users|

  users.with_options :requirements =&gt; {
    :id =&gt; %r([^/;,?]+)
  } do |users_requirements|

    users_requirements.resources :interests
    users_requirements.resources :buddies
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Much better. Accessing &lt;code&gt;/users/mr.piggy/buddies&lt;/code&gt; works as expected now, routing to &lt;code&gt;BuddiesController#index&lt;/code&gt; with &lt;code&gt;params[:user_id]&lt;/code&gt; having a value of &lt;code&gt;mr.piggy&lt;/code&gt;, which you can use in a before filter to setup the parent resource.&lt;/p&gt;

&lt;h1&gt;Final words&lt;/h1&gt;

&lt;p&gt;It’s debatable whether or not it’s a good idea to allow punctuation characters in the URI. In my case, reworking parts of an existing application with an existing user base of several hundred thousand registered users I didn’t have an option but to comply.&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=KwCcV9"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=KwCcV9" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=b2nXvI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=b2nXvI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=y7o2UI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=y7o2UI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=0KfxOi"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=0KfxOi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=W1dghI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=W1dghI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=7strgi"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=7strgi" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/184866199" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2007%2F11%2F14%2Fspecial-characters-and-nested-routes</feedburner:awareness><feedburner:origLink>http://poocs.net/2007/11/14/special-characters-and-nested-routes</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2007-11-08:560</id>
    <published>2007-11-08T22:23:47Z</published>
    <updated>2007-11-08T22:24:32Z</updated>
    <category term="Rails" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/181872025/slow-queries-rails-habtm-gotcha" rel="alternate" type="text/html" />
    <title>Slow queries: Rails habtm gotcha</title>
<content type="html">
            &lt;p&gt;Back in the old days when some brave souls started with Rails, the framework would automatically supply helper methods to check the availability of associated records for every &lt;code&gt;has_many&lt;/code&gt; or &lt;code&gt;has_and_belongs_to_many&lt;/code&gt; association in the form of &lt;code&gt;has_foos?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, given a declaration like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
class User
  has_and_belongs_to_many :interests
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;would get you &lt;code&gt;User#has_interests?&lt;/code&gt; back in the days.&lt;/p&gt;

&lt;p&gt;Fast forward to the present, these methods have long been removed from Rails core. There’s no 1:1 replacement, really. When you want to check a collection in a conditional for whether or not it’s empty, there are several things you can do.&lt;/p&gt;

&lt;h1&gt;Association Proxies, a quick review&lt;/h1&gt;

&lt;p&gt;Basically, every collection is a derivative of the &lt;code&gt;Array&lt;/code&gt; class, as such most of &lt;code&gt;Array&lt;/code&gt;s methods have been (re-)implemented for the respective collection proxies.&lt;/p&gt;

&lt;p&gt;First of all, there’s &lt;code&gt;collection#length&lt;/code&gt;, which is the most brutal of them all because it simply loads the &lt;em&gt;whole&lt;/em&gt; collection into memory and runs &lt;code&gt;#size&lt;/code&gt; on it.&lt;/p&gt;

&lt;p&gt;Next up is &lt;code&gt;collection#count&lt;/code&gt;, which uses an SQL &lt;code&gt;COUNT()&lt;/code&gt; statement to just fetch the number of associated records and is usually the quickest way at that.&lt;/p&gt;

&lt;p&gt;Finally, there’s &lt;code&gt;collection#size&lt;/code&gt;, which is basically a combination of both &lt;code&gt;length&lt;/code&gt; and &lt;code&gt;count&lt;/code&gt; since it behaves differently depending on whether or not the collection has already been loaded at the time it is being called. Given the collection has already been loaded (by a prior statement in your code, what have you) it’s identical to &lt;code&gt;collection#length&lt;/code&gt;. If it hasn’t been loaded, its behavior is identical to &lt;code&gt;collection#count&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;Best practice&lt;/h1&gt;

&lt;p&gt;Judging from the rundown above, it’s usually best practice to simply use &lt;code&gt;collection#size&lt;/code&gt; and trust it to do the right thing. In case you’re planning to use a collection as soon as you found out there are records associated with it, use &lt;code&gt;collection#length&lt;/code&gt; to load the connection right away and then loop over it. Beware, however, that this is advisable only for those cases that don’t use pagination. (You’re using &lt;a href="http://errtheblog.com/post/4791"&gt;will_paginate&lt;/a&gt; for that, aren’t you?)&lt;/p&gt;

&lt;p&gt;In a conditional, it makes most sense to use &lt;code&gt;collection#empty?&lt;/code&gt;, which uses &lt;code&gt;size#zero?&lt;/code&gt; internally.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
unless user.interests.empty?
  # ...
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;The problem&lt;/h1&gt;

&lt;p&gt;99% of what I said above applies to both &lt;code&gt;has_many&lt;/code&gt; and &lt;code&gt;has_and_belongs_to_many&lt;/code&gt; associations. Admittedly, poor little &lt;code&gt;habtm&lt;/code&gt; has had its momentum and seems to be on the way out of the cool kids’ block. Still, there are a few cases where it’s still the best fit (such as the &lt;code&gt;User#interests&lt;/code&gt; example from first section of this article) and some people *do* have Rails code that’s been in existence for a few years. (Well, maybe only I do.)&lt;/p&gt;

&lt;p&gt;So, the 1% that behaves differently is that &lt;code&gt;size&lt;/code&gt; on a &lt;code&gt;habtm&lt;/code&gt; collection is not as intelligent as its little brother from the &lt;code&gt;has_many&lt;/code&gt; camp. In fact, it’s pretty dumb because it’s in every case behaving identical to &lt;code&gt;length&lt;/code&gt; meaning it’s loading the whole collection. Ouch.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; user.interests.size
  Join Table Columns (0.001284)   SHOW FIELDS FROM interests_users
  Interest Load (0.001263)   SELECT * FROM interests
    INNER JOIN interests_users
    ON interests.id = interests_users.interest_id
    WHERE (interests_users.user_id = 142841 )
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;The solution&lt;/h1&gt;

&lt;p&gt;You have to fill in the gaps of &lt;code&gt;habtm#size&lt;/code&gt;’s lack of intelligence yourself. If you trap over &lt;code&gt;habtm&lt;/code&gt; queries that take way too long for your taste, it might be about time to swap out that &lt;code&gt;size&lt;/code&gt; call for an always speedy &lt;code&gt;count&lt;/code&gt; call.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; u.interests.count
  Interest Columns (0.001006)   SHOW FIELDS FROM interests
  SQL (0.009749)   SELECT count(*) AS count_all FROM interests
    INNER JOIN interests_users
    ON interests.id = interests_users.interest_id
    WHERE (interests_users.user_id = 142841 )
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You would then also avoid using &lt;code&gt;collection#empty?&lt;/code&gt; in your conditionals, since that would then resort back to using &lt;code&gt;size&lt;/code&gt; internally. Instead, use the &lt;code&gt;count#zero?&lt;/code&gt; form or define your own instance methods on the association.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
if user.interests.count.zero?
  # ..
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;Postscript&lt;/h1&gt;

&lt;p&gt;To actually find out what Rails is transforming your method calls into (in terms of generated SQL) I prefer to use &lt;a href="http://weblog.jamisbuck.org/2007/1/8/watching-activerecord-do-it-s-thing"&gt;this technique&lt;/a&gt; by the always-wise Jamis Buck. Redirecting the &lt;code&gt;ActiveRecord&lt;/code&gt; logger to the shell’s standard output will intermix the SQL statements with the output of your method calls, making everything relevant visible at first glance.&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=JjUyHF"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=JjUyHF" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=HipFPI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=HipFPI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=9KJkhI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=9KJkhI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=tXlHPi"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=tXlHPi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=m4XeuI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=m4XeuI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=6as0Ji"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=6as0Ji" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/181872025" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2007%2F11%2F8%2Fslow-queries-rails-habtm-gotcha</feedburner:awareness><feedburner:origLink>http://poocs.net/2007/11/8/slow-queries-rails-habtm-gotcha</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2007-10-23:517</id>
    <published>2007-10-23T14:45:06Z</published>
    <updated>2007-10-23T14:47:59Z</updated>
    <category term="Rails" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/173854916/revisiting-date-localization-for-ruby-1-8-6" rel="alternate" type="text/html" />
    <title>Revisiting date localization for Ruby 1.8.6</title>
<content type="html">
            &lt;p&gt;Welcome to my yearly post about a revised version of a simple way to localize Ruby’s &lt;code&gt;Time#strftime&lt;/code&gt; method (after my &lt;a href="http://poocs.net/2005/10/4/localization-for-ruby-s-time-strftime"&gt;original post in ‘05&lt;/a&gt; and the &lt;a href="http://poocs.net/2006/7/24/revisiting-time-strftime-localization"&gt;update in ‘06&lt;/a&gt;).&lt;/p&gt;

&lt;h1&gt;What’s changed?&lt;/h1&gt;

&lt;p&gt;In my original methodology, the arrays in the &lt;code&gt;Date&lt;/code&gt; class containing the
actual day and month names in clear text had to be replaced by strings wrapped
in the infamous &lt;code&gt;_()&lt;/code&gt; call of GetText in order to spit out their localized
versions when requested from the modified &lt;code&gt;Time#strftime&lt;/code&gt; call.&lt;/p&gt;

&lt;p&gt;When Ruby 1.8.6 came along, it had its &lt;code&gt;Date&lt;/code&gt; array constants frozen. While I
agree it’s generally not a good idea to modify the contents of a constant
(it’s a &lt;em&gt;constant&lt;/em&gt; after all, mind you), the implementation I came up with 2
years ago worked fine up to and including today.&lt;/p&gt;

&lt;p&gt;Since, also, most of the sites I’m working on require multiple languages (as
opposed to, say, a single language set at application boot time), the contents
of those &lt;code&gt;Date&lt;/code&gt; arrays truly need to be modified at runtime and having those
arrays frozen meant jumping through all sorts of hoops to address a supposedly
simple issue.&lt;/p&gt;

&lt;h1&gt;What now?&lt;/h1&gt;

&lt;p&gt;Well, I had to come up with a way to actually execute the gettext
functionality in the context of an object that has the current GetText locale
bound to it. The most obvious object with that kind of property is
&lt;code&gt;ApplicationController&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But this still leaves us with the issue that we cannot modify the frozen
&lt;code&gt;Date&lt;/code&gt; constants and that everything we put into these constants is evaluated
right away instead of at a point where we have the desired locale set.&lt;/p&gt;

&lt;p&gt;What I came up with was a proxy object derived from the &lt;code&gt;Array&lt;/code&gt; class that
would basically just wrap the cleartext contents that are already in each of
the &lt;code&gt;Date&lt;/code&gt; arrays but not before they’re actually accessed/output.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
    # lib/date_localization.rb
    class GetTextDateProxy &amp;lt; Array

      cattr_accessor :gettext_proxy

      def [](key)
        _(at(key))
      end

      def _(string)
        return string unless gettext_proxy
        gettext_proxy.instance_eval { gettext(string) }
      end

    end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see, the proxy object is pretty simple after all. It just
overwrites the default of &lt;code&gt;Array#[]&lt;/code&gt; to look up the requested key and then
wrap the output in &lt;code&gt;_()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since I couldn’t actually be bothered to include the whole of Ruby-GetText
into my poor little proxy object, I then made room for it to hold a pointer to
an instance of &lt;code&gt;ApplicationController&lt;/code&gt; in a class attribute called
&lt;code&gt;gettext_proxy&lt;/code&gt;. The local underscore method of my proxy class then wraps
around the actual gettext implementation available to the gettext proxy (read:
&lt;code&gt;ApplicationController&lt;/code&gt;), returning the string unchanged if there is no
gettext proxy and if there is, run the string through the proxy’s &lt;code&gt;gettext&lt;/code&gt;
method.&lt;/p&gt;

&lt;p&gt;Dealing with a state of not having a gettext proxy available is actually
necessary in cases where there are calls to these arrays before
&lt;code&gt;ApplicationController&lt;/code&gt; gets to hook itself up to &lt;code&gt;GetTextDateProxy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But how does this actually hook into the &lt;code&gt;Date&lt;/code&gt; class now? Let’s take a look:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
    # lib/date_localization.rb
    class Date

      silence_warnings do
        %w(
          MONTHNAMES DAYNAMES ABBR_MONTHNAMES ABBR_DAYNAMES
        ).each do |array|
          class_eval %( #{array} = GetTextDateProxy.new(#{array}) )
        end
      end

    end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;While this still looks a little tedious, it’s far less tedious than repeating
the arrays’ contents simply wrapped in &lt;code&gt;_()&lt;/code&gt; all over the place, like we had
to do in previous incarnations of this methodology.&lt;/p&gt;

&lt;p&gt;Basically, now every array is hooked up with their very own instance of
&lt;code&gt;GetTextDateProxy&lt;/code&gt; which then takes care of running the strings through
gettext in the appropriate moments.&lt;/p&gt;

&lt;h1&gt;Wiring it all up&lt;/h1&gt;

&lt;p&gt;For the last part, we need to get &lt;code&gt;ApplicationController&lt;/code&gt; to hook itself into
&lt;code&gt;GetTextDateProxy&lt;/code&gt; after having received the appropriate locale for the
request it’s dealing with.&lt;/p&gt;

&lt;p&gt;The best fit for this is the &lt;code&gt;after_init_gettext&lt;/code&gt; hook provided by
Ruby-GetText. Adding this code to &lt;code&gt;ApplicationController&lt;/code&gt; will take care of
the last required step.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;
    # app/controllers/application.rb
    after_init_gettext { GetTextDateProxy.gettext_proxy = self }    
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here you go, working (albeit hackish) localization for Ruby’s &lt;code&gt;Time#strftime&lt;/code&gt; working up to and including the most recent version of Ruby, which is 1.8.6 as of this writing.&lt;/p&gt;

&lt;p&gt;Enjoy.&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=bmY0CC"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=bmY0CC" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=JUtAdI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=JUtAdI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=nM2QJI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=nM2QJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=bGZYdi"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=bGZYdi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=Slb7WI"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=Slb7WI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=zQBtRi"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=zQBtRi" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/173854916" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2007%2F10%2F23%2Frevisiting-date-localization-for-ruby-1-8-6</feedburner:awareness><feedburner:origLink>http://poocs.net/2007/10/23/revisiting-date-localization-for-ruby-1-8-6</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2007-10-02:482</id>
    <published>2007-10-02T18:59:24Z</published>
    <updated>2007-11-25T16:47:07Z</updated>
    <category term="Rails" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/164327729/ruby-debug-howto-and-free-book-pdf-download" rel="alternate" type="text/html" />
    <title>Ruby-Debug HOWTO and free book</title>
<content type="html">
            &lt;p&gt;Somewhere between the release of &lt;a href="http://sitepoint.com/books/rails1"&gt;my Rails book&lt;/a&gt; and now, several things happened. First of all, &lt;a href="http://www.ruby-lang.org/en/news/2007/03/12/ruby-1-8-6-released/"&gt;Ruby 1.8.6&lt;/a&gt; was released in March and quickly became the &lt;a href="http://rubyonrails.org/down"&gt;preferred version&lt;/a&gt; to use with Rails application with the release of &lt;a href="http://weblog.rubyonrails.org/2007/3/14/rails-1-2-3-compatible-with-ruby-1-8-6-and-other-fixes"&gt;Rails 1.2.3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This, however, meant the end to the era of the breakpointer library to debug your Rails application, which relied on a bug in Ruby that had been fixed in Ruby 1.8.5 onwards. The Rails Core group was quick to adopt &lt;a href="http://www.datanoise.com/ruby-debug/"&gt;ruby-debug&lt;/a&gt;, Kent Sibilev’s native implementation of a Ruby debugger which was also heavily inspired by more powerful debuggers from other programming languages such as C.&lt;/p&gt;

&lt;p&gt;With the &lt;a href="http://weblog.rubyonrails.org/2007/9/30/rails-2-0-0-preview-release"&gt;preview release of Rails 2.0&lt;/a&gt;, available since Sep 30, integration of ruby-debug has been fostered even more.&lt;/p&gt;

&lt;p&gt;For this very reason, I recently sat down and wrote a replacement chapter for my Rails book that serves both as a gentle conceptual introduction to ruby-debug (which still somewhat lacks detailed hands-on articles, due to its still fairly young age) and a replacement for the example debugging sessions the printed book has (but relying on the slightly different operation of the breakpointer client).&lt;/p&gt;

&lt;p&gt;The article is available through &lt;a href="http://www.sitepoint.com/article/debug-rails-app-ruby-debug"&gt;SitePoint.com&lt;/a&gt;. Please note, however, that you should have the source code for the sample application from the book available, to give yourself some context and the full scope of the code.&lt;/p&gt;

&lt;h1&gt;Rails book available for FREE&lt;/h1&gt;

&lt;p&gt;On a related note, SitePoint, the publisher of &lt;a href="http://sitepoint.com/books/rails1"&gt;Build Your Own Ruby on Rails Web Applications&lt;/a&gt;, decided to offer the &lt;strong&gt;entire book as a free PDF download&lt;/strong&gt; for a limited time period of 60 days starting today. Grab your copy of the 474 pages (including the updated chapter on debugging making use of ruby-debug) &lt;a href="http://rails.sitepoint.com/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;div&gt;
&lt;a href="http://rails.sitepoint.com/"&gt;&lt;img src="http://sitepointstatic.com/images/books/rails1/cover3d-1-2.png" alt="" /&gt;&lt;/a&gt;
&lt;/div&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=yBeF2j"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=yBeF2j" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=Ae3FOJVn"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=Ae3FOJVn" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=GHSw0DdR"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=GHSw0DdR" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=Fajz7eRs"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=Fajz7eRs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=AzywQc29"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=AzywQc29" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=wypVaRk7"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=wypVaRk7" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/164327729" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2007%2F10%2F2%2Fruby-debug-howto-and-free-book-pdf-download</feedburner:awareness><feedburner:origLink>http://poocs.net/2007/10/2/ruby-debug-howto-and-free-book-pdf-download</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2007-09-23:478</id>
    <published>2007-09-23T22:08:00Z</published>
    <updated>2007-09-24T07:43:00Z</updated>
    <category term="Conferences" />
    <category term="rails railsconf railsconfeurope" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/160355254/railsconf-europe-2007" rel="alternate" type="text/html" />
    <title>RailsConf Europe 2007 Retrospective</title>
<content type="html">
            &lt;div&gt;
&lt;a href="http://www.flickr.com/photos/scoop/1402919737/" title="Photo Sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1181/1402919737_fa723b96e9_m.jpg" height="160" alt="RailsConf Europe Logo" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;As some of you might or might not now (depending on whether or not you’ve been following my &lt;a href="http://twitter.com/poocs"&gt;Twitter stream&lt;/a&gt;), I’ve spent the past week touring Berlin for &lt;a href="http://railsconfeurope.com"&gt;RailsConf Europe&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;Foreword&lt;/h1&gt;

&lt;p&gt;It’s always a difficult undertaking who you’re trying to attract with such a specialized conference like RailsConf, being about a specific framework in a specific area of development (The Web). Go too technical and lose the beginners. Stay too broad or basic and lose those who have been following for years. With RailsConf Europe 2007, I think the balance was basically pretty much spot on.&lt;/p&gt;

&lt;p&gt;But: The same holds true for the audience, too. I occasionally had a hard time figuring out the “level of sophistication” of some of the talks beforehand, so I could decide which of the 4 tracks in parallel was worth attending. And sometimes I picked wrong and let go of a presentation for one that turned out to be much too broad and lacking depth.&lt;/p&gt;

&lt;p&gt;I’m sure attempts to solve this issue have come up before. Everything from including a short passage of “recommended skills to attend” or a simplified, numeric “sophistication index” that goes on the schedule with the title and description of the talk might help. Or create additional confusion. There you have one of the reasons why I’m not putting together conferences.&lt;/p&gt;

&lt;h1&gt;Tutorials&lt;/h1&gt;

&lt;p&gt;RailsConf Europe 2007 kicked off on Monday, September 17 with a day of (mostly) half-day &lt;a href="http://www.railsconfeurope.com/pub/w/61/tutorials.html"&gt;tutorial sessions&lt;/a&gt; in parallel tracks. (One of the morning tutorials then had to be cancelled at short notice, though.)&lt;/p&gt;

&lt;p&gt;I had opted for the &lt;a href="http://www.railsconfeurope.com/cs/railseurope2007/view/e_sess/14221"&gt;BDD tutorial&lt;/a&gt; from the &lt;a href="http://rspec.rubyforge.org/"&gt;RSpec&lt;/a&gt; guys. I’ve been using RSpec in a couple projects now so I was well prepared for not getting too much out of it, but still hoped that some best practice would be dealt with.&lt;/p&gt;

&lt;div&gt;&lt;a href="http://www.flickr.com/photos/37581743@N00/1403808340" title="View 'Dan North' on Flickr.com"&gt;&lt;img src="http://farm2.static.flickr.com/1120/1403808340_2afb107564.jpg" height="333" alt="Dan North" width="500" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;The guys were indeed having a good time on stage and the presentation was okay. (Actually, it was fairly uncommon practice to use a mind-map instead of presentation slides, but let’s save that story for next time.)&lt;/p&gt;

&lt;p&gt;The tutorial got messy when the audience was asked to download the code for a sample application from the RSpec Subversion repository and no-one was actually able to get more than a few bytes down the pipe due to the massively overwhelmed Wi-Fi (more on that in a later section). This then exaggerated into a wild USB-stick trading scene and in the end we didn’t even get around looking at the code at all. That was a tad disappointing.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In the afternoon I then attended the &lt;a href="http://www.railsconfeurope.com/cs/railseurope2007/view/e_sess/14267"&gt;Scaling Rails&lt;/a&gt; tutorial of &lt;a href="http://jasonhoffman.org/"&gt;Jason Hoffman&lt;/a&gt; of &lt;a href="http://joyent.com/"&gt;Joyent&lt;/a&gt; (I have that scaling thing going, as some of you &lt;a href="http://poocs.net/search?q=adventures+of+scaling"&gt;might remember&lt;/a&gt;).&lt;/p&gt;

&lt;div&gt;&lt;a href="http://www.flickr.com/photos/37581743@N00/1403005415" title="View 'Jason Hoffman' on Flickr.com"&gt;&lt;img src="http://farm2.static.flickr.com/1415/1403005415_5288e99dd2.jpg" height="333" alt="Jason Hoffman" width="500" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Jason spent quite an amount of time talking about some of their preferred hard- and software setups as well as some of the specifics of being the host for &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt;, which was nice.&lt;/p&gt;

&lt;p&gt;Scaling talks can only be so far applicable to your own itches since this is one of the topics that is so tightly bound to the application specifics that it’s simply impossible to state more than a handful best practices and then spend a great amount of time with case studies.&lt;/p&gt;

&lt;h1&gt;Keynotes&lt;/h1&gt;

&lt;p&gt;The actual conference was then kicked off later Monday night by program chair David Black and the opening keynote by &lt;a href="http://pragdave.blogs.pragprog.com/pragdave/"&gt;Dave Thomas&lt;/a&gt;, “The Art in Rails”.&lt;/p&gt;

&lt;div&gt;&lt;a href="http://www.flickr.com/photos/37581743@N00/1403986186" title="View 'Dave Thomas' on Flickr.com"&gt;&lt;img src="http://farm2.static.flickr.com/1100/1403986186_02ad807518.jpg" height="333" alt="Dave Thomas" width="500" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;I truly enjoyed Dave’s speech, being the first of his I saw in-person. Rather than giving a tech-heavy presentation (that he had, from his own words, gotten several beating for), Dave went down the philosophical path of contrasting software development with art. His speech is covered sufficiently by &lt;a href="http://casperfabricius.com/blog/2007/09/17/railsconf-the-art-in-rails/"&gt;Casper Fabricius&lt;/a&gt; and &lt;a href="http://www.liverail.net/articles/2007/9/18/railsconf-europe-dave-thomas-keynote"&gt;Stuart Eccles&lt;/a&gt; - I have little (if anything) to add there.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Tuesday morning was then started by The Man Himself, &lt;a href="http://www.loudthinking.com/"&gt;David Heinemeier Hansson&lt;/a&gt; talking about the upcoming release of Rails 2.0. &lt;/p&gt;

&lt;p&gt;DHH presented smaller increments of progress the core team has made during the past several months and stated that at this point they’re focussing on evolutions rather than revolutions since Rails has successfully had enough of the latter since it was first released.&lt;/p&gt;

&lt;div&gt;&lt;a href="http://www.flickr.com/photos/37581743@N00/1403210859" title="View 'David Heinemeier Hansson' on Flickr.com"&gt;&lt;img src="http://farm2.static.flickr.com/1385/1403210859_24a7b7148d.jpg" height="333" alt="David Heinemeier Hansson" width="500" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Rails 2.0 will see a preview release in the short term, so David presented the old (way before Rails 1.0) and upcoming (past 2.0) way of developing a sample application (the now infamous weblog application that starred the very first Rails introductory screencast).&lt;/p&gt;

&lt;p&gt;Additional notes and code samples are, again, available from &lt;a href="http://casperfabricius.com/blog/2007/09/18/railsconf2007-dhh/"&gt;Casper Fabricius&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Another keynote worth mentioning was &lt;a href="http://www.ics.uci.edu/~fielding/"&gt;Dr. Roy T. Fielding&lt;/a&gt;’s talk “The Rest of REST”, dealing with, as the name suggest, REST as an architecture of developing modern web applications. &lt;/p&gt;

&lt;div&gt;&lt;a href="http://www.flickr.com/photos/37581743@N00/1403383059" title="View 'Roy T. Fielding' on Flickr.com"&gt;&lt;img src="http://farm2.static.flickr.com/1390/1403383059_fcaf23d629.jpg" height="333" alt="Roy T. Fielding" width="500" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Over the course of his talk, Roy Fielding for several times returned to a graph of how many web sites the World Wide Web had at a certain time while he iterated over major milestones in WWW and HTTP history as well as his involvement sculpting the protocols and specifications that drive major parts of the internet today.&lt;/p&gt;

&lt;p&gt;Fielding even looked at Rails’ REST implementation (looking from the outside in, as he hasn’t really developed applications in Rails so far) and offered suggestions on how to improve it. His &lt;a href="http://conferences.oreillynet.com/presentations/railsconfeurope07/re7_royfielding.pdf"&gt;slides are available&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;Sessions&lt;/h1&gt;

&lt;p&gt;The schedule of RailsConf Europe 2007 was packed. 50+ sessions were scheduled to take place in 4 parallel tracks. Of positive note should be that the track locations were so close together that almost no time was lost traveling around. But, as indicated in the foreword, there were time slots in the schedule that had me want to split in quarters to be able to attend all 4 tracks at once.&lt;/p&gt;

&lt;p&gt;Another negative aspect was that only the keynotes were actually recorded. Having missed out on a couple sessions for the reasons above, I’m not even able to watch a recording of a session I missed.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;From the sessions I went to I really liked &lt;a href="http://blog.fallingsnow.net/"&gt;Evan Phoenix&lt;/a&gt;’ presentation about the state of &lt;a href="http://rubini.us/"&gt;Rubinius&lt;/a&gt;, his alternative Ruby implementation.&lt;/p&gt;

&lt;p&gt;Evan is now working full-time on Rubinius (financed by &lt;a href="http://www.engineyard.com/"&gt;EngineYard&lt;/a&gt;) and has made really good progress during the past months. He’s anticipating a preview release of Rubinius 1.0 as early as November (yes, of 2007).&lt;/p&gt;

&lt;p&gt;Apart from the interestingness the Rubinius project brings with it, Evan sure had the best made up stats graphs of the entire conference. Not to mention his awesome tie.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In a fill-in effort for Jamis Buck (who just released &lt;a href="http://weblog.jamisbuck.org/2007/9/9/child-3-0"&gt;Child 3.0&lt;/a&gt;), &lt;a href="http://www.vernix.org/marcel/"&gt;Marcel Molina Jr.&lt;/a&gt; joined &lt;a href="http://www.koziarski.net/"&gt;Michael Koziarski&lt;/a&gt; in a Rails Best Practices session along the lines of what they do over at &lt;a href="http://www.therailsway.com/"&gt;The Rails Way&lt;/a&gt;.&lt;/p&gt;

&lt;div&gt;&lt;a href="http://www.flickr.com/photos/37581743@N00/1407387194" title="View 'Michael Koziarski and Marcel Molina Jr.' on Flickr.com"&gt;&lt;img src="http://farm2.static.flickr.com/1212/1407387194_3427052962.jpg" height="333" alt="Michael Koziarski and Marcel Molina Jr." width="500" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Using several (supposedly bad) code samples the duo explained how one could improve readability, modularity, and maintainability all at once by following several simple guidelines such as ”&lt;a href="http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model"&gt;Skinny Controller, Fat Model&lt;/a&gt;”, as first introduced on Jamis Buck’s blog in 2006.&lt;/p&gt;

&lt;p&gt;Make sure all of these suggestions go straight into your “common sense” bin.&lt;/p&gt;

&lt;h1&gt;The Venue&lt;/h1&gt;

&lt;p&gt;RailsConf Europe 2007 took place in the &lt;a href="http://www.maritim.de/typo3/english/hotels/hotels/proarte-hotel-berlin.html"&gt;Maritim proArte Berlin&lt;/a&gt;. As soon as your brain adjusted for the fact that the street-address-facing side of the hotel is actually a mall that doesn’t look at all like a hotel, the hotel worked fairly well as a venue for a 800+ attendee conference.&lt;/p&gt;

&lt;p&gt;Being located in downtown Berlin on Friedrichstrasse, the hotel was both in little distance to most travel places (3km to the central station, 15 minutes cab ride to the next airport) &lt;em&gt;and&lt;/em&gt; around lots of decent food places.&lt;/p&gt;

&lt;p&gt;Speaking of food, lunch was a disaster. And I’m not talking about the food per-se (which was good), but the organization around getting 800+ attendees to their food (or rather, vice versa). If the session you attended happened to end a few minutes late, you’d have to expect to be stuck in lines for the next 20-30 minutes, risking either your cigarette break or your siesta (or both).&lt;/p&gt;

&lt;p&gt;The breaks between the sessions as well as the lunch and intermediate breaks were nicely laid out and enough time for both participants and the venue staff to re-arrange the conference rooms going from keynote-mode into split-tracks mode.&lt;/p&gt;

&lt;p&gt;From a technical standpoint, two things got in the way of the conference being a full win. First of all, as mentioned in the tutorials section above, the Wi-Fi was unusable most of the time. Luckily, the Wi-Fi at Starbucks right next door would accept the conference credentials for access and provided much better connectivity.&lt;/p&gt;

&lt;p&gt;Additionally, the lights on stage and in the session rooms were really bad if you happen to have a passion for photography. Even Mr. Conference Photography himself &lt;a href="http://twitter.com/duncan/statuses/279673732"&gt;twittered that&lt;/a&gt;. So for the next event, I’ll have to bring my flashes and &lt;a href="http://www.pocketwizard.com/"&gt;PocketWizards&lt;/a&gt; and mess with Duncan’s lighting.&lt;/p&gt;

&lt;h1&gt;Summary&lt;/h1&gt;

&lt;p&gt;It was indeed a good conference where I’ve finally met several people I had only been having electronic conversations with. (So that part of the “networking” actually worked out well.)&lt;/p&gt;

&lt;p&gt;Now I’m looking forward to &lt;a href="http://conferences.oreillynet.com/rails/"&gt;RailsConf US 2008&lt;/a&gt; in Portland (May 29-Jun 01), although I’m not yet certain that I will be able to attend. The next RailsConf Europe will be in Berlin again, but the dates aren’t set yet. As David Black put it: “Block out the entire fall.”&lt;/p&gt;

&lt;h1&gt;Related Reading&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://flickr.com/photos/scoop/sets/72157602072372687/"&gt;My Flickr set&lt;/a&gt; or &lt;a href="http://flickr.com/photos/tags/railsconfeurope07/"&gt;All photos tagged railsconfeurope07&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://conferences.oreillynet.com/pub/w/61/presentations.html"&gt;Presentation Slides&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;David Heinemeier Hansson: &lt;a href="http://www.loudthinking.com/posts/12-good-times-at-railsconf-europe"&gt;Good times at RailsConf Europe&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;David Heinemeier Hansson: &lt;a href="http://www.loudthinking.com/posts/11-sun-surprises-at-railsconf-europe-2007"&gt;Sun surprises at RailsConf Europe 2007&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;James Duncan Davidson: &lt;a href="http://duncandavidson.com/archives/590"&gt;Inspirational Keynotes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Peter Cooper: &lt;a href="http://www.rubyinside.com/railsconf-eu-2007-wrap-up-608.html"&gt;RailsConf EU 2007 Wrap Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;RidingRails: &lt;a href="http://weblog.rubyonrails.com/2007/9/20/railsconf-eu-07-is-over"&gt;RailsConf EU ‘07 is over&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=6XKM79"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=6XKM79" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=dHxrImOc"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=dHxrImOc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=ebDMxdjy"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=ebDMxdjy" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=3H7MY2rN"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=3H7MY2rN" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=wOSCDetk"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=wOSCDetk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=gwaEtdkN"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=gwaEtdkN" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/160355254" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2007%2F9%2F23%2Frailsconf-europe-2007</feedburner:awareness><feedburner:origLink>http://poocs.net/2007/9/23/railsconf-europe-2007</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2007-09-21:467</id>
    <published>2007-09-21T08:28:00Z</published>
    <updated>2007-11-01T14:25:05Z</updated>
    <category term="Apple" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/159376351/apple-wireless-keyboard" rel="alternate" type="text/html" />
    <title>Apple Wireless Keyboard: First impressions</title>
<content type="html">
            &lt;div&gt;&lt;a href="http://www.flickr.com/photos/37581743@N00/1416824834" title="View 'Apple Wireless Keyboard' on Flickr.com"&gt;&lt;img src="http://farm2.static.flickr.com/1347/1416824834_faaafbcd3c.jpg" height="333" alt="Apple Wireless Keyboard" width="500" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Apple announced &lt;a href="http://www.apple.com/keyboard/"&gt;new keyboards&lt;/a&gt; alongside its new iMacs in early August, but the bluetooth variant wasn’t shipping until mid-September. As you can see, mine just shipped (I’ve been using Apple bluetooth keyboards since they first came out).&lt;/p&gt;

&lt;p&gt;When you initially open the package, these things really seem tiny. But in the end, they’re exactly the size as the thicker older model minus the numeric keypad and cursor keys moved over.&lt;/p&gt;

&lt;p&gt;With regards to the touch feel (and I’m typing this on the keyboard you see above), they feel different but I can type quick and fast easily. The keyboard of my MacBook Pro still feels a little softer and typing on the old whitish Apple keyboards is a different deal altogether. The lowered height of the device is definitely a welcome change.&lt;/p&gt;

&lt;p&gt;So far I don’t miss the numeric keypad (and I’m far from being an accountant). The only thing I have to mentally adjust for is the lack of an enter key right next to where I keep the mouse. Due to the smaller size, my mouse currently lives quite a bit to the right and I tended to hit that extra enter key with my right hand occasionally when reaching over from the mouse. This hits solid table ground for the time being. But I’ll live.&lt;/p&gt;

&lt;p&gt;Keyboard Update 1.2 popped up when checking with Software Update after pairing the keyboard, installed and rebooted, the new keys for Dashboard and iTunes (play/pause/skip) worked immediately. So no issues to report there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Here’s a shot of the front edge with a (metric) ruler attached to it, as some commenters indicated interest in it.&lt;/p&gt;

&lt;div&gt;&lt;a href="http://www.flickr.com/photos/37581743@N00/1417062681" title="View 'Apple Wireless Keyboard' on Flickr.com"&gt;&lt;img src="http://farm2.static.flickr.com/1253/1417062681_2291b186d9.jpg" height="333" alt="Apple Wireless Keyboard" width="500" /&gt;&lt;/a&gt;&lt;/div&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=BQbsjV"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=BQbsjV" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=NwUdEvSZ"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=NwUdEvSZ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=jGWRdmeM"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=jGWRdmeM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=j56XKvcV"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=j56XKvcV" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=FTXhRiL9"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=FTXhRiL9" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=yGPKfoc0"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=yGPKfoc0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/159376351" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2007%2F9%2F21%2Fapple-wireless-keyboard</feedburner:awareness><feedburner:origLink>http://poocs.net/2007/9/21/apple-wireless-keyboard</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2007-09-11:466</id>
    <published>2007-09-11T18:15:00Z</published>
    <updated>2007-09-11T20:26:27Z</updated>
    <category term="Web" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/155183227/highrise-use-tags-as-the-poor-man-s-case" rel="alternate" type="text/html" />
    <title>Highrise: Use Tags as the Poor Man's Case</title>
<content type="html">
            &lt;p&gt;&lt;a href="http://www.highrisehq.com"&gt;Highrise&lt;/a&gt;, 37signals’ simple CRM system, features cases to &lt;a href="http://www.highrisehq.com/tour#cases"&gt;keep related stuff together&lt;/a&gt;. Depending on which plan you’re on, you may end up with anywhere from &lt;a href="http://www.highrisehq.com/signup"&gt;1 to unlimited cases&lt;/a&gt; available to you.&lt;/p&gt;

&lt;p&gt;Well, I love cases. And I hate them at the same time.&lt;/p&gt;

&lt;h1&gt;The problem with cases&lt;/h1&gt;

&lt;p&gt;We’re currently in the process of building a house. That means a lot of correspondence and a lot of involved people. I currently have more than 30 people attached to my ‘House’ case. Arguably, I could split it up into multiple cases, but that wouldn’t address my issues and concerns with the use of a busy case like this.&lt;/p&gt;

&lt;p&gt;First of all, case assignment is a manual process. And it’s always at least 2 clicks away (and something you have to remember doing). (&lt;a href="http://37signals.blogs.com/products/2007/09/new-highrise-fe.html"&gt;Reducing clicks is good&lt;/a&gt;, btw.)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/scoop/1361382737/" title="Photo Sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1310/1361382737_93070d9345_o.png" height="127" alt="Adding note in Highrise" width="557" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you’re adding a note to a contact, you have to remember clicking that little “Show options (files, cases, permissions)” to actually pick your case from the drop down menu. Admittedly, 37signals did try to reduce clutter in that form and all options &lt;em&gt;besides&lt;/em&gt; the case drop down would actually *be* clutter. However, one out of two notes I’m adding I forget to assign a case. Blame it on my age.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/scoop/1361392907/" title="Photo Sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1404/1361392907_1071881703_o.png" height="156" alt="Assigning a case in Highrise" width="557" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Things get much worse when you’re just forwarding or Bcc’ing email to Highrise. That puts off case assignment even farther as you have to remember to &lt;em&gt;actually open Highrise&lt;/em&gt; to do so. That, I won’t remember for life.&lt;/p&gt;

&lt;h1&gt;Enter Tags&lt;/h1&gt;

&lt;p&gt;The tags implementation in Highrise has recently seen welcome improvements. Most recently, they rolled out an update that lets you &lt;a href="http://37signals.blogs.com/products/2007/08/new-highrise-fe.html"&gt;filter by multiple tags&lt;/a&gt; and a while farther back they gave us 
&lt;a href="http://37signals.blogs.com/products/2007/08/tag-tab-and-str.html"&gt;tag streams and tag tabs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What especially the latter improvement buys us is a way to circumvent the cumbersome case assignment problem I was talking about in the last section. tag streams will collect all correspondence with contacts having a particular tag assigned automatically, whether you manually add notes directly in Highrise or forward/bcc email to Highrise. The tag stream will immediately reflect the new item.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/scoop/1362332968/" title="Photo Sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1372/1362332968_d6fd6a999c_o.png" height="84" alt="Tag stream in Highrise" width="557" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another little nicety of the tag streams is that they carry over the little ‘Task completed’ markers for completed tasks assigned to contacts tagged with a particular tag.&lt;/p&gt;

&lt;p&gt;Tags, as mentioned before, will also show up as one of the recently visited tabs at the top of the page, next to contacts, companies, and ‘real’ cases. Additionally, the ‘Tags’ tab provides you with a list of all of your tags as well as recently viewed ones for easy and speedy access.&lt;/p&gt;

&lt;p&gt;Finally, if you’re on the Free or Personal plans of Highrise, tags obviously won’t count against your limit of cases are allowed to have open simultaneously.&lt;/p&gt;

&lt;h1&gt;The Drawbacks&lt;/h1&gt;

&lt;p&gt;We all know there is No Free Lunch.&lt;/p&gt;

&lt;p&gt;Using tags for cases means that as soon as a contact is involved in more than one case (or tag) you’re out of luck. The correspondence of both tags would accumulate in the tag streams and things would get wonky.&lt;/p&gt;

&lt;p&gt;Also, while you can assign tasks to a case, you cannot assign tasks to tags (yet?). While this is not mission critical, I occasionally make use of this feature when dealing with cases.&lt;/p&gt;

&lt;p&gt;On a visible note, cases nicely display the attached contacts and companies right there next to the stream of notes attached to a case. Highrise’s tag streams are just that, streams of correspondence. There’s a separate page for listing the contacts and companies tagged with a given tag.&lt;/p&gt;

&lt;p&gt;Lastly, tags don’t have an open/close status like cases do. And since Highrise doesn’t allow for renaming of tags after the fact, you’re stuck with either removing tags from contacts after projects are done or have them stick around forever.&lt;/p&gt;

&lt;h1&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;I mostly find myself using tags to complement cases, not instead of them. I hate going over a day’s correspondence to reassign cases so I tend to trust my tagging when reviewing a certain project’s correspondence through its tag stream. Cases still give the better overview in terms of being open and closed, though. Maybe a future Highrise update will rectify some of the concerns I’ve raised in this post requiring another mind shift.&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=2N4YAj"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=2N4YAj" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=ThO9zkKG"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=ThO9zkKG" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=o0sJeUD9"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=o0sJeUD9" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=kNdGrATv"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=kNdGrATv" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=Cm4EdRnb"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=Cm4EdRnb" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=dpyzRhRj"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=dpyzRhRj" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/155183227" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2007%2F9%2F11%2Fhighrise-use-tags-as-the-poor-man-s-case</feedburner:awareness><feedburner:origLink>http://poocs.net/2007/9/11/highrise-use-tags-as-the-poor-man-s-case</feedburner:origLink></entry>
  <entry xml:base="http://poocs.net/">
    <author>
      <name>scoop</name>
    </author>
    <id>tag:poocs.net,2007-09-05:461</id>
    <published>2007-09-05T18:43:00Z</published>
    <updated>2007-09-10T07:24:54Z</updated>
    <category term="Personal" />
    <category term="personal life update 2007" />
    <link href="http://feeds.feedburner.com/~r/poocsnet/~3/152634348/september-2007-a-life-update" rel="alternate" type="text/html" />
    <title>September 2007, a life update</title>
<content type="html">
            &lt;p&gt;&lt;em&gt;Tap tap&lt;/em&gt;, is this thing on?&lt;/p&gt;

&lt;p&gt;Looking at the fact that the most recent article on this site was written on May 9 was making me sad for a long time, yet I always found plenty of excuses to not produce new content. (All of them being moot, of course.)&lt;/p&gt;

&lt;p&gt;So here I am, finally convincing myself that letting this site die out totally would be bad in way too many ways. I haven’t yet formally decided in which direction content will be flowing, so I’ll try to give a simple update of recent happenings.&lt;/p&gt;

&lt;h1&gt;The book&lt;/h1&gt;

&lt;p&gt;The major project that kept me busy during the second half of last year was of course finishing up my beginner’s book about developing Rails applications for &lt;a href="http://www.sitepoint.com/"&gt;SitePoint&lt;/a&gt;. &lt;a href="http://www.sitepoint.com/books/rails1/"&gt;Build Your Own Ruby on Rails Web Applications&lt;/a&gt; has been selling for roughly 6 months now and I’m eagerly awaiting the first sales figures.&lt;/p&gt;

&lt;p&gt;Due to the fact that we were pushing the book out right after the release of Rails 1.2 it might’ve been a bumpy ride for some readers at some point since several major things changed in the Rails world after the book went to print. Because of that, the book ended up with a fairly big chunk of errata. Still, it was the right decision to focus on Rails 1.2 at that point and the errata has hopefully been comprehensive enough to assist readers when they got stuck. I also monitor the &lt;a href="http://www.sitepoint.com/forums/"&gt;SitePoint forums&lt;/a&gt; closely and jump in to assist whenever necessary.&lt;/p&gt;

&lt;p&gt;Additionally, one particular chapter in the book, although still applicable, got outdated quickly and will soon enough be replaced with new content that is going up on SitePoint.com as an article real soon now.&lt;/p&gt;

&lt;h1&gt;Gwen turns 2&lt;/h1&gt;

&lt;p&gt;On July 30th, my daughter Gwendolyn turned 2 having her first “real” birthday party with friends and such. It was an exhausting endeavor for both her and us :) But still, a lot of fun!&lt;/p&gt;

&lt;div&gt;&lt;a href="http://www.flickr.com/photos/37581743@N00/1328820268" title="View 'Gwen' on Flickr.com"&gt;&lt;img src="http://farm2.static.flickr.com/1406/1328820268_925f589cee.jpg" height="500" alt="Gwen" width="333" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;In general, Gwen’s been awesome. Although she’s only two, she’s talking about as much as I am, probably more. So much talking, so many words coming out of her baby brain. She’s also learning the alphabet using her new &lt;a href="http://www.vtech.com/toys/"&gt;VTech&lt;/a&gt; learning laptop.&lt;/p&gt;

&lt;p&gt;Oh, and no, as &lt;a href="http://www.kottke.org/07/09/back-in-the-saddle"&gt;Kottke put it&lt;/a&gt;, this site won’t turn “into some kind of daddyblog” either.&lt;/p&gt;

&lt;h1&gt;RSpec&lt;/h1&gt;

&lt;p&gt;After having happily spent a long time in the &lt;a href="http://chneukirchen.org/blog/archive/2007/01/announcing-test-spec-0-3-a-bdd-interface-for-test-unit.html"&gt;test/spec&lt;/a&gt; camp when it comes to Behavior Driven Development for my Rails projects, I’ve &lt;a href="http://twitter.com/poocs/statuses/101347982"&gt;recently&lt;/a&gt; started to adopt RSpec for my current and future projects. Its tight integration and the solidness coming with recent releases (past the 1.0 milestone, I guess) really made it a joy to work with.&lt;/p&gt;

&lt;p&gt;Currently being in an unreleased and still-ironing-out-the-bugs state, the next release of RSpec will also come with &lt;a href="http://dannorth.net/2007/06/introducing-rbehave"&gt;rbehave&lt;/a&gt; merged into it, so it’s also possible to setup user stories to replace Rails’ own integration tests. Pat Maddox has &lt;a href="http://evang.eli.st/blog/2007/9/1/user-stories-with-rspec-s-story-runner"&gt;a beautiful write-up&lt;/a&gt; on this very topic. &lt;/p&gt;

&lt;p&gt;The lead developers of RSpec are also giving a talk titled &lt;a href="http://www.railsconfeurope.com/cs/railseurope2007/view/e_sess/14221"&gt;A Half-day of Behavior-driven Development on Rails&lt;/a&gt; at the upcoming RailsConf Europe.&lt;/p&gt;

&lt;h1&gt;Visited by JDD&lt;/h1&gt;

&lt;p&gt;As for even more recent happenings, my friend and photographic mentor &lt;a href="http://duncandavidson.com/"&gt;James Duncan Davidson&lt;/a&gt; visited me as part of his trip to Europe this month. Besides the usual “show me yours and I’ll show you mine” geekery we’ve obviously been out and about to shoot a few frames of several places in and around Wiesbaden, Germany.&lt;/p&gt;

&lt;div&gt;&lt;a href="http://www.flickr.com/photos/37581743@N00/1328817414" title="View 'Duncan' on Flickr.com"&gt;&lt;img src="http://farm2.static.flickr.com/1317/1328817414_b2f9c691ed.jpg" height="500" alt="Duncan" width="333" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Although the weather was far from striking (cloudy skies, frequent yet light rain showers), a couple pictures actually turned out pretty decently. You can find Duncan’s photoset &lt;a href="http://flickr.com/photos/x180/sets/72157601802011676/"&gt;here on Flickr&lt;/a&gt;, mine is &lt;a href="http://www.flickr.com/photos/scoop/sets/72157601822270009/"&gt;right next to it&lt;/a&gt;. Duncan also blogged about 
&lt;a href="http://duncandavidson.com/archives/580"&gt;this part&lt;/a&gt; &lt;a href="http://duncandavidson.com/archives/581"&gt;of his&lt;/a&gt; &lt;a href="http://duncandavidson.com/archives/582"&gt;trip&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;RailsConf&lt;/h1&gt;

&lt;p&gt;Speaking of Duncan, he’s also hopped to Europe to shoot RailsConf Europe taking place in Berlin, Germany this year from September 17-19 featuring a boatload of interesting talks and sessions. While yours truly will not be presenting anything, I’m attending the conference and will be in Berlin starting September 16. Shoot me a message if you’re in town as well.&lt;/p&gt;

&lt;p&gt;And by the way of Rails conferences, I’ve also attended Rails Konferenz in Frankfurt, Germany last June. My set of pictures shooting the conference can be found &lt;a href="http://flickr.com/photos/scoop/sets/72157600455347393/"&gt;on Flickr&lt;/a&gt;, as usual. The conference itself was a little lacking, for my taste, probably due to the fact that RailsConf Europe is coming up now and people had been opting to rather go there instead of the Frankfurt one. Still, it’s a worthy effort that &lt;a href="http://www.b-simple.de/"&gt;Thomas Baustert&lt;/a&gt; and friends should keep on pursuing.&lt;/p&gt;

&lt;h1&gt;Photography&lt;/h1&gt;

&lt;p&gt;As you might’ve guessed from the entries of my &lt;a href="http://scoop.tumblr.com/"&gt;tumblelog&lt;/a&gt; and the references in this article, photography has taken up quite a seat in my life. I have yet to find my favorite shooting environment (although I’m pretty much certain that I don’t want to pursue a career as a beauty and fashion photographer) so I’m experimenting with all sorts of different shooting situations from available light to using strobes, from landscapes to studio work, from conference shooting to casual street shooting.&lt;/p&gt;

&lt;p&gt;The workflow tool of choice as of March of 2007 has been &lt;a href="http://www.adobe.com/products/photoshoplightroom/"&gt;Adobe Lightroom&lt;/a&gt; (previously I was hooked up to &lt;a href="http://www.apple.com/aperture/"&gt;Apple Aperture&lt;/a&gt; until it showed that Lightroom’s workflow was so much faster dealing with huge RAW images of my Canon full-frame body).&lt;/p&gt;

&lt;p&gt;Lightroom has really been a pleasure to work with. If you need a primer of what it can do for you, Michael Reichmann’s and Jeff Schewe’s Lightroom Video Tutorial &lt;a href="http://luminous-landscape.com/videos/LR-V1.shtml"&gt;sold through Luminous Landscape&lt;/a&gt; is probably the best resource for this. Additionally, the O’Reilly blog &lt;a href="http://digitalmedia.oreilly.com/lightroom/"&gt;Inside Adobe Lightroom&lt;/a&gt; has daily tips, tricks and workflow help for working with the program. Duncan even published &lt;a href="http://www.oreillynet.com/digitalmedia/blog/2007/09/speeding_up_entry_of_metadata_1.html"&gt;two of my Lightroom tips&lt;/a&gt; recently.&lt;/p&gt;

&lt;p&gt;I’ve setup a placeholder site at &lt;a href="http://photo.graphi.st/"&gt;photo.graphi.st&lt;/a&gt; for what may or may not become a future business.&lt;/p&gt;

&lt;h1&gt;OmniFocus&lt;/h1&gt;

&lt;p&gt;Self-organizing by using methodologies such as &lt;a href="http://www.davidco.com/"&gt;Getting Things Done&lt;/a&gt; and &lt;a href="http://www.43folders.com/izero/"&gt;Inbox Zero&lt;/a&gt; have long been part of my life. What I haven’t found thus far was the perfect tool for the job. I’ve pondered baking my own, but haven’t gone down that path for various reasons, the most important being.. the lack of time.&lt;/p&gt;

&lt;p&gt;Right now my private and professional life is spread over several tools, including but not limited to the trio infernale from 37signals (Highrise, Basecamp, Backpack), my IMAP mailboxes, and, as of recently, the still-not-quite-beta &lt;a href="http://www.omnigroup.com/applications/omnifocus/"&gt;OmniFocus&lt;/a&gt; from the OmniGroup.&lt;/p&gt;

&lt;p&gt;OmniFocus still has some way to go before being able to take over the center spot of my self-organization. But let’s be fair, they haven’t left the alpha stage. Yet still, they’ve accomplished quite something with regards to the workflow OmniFocus encourages. My major roadblock right now is the fact that it’s a desktop app. My tasks have always been with me in some form, yet with OmniFocus and even using tools like &lt;a href="http://www.foldershare.com/"&gt;FolderShare&lt;/a&gt; (ignoring the fact that they’ve been acquired by Microsoft and been dormant for quite some time now) means I’ll have to remember to close the application on all of my machines when leaving the house or office or it’ll complain about “already being open”.&lt;/p&gt;

&lt;p&gt;Maybe there’s a blog post or two to come out of this. I don’t yet know. I’ll try hard to adopt. And adapt.&lt;/p&gt;

&lt;h1&gt;Music I’m listening to&lt;/h1&gt;

&lt;p&gt;Closing off this way too lengthy post, here are some of the albums that I’ve recently added to my playlist.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?id=213329388&amp;amp;amp;s=143443"&gt;&lt;img src="http://a1.phobos.apple.com/eu/r10/Music/9a/67/67/mzi.ylqcuwbl.170x170-75.jpg" alt="Chill Lounge Cape Town Vol.2" /&gt;&lt;/a&gt;
&lt;a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?id=261319335&amp;amp;amp;s=143443"&gt;&lt;img src="http://a1.phobos.apple.com/eu/r40/Music/d8/1e/5b/mzi.vdsbhxyc.170x170-75.jpg" alt="H-Blockx - Open Letter to a Friend" /&gt;&lt;/a&gt;
&lt;a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?id=253430402&amp;amp;amp;s=143443"&gt;&lt;img src="http://a1.phobos.apple.com/eu/r10/Music/78/c5/f1/mzi.zfqnppmp.170x170-75.jpg" alt="30 Seconds to Mars - A Beautiful Lie" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?id=251126923&amp;amp;amp;s=143443"&gt;&lt;img src="http://a1.phobos.apple.com/eu/r10/Music/f7/32/5b/mzi.bqpypwju.170x170-75.jpg" alt="Arctic Monkeys - Favourite Worst Nightmare" /&gt;&lt;/a&gt;
&lt;a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?id=217813396&amp;amp;amp;s=143443"&gt;&lt;img src="http://a1.phobos.apple.com/eu/r10/Music/81/7b/24/mzi.ooqmmamb.170x170-75.jpg" alt="Good Charlotte - Good Morning Revival" /&gt;&lt;/a&gt;
&lt;a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?id=253405269&amp;amp;amp;s=143443"&gt;&lt;img src="http://a1.phobos.apple.com/eu/r10/Music/2d/d6/99/mzi.wyzighne.170x170-75.jpg" alt="Linkin Park - Minutes to Midnight" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?id=219774515&amp;amp;amp;s=143443"&gt;&lt;img src="http://a1.phobos.apple.com/eu/r10/Music/2e/18/0e/mzi.ptwjwvvv.170x170-75.jpg" alt="Gods of Blitz - Reporting a Mirage" /&gt;&lt;/a&gt;
&lt;a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?id=160346607&amp;amp;amp;s=143443"&gt;&lt;img src="http://a1.phobos.apple.com/eu/r10/Music/31/89/a2/mzi.ntaoftmc.170x170-75.jpg" alt="Billy Talent - Billy Talent II" /&gt;&lt;/a&gt;
&lt;a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?id=260046429&amp;amp;amp;s=143443"&gt;&lt;img src="http://a1.phobos.apple.com/eu/r40/Music/aa/97/50/mzi.znzwalam.170x170-75.jpg" alt="Sum 41 - Underclass Hero" /&gt;&lt;/a&gt;&lt;/p&gt;
          
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~a/poocsnet?a=OHkSKu"&gt;&lt;img src="http://feeds.feedburner.com/~a/poocsnet?i=OHkSKu" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=HJCqfzwU"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=HJCqfzwU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=AXneCOx5"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=AXneCOx5" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=fuc4Kx2u"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=fuc4Kx2u" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=uZJi8d9k"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=uZJi8d9k" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/poocsnet?a=BoXlHmca"&gt;&lt;img src="http://feeds.feedburner.com/~f/poocsnet?i=BoXlHmca" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/poocsnet/~4/152634348" height="1" width="1"/&gt;</content>  <feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=poocsnet&amp;itemurl=http%3A%2F%2Fpoocs.net%2F2007%2F9%2F5%2Fseptember-2007-a-life-update</feedburner:awareness><feedburner:origLink>http://poocs.net/2007/9/5/september-2007-a-life-update</feedburner:origLink></entry>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetFeedData?uri=poocsnet</feedburner:awareness></feed>
