<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
    <title>Rob Wilkerson</title>
    <subtitle>You'll Know When I Know</subtitle>
    <id>http://robwilkerson.org/feed</id>
    <updated>2009-03-27T10:28:16-04:00</updated>
    
    <link href="http://robwilkerson.org" />
    <generator uri="http://chyrp.net/" version="2.0">Chyrp</generator>
    <link rel="self" href="http://feeds.feedburner.com/robwilkerson" type="application/atom+xml" /><feedburner:emailServiceId>robwilkerson</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry>
        <title type="html">Friendly Project Names in Komodo Edit</title>
        <id>tag:robwilkerson.org,2009-03-27:/id/175/</id>
        <updated>2009-03-27T10:31:47-04:00</updated>
        <published>2009-03-27T10:28:16-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/Y33yrNVPyws/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;For several years now, &lt;a href="http://eclipse.org"&gt;Eclipse&lt;/a&gt; has been my primary &lt;acronym title="Integrated Development Environment"&gt;&lt;span class="caps"&gt;IDE&lt;/span&gt;&lt;/acronym&gt;. I’ve used it to write in a number of languages on a number of platforms and was more or less happy with it. In the last six months or so, the scales of justice began to tip away from more and towards less until a couple of months ago when I finally hit my breaking point. I decided that I’d had enough of trying to dedicate enough system resources to keep Eclipse happy. I’d had enough of trying to keep my installs on several machines using several operating systems synced up properly. I felt like Eclipse was taking over my life rather than making it easy.&lt;/p&gt;

	&lt;p&gt;I started looking around with only a couple of key requirements:&lt;/p&gt;

	&lt;ol&gt;
		&lt;li&gt;Responsive. Not necessarily &lt;em&gt;fast&lt;/em&gt;, just responsive.&lt;/li&gt;
		&lt;li&gt;Cross platform. I’m cross-platform and I need my key software to be cross-platform too.&lt;/li&gt;
		&lt;li&gt;Power user friendly. By that, mostly I mean a rich set of keyboard shortcuts and snippets.&lt;/li&gt;
		&lt;li&gt;Free-ish. I’m happy to pay for good software, but I’m not willing to plunk down hundreds of dollars if there are almost-as-good options.&lt;/li&gt;
	&lt;/ol&gt;

	&lt;p&gt;After trying a number of &lt;span class="caps"&gt;IDE&lt;/span&gt;s and text editors, I finally settled on &lt;a href="http://www.activestate.com/komodo_edit/"&gt;Komodo Edit&lt;/a&gt;. It’s a text editor that’s lightweight and snappy the way that a text editor should be, but it has just enough &lt;span class="caps"&gt;IDE&lt;/span&gt;-like features to meet my minimal needs. It met all of my needs. &lt;/p&gt;

	&lt;p&gt;For me, one of the huge tipping points was that it is a project-based editor. I loved that particular metaphor once I started using Eclipse and it’s not something you see in a lot of text editors so I was happy to get that support. What I didn’t like was that, unlike Eclipse, I couldn’t enter a “friendly” name for my projects. Eclipse has its &lt;span class="technical"&gt;.project&lt;/span&gt; files and Komodo Edit has a &lt;span class="technical"&gt;projectname.kpf&lt;/span&gt; file, but in the latter there was no way to set a nice, human name for each project. Cracking open the &lt;span class="technical"&gt;.kpf&lt;/span&gt; project file showed me that it’s just an &lt;span class="caps"&gt;XML&lt;/span&gt; config file and that there’s a &lt;span class="technical"&gt;name&lt;/span&gt; attribute on the &lt;span class="technical"&gt;project&lt;/span&gt; root element, but changing that changed nothing.&lt;/p&gt;

	&lt;p&gt;I asked about this on the forum and one of the developers suggested that I enter an enhancement request. &lt;a href="http://bugs.activestate.com/show_bug.cgi?id=82050"&gt;I did&lt;/a&gt; and, to my surprise, a patch was made available the same day – within an hour, if I recall correctly. Since doing so, the change has been rolled into the latest version (v5.1). &lt;/p&gt;

	&lt;p&gt;To give your Komodo Edit friendly project names that will show up in the project explorer:&lt;/p&gt;

	&lt;ol&gt;
		&lt;li&gt;Create a project (if one isn’t already created).&lt;/li&gt;
		&lt;li&gt;Open the &lt;span class="technical"&gt;.kpf&lt;/span&gt; file in a text editor.&lt;/li&gt;
		&lt;li&gt;Set the value of the &lt;span class="technical"&gt;name&lt;/span&gt; attribute to the friendly value of your choice.&lt;/li&gt;
		&lt;li&gt;Save, close and restart Komodo Edit.&lt;/li&gt;
	&lt;/ol&gt;

	&lt;p&gt;Here’s what one of my &lt;span class="technical"&gt;.kpf&lt;/span&gt; files (&lt;span class="technical"&gt;scratchpad.kpf&lt;/span&gt;) looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!-- Komodo Project File - DO NOT EDIT --&gt;
&lt;project id="714c52ec-687a-0241-b5ef-eb09952b79d5" kpf_version="4" name="Scratchpad"&gt;
&lt;preference-set idref="714c52ec-687a-0241-b5ef-eb09952b79d5"&gt;
  &lt;boolean id="import_live"&gt;1&lt;/boolean&gt;
&lt;/preference-set&gt;
&lt;/project&gt;&lt;/code&gt;&lt;/pre&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2009/03/27/friendly-project-names-in-komodo-edit/</feedburner:origLink></entry>
    <entry>
        <title type="html">Clear All Growl Notifications</title>
        <id>tag:robwilkerson.org,2009-02-20:/id/174/</id>
        <updated>2009-02-20T16:49:26-04:00</updated>
        <published>2009-02-20T16:48:48-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/IZZnqUKUkTE/cleargrowl.html" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;When IM errors occur, I have Adium’s Growl alerts set to remain onscreen until I dismiss them. Unfortunately, sometimes I accidentally leave Adium online when I go to work. When I get back home, I have a huge number of notifications waiting to tell me that my user for service X is logged in from multiple locations.&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;As it turns out, there’s a simple way to close all notifications at once—just hold the Option key before clicking on the first notification.&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;Take that AOLSystemMessage guy.&lt;/p&gt;        </content>
    <feedburner:origLink>http://www.macworld.com/article/138864/2009/02/cleargrowl.html?lsrc=rss_main</feedburner:origLink></entry>
    <entry>
        <title type="html">Session Interaction with Quicksilver</title>
        <id>tag:robwilkerson.org,2009-02-17:/id/173/</id>
        <updated>2009-02-17T20:55:21-04:00</updated>
        <published>2009-02-17T20:53:35-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/Np-1g7lovak/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;Although it’s true that, on the whole, I prefer the OS X environment to that of the Ubuntu Linux environment I’ve been using at work for the last few months, the degree of that preference is not as high as I would have ever thought. Nonetheless, I have to confess that I have a tremendous preference for &lt;a href="http://do.davebsd.com/"&gt;Gnome Do&lt;/a&gt; over &lt;a href="http://blacktree.com/?quicksilver"&gt;Quicksilver&lt;/a&gt; for OS X. I know, that borders on blasphemy, right?&lt;/p&gt;

	&lt;p&gt;I prefer Do for a number of reasons that are beyond the intent of this post, but one reason is that I’ve been spoiled by having the ability to logout, restart, shutdown and otherwise interact with my user session. My inability to do so with Quicksilver has begun to frustrate me lately and tonight I finally figured out that Quicksilver has the same capability. Unfortunately, that capability is tucked away and obscured so that it’s not immediately obvious.  Session interaction, as well as a few other nice tools, is tucked away in the &lt;strong&gt;Extra Scripts&lt;/strong&gt; plugin.&lt;/p&gt;

	&lt;p&gt;Another of my frustrations with Quicksilver is the complexity of the interface, but I wanted to know what was in included with this plugin, so I dug it up in Finder. Since the plugin is really just a collection of shell scripts, it’s pretty easy to see what’s in there. Here are some of the highlights:&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;Get your current IP addresses&lt;/li&gt;
		&lt;li&gt;Eject and close the disk tray&lt;/li&gt;
		&lt;li&gt;Logout of your current session&lt;/li&gt;
		&lt;li&gt;Lock the screen&lt;/li&gt;
		&lt;li&gt;Switch to root&lt;/li&gt;
		&lt;li&gt;Put the computer to sleep&lt;/li&gt;
		&lt;li&gt;Shutdown or restart the system&lt;/li&gt;
		&lt;li&gt;Control the system volume&lt;/li&gt;
		&lt;li&gt;Empty the trash&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;More is available, but these are the functions that I thought were the most interesting or potentially useful to me. I can’t find a way to see a list of functions available in the Quicksilver UI, but if you’re interested you can see what’s included using Finder:&lt;/p&gt;

	&lt;ol&gt;
		&lt;li&gt;Open the Quicksilver preferences&lt;/li&gt;
		&lt;li&gt;Go to the &lt;strong&gt;Plug-ins&lt;/strong&gt; “tab”&lt;/li&gt;
		&lt;li&gt;Click the gear icon at the bottom of the window&lt;/li&gt;
		&lt;li&gt;Select &lt;strong&gt;Show Plug-ins Folder&lt;/strong&gt;&lt;/li&gt;
		&lt;li&gt;Right click on the &lt;strong&gt;Extra Scripts.qsplugin&lt;/strong&gt; “file” and select &lt;strong&gt;Show Package Contents&lt;/strong&gt;&lt;/li&gt;
		&lt;li&gt;Open the &lt;strong&gt;Resources/ExtraScripts&lt;/strong&gt; directory&lt;/li&gt;
		&lt;li&gt;Explore the subdirectories&lt;/li&gt;
	&lt;/ol&gt;

	&lt;p&gt;Most of the scripts are pretty descriptively named. It should be pretty apparent what functionality they provide.&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2009/02/17/session-interaction-with-quicksilver/</feedburner:origLink></entry>
    <entry>
        <title type="html">Sony Releases New Stupid Piece of Shit That Doesn’t Fucking Work</title>
        <id>tag:robwilkerson.org,2009-02-10:/id/172/</id>
        <updated>2009-02-10T20:53:29-04:00</updated>
        <published>2009-02-10T20:47:32-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/IzRwXRJFRVY/sony_releases_new_stupid_piece_of" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;blockquote&gt;
		&lt;p&gt;I can’t wait to get home and spend my whole fucking night trying to figure the goddamn thing out.&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;I heart The Onion. I’ve watched this about 30 times today and it just doesn’t get old. Just in case the title somehow isn’t clear, this is &lt;acronym title="Not Safe For Work"&gt;&lt;span class="caps"&gt;NSFW&lt;/span&gt;&lt;/acronym&gt;. At least not without headphones.&lt;/p&gt;        </content>
    <feedburner:origLink>http://www.theonion.com/content/video/sony_releases_new_stupid_piece_of</feedburner:origLink></entry>
    <entry>
        <title type="html">When SSH Public Key Authentication Fails</title>
        <id>tag:robwilkerson.org,2009-02-10:/id/171/</id>
        <updated>2009-02-10T15:08:31-04:00</updated>
        <published>2009-02-10T15:07:11-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/ZUeKwrpD3PY/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;I’m no Sys Admin, but I connect to enough Unix machines often enough that enabling public key authentication is a real time saver. For those that may not know, public key authentication allows a user to login to another machine via &lt;acronym title="Secure SHell"&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt;&lt;/acronym&gt; without a password. I’ve &lt;a href="http://musetracks.instantspot.com/blog/2007/03/13/SSHSCP-Without-Being-Prompted-for-a-Password"&gt;written a bit more about the technique&lt;/a&gt; itself in my archive.  The other day, in the course of setting up authentication for several machines at work, I noticed that it worked for most of the machines but failed for a few others. After spending a little over an hour checking and double checking the files in my &lt;span class="technical"&gt;~/.ssh&lt;/span&gt; directory, I spent another hour comparing files on the machines that weren’t working with the ones that were. Everything was &lt;em&gt;precisely the same&lt;/em&gt;.&lt;/p&gt;

	&lt;p&gt;Except that it wasn’t. Evidently I neglected to read my own earlier post, specifically step 5.  I had no idea that permissions were such a hot button, but it makes sense. The permissions on my &lt;span class="technical"&gt;~/.ssh/authorized_keys&lt;/span&gt; file were &lt;strong&gt;664&lt;/strong&gt;. The boxes wouldn’t let me login because the file was writeable by someone other than me (at least in principle).  As soon as I changed the permissions to &lt;strong&gt;644&lt;/strong&gt;, I was able to connect just fine.&lt;/p&gt;

	&lt;p&gt;Of course, I realize that this is by design and a very good thing, but I wasn’t expecting it so I stumbled over it.&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2009/02/10/when-public-key-authentication-fails/</feedburner:origLink></entry>
    <entry>
        <title type="html">Broken gets fixed. Shoddy lasts forever.</title>
        <id>tag:robwilkerson.org,2009-02-06:/id/170/</id>
        <updated>2009-02-06T20:58:13-04:00</updated>
        <published>2009-02-06T20:55:23-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/gXN3qcEAqF4/truism" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;Fail loud, fail proud, &lt;a href="http://musetracks.instantspot.com/blog/2008/01/30/Fail-Now-Fail-Loud-Fail-Proud"&gt;that’s what I say&lt;/a&gt; (in my archive). This is the reason I say that.&lt;/p&gt;        </content>
    <feedburner:origLink>http://designaday.tumblr.com/post/75496791/truism</feedburner:origLink></entry>
    <entry>
        <title type="html">Mac Owners, Freak Out Someone You Love</title>
        <id>tag:robwilkerson.org,2009-01-31:/id/168/</id>
        <updated>2009-01-31T15:26:14-04:00</updated>
        <published>2009-01-31T15:22:55-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/0cdyABtwfQY/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;My girlfriend works from home on Fridays. I do not. I do, however, leave my Mac powered on and active during the day so that I can &lt;acronym title="Secure SHell"&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt;&lt;/acronym&gt; in and access files from the office if I need to do so. Last week, knowing that she would be sitting near said computer, I decided to mess with her just a little bit. To do so, I &lt;span class="caps"&gt;SSH&lt;/span&gt;’d into the Mac and used the &lt;span class="technical"&gt;say&lt;/span&gt; command:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;$ say "Hello Tricia, this is God. Have you been touching yourself again?"&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;I personalized the line from &lt;em&gt;Real Genius&lt;/em&gt;, but you get the idea. A very nice, disembodied voice that goes by the name of Alex spoke the words aloud as if there was someone in the room with her.  She said she jumped about a six feet and had to crawl back into her own skin. She also said that she found Alex’s voice disturbingly sexy. Disturbing to whom?&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2009/01/31/mac-owners-freak-out-someone-you-love/</feedburner:origLink></entry>
    <entry>
        <title type="html">Learning CakePHP: Foreign Key Constraint Violation</title>
        <id>tag:robwilkerson.org,2009-01-30:/id/167/</id>
        <updated>2009-01-30T08:53:30-04:00</updated>
        <published>2009-01-30T08:24:01-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/b7-EbKsTZEg/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;In the course of building forms with &lt;a href="http://book.cakephp.org/view/182/Form"&gt;CakePHP’s form helper&lt;/a&gt;, I kept running into problems with the foreign key constraints in my database. I’d get an error if I didn’t enter a value in the form even though a &lt;span class="technical"&gt;&lt;span class="caps"&gt;NULL&lt;/span&gt;&lt;/span&gt; value was allowed at the database level. A little debugging indicated that the cause was &lt;a href="http://cakephp.org"&gt;CakePHP&lt;/a&gt; trying to insert an empty string into the foreign key field. Since there was no record in the parent table with an empty string id value, the database had no choice but to reject the insert request:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;SQL Error: 1452: Cannot add or update a child row: a foreign key constraint fails (`mydatabase/events`, CONSTRAINT `events_ibfk_1` FOREIGN KEY (`location_id`) REFERENCES `locations` (`id`) ON DELETE NO ACTION ON UPDATE CASCADE)&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;I will confess right now that I didn’t research this extensively and I don’t know whether this is something that’s easily avoidable using existing techniques or resources offered by CakePHP. It could also be that I’ve coded something incorrectly. What I saw, though, was an opportunity to learn. I saw an opportunity to create a behavior – something I hadn’t done yet – that would detect fields where a &lt;span class="technical"&gt;&lt;span class="caps"&gt;NULL&lt;/span&gt;&lt;/span&gt; value was acceptable and replace empty string values accordingly.&lt;/p&gt;

	&lt;p&gt;My project has events and events have locations. The relevant components of my database schema look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;CREATE TABLE locations (
   id            VARCHAR(255)   NOT NULL,
   name          VARCHAR(255)   NOT NULL,
   description   VARCHAR(255)   NULL,
   PRIMARY KEY ( id )
);
CREATE TABLE events (
   id            CHAR(36)       NOT NULL,
   location_id   VARCHAR(255)   NULL,
   name          VARCHAR(255)   NOT NULL,
   start_time    DATETIME       NOT NULL,
   end_time      DATETIME       NULL,
   PRIMARY KEY ( id ),
   FOREIGN KEY ( location_id )
      REFERENCES locations ( id )
         ON UPDATE CASCADE
         ON DELETE SET NULL
);&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Using those tables are my &lt;span class="technical"&gt;Event&lt;/span&gt; and &lt;span class="technical"&gt;Location&lt;/span&gt; models:&lt;/p&gt;

	&lt;p&gt;&lt;pre&gt;&lt;code&gt;class Event extends AppModel {
   public $name      = ‘Event’;
   public $belongsTo = array ( ‘Location’ );&lt;/p&gt;

   /** content */
}
class Location extends AppModel {
   public $name    = ‘Location’;
   public $hasMany = ‘Event’;

   /** content */
}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;In my event form, I have a dropdown list by which a user can select a location where the event will occur. Since not all events have a specific location, I’ve set the &lt;span class="technical"&gt;empty&lt;/span&gt; option to &lt;span class="technical"&gt;true&lt;/span&gt; so that the user can choose no association:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;echo $form-&gt;input (
     'location_id',
     array (
        'div'      =&gt; 'input select',
        'selected' =&gt; $this-&gt;data['Location']['id'],
        'empty'    =&gt; true
     )
);&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Unfortunately, my foreign key constraint didn’t like that empty option. My solution was to create a new &lt;span class="technical"&gt;Nullable&lt;/span&gt; behavior. All the behavior does is inspect a model’s schema and the data being saved. If a field is nullable and the data for that field is empty, the data values empty string is replaced with a &lt;span class="technical"&gt;null&lt;/span&gt; value. It does this in the &lt;span class="technical"&gt;beforeSave()&lt;/span&gt; callback function.&lt;/p&gt;

	&lt;p&gt;&lt;pre&gt;&lt;code&gt;class NullableBehavior extends ModelBehavior {
   /**
    * function beforeSave
    * Looks for nullable fields in the schema and replaces empty string values for those fields
    * with &lt;span class="caps"&gt;NULL&lt;/span&gt; values.
    */
   function beforeSave ( $model ) {
      $schema = $model-&gt;schema();&lt;/p&gt;

      foreach ( $schema as $field =&gt; $metadata ) {
         if ( $metadata[‘null’] ) {
            if ( isset ( $model-&gt;data[$model-&gt;name][$field] ) &amp;&amp; $model-&gt;data[$model-&gt;name][$field] === ‘’ ) {
               $model-&gt;data[$model-&gt;name][$field] = null;
            }
         }
      }
   }
}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Because I really like the technical accuracy that results from this solution even when constraint errors aren’t being thrown, I wanted to apply it to all of my models. Because I’m lazy, I didn’t want to write the code to add the behavior to all of those models. What I did instead was add it to my applications &lt;span class="technical"&gt;AppModel&lt;/span&gt; in the &lt;span class="technical"&gt;app/&lt;/span&gt; directory.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class AppModel extends Model{
   public $actsAs = array ( 'Nullable' );
}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;It solved my problem, but it may not be perfect or even necessary. Any feedback on my approach or the behavior itself would be appreciated.&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2009/01/30/learning-cakephp-foreign-key-constraint-violation/</feedburner:origLink></entry>
    <entry>
        <title type="html">Tab Completion for CDPATH on Mac</title>
        <id>tag:robwilkerson.org,2009-01-14:/id/166/</id>
        <updated>2009-01-14T17:58:13-04:00</updated>
        <published>2009-01-14T17:50:11-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/8pg92xqWDSE/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;Though I’ve written several shell-related posts, I’m not a shell geek. Let’s get that out of the way right now. The shell is a tool for me and nothing more. I had used tcsh for years and years and years for no other reason than someone told me it was better than bash when I first started doing any “real” Unix work. I recently moved to bash because, frankly, I was tired of having to custom-configure every system I login to on a regular basis. Bash is the default shell for most Unix flavors and since the shell is only a tool, I saw no reason to continue spending time on customizations.&lt;/p&gt;

	&lt;p&gt;The other day when &lt;a href="http://twitter.com/patrick_mc"&gt;@patrick_mc&lt;/a&gt; dropped a link to a &lt;a href="http://www.builderau.com.au/program/linux/soa/10-shortcuts-to-master-bash/0,339028299,339279043,00.htm"&gt;bash mastery article&lt;/a&gt; in a tweet, I saw the opportunity to learn something. Though it was hardly a masterful type article, I did learn about one thing that I didn’t know about before: &lt;span class="technical"&gt;&lt;span class="caps"&gt;CDPATH&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;

	&lt;p&gt;The details of &lt;span class="technical"&gt;&lt;span class="caps"&gt;CDPATH&lt;/span&gt;&lt;/span&gt; are outside of the scope of this post, but the gist is that it works the way that the &lt;span class="technical"&gt;&lt;span class="caps"&gt;PATH&lt;/span&gt;&lt;/span&gt; works. Type a directory and if it’s in your &lt;span class="technical"&gt;&lt;span class="caps"&gt;CDPATH&lt;/span&gt;&lt;/span&gt;, the OS will find it and change to that directory by name alone – even if the directory name isn’t in your current working directory. For example, if I’m in my home directory, I can type &lt;strong&gt;www&lt;/strong&gt; and be delivered directly to &lt;span class="technical"&gt;/Users/me/Development/www&lt;/span&gt; as long as &lt;span class="technical"&gt;/Users/me/Development&lt;/span&gt; is in my &lt;span class="technical"&gt;&lt;span class="caps"&gt;CDPATH&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;

	&lt;p&gt;When I first read the article, I was at work and on my Ubuntu machine so I tried it there first by adding the following line to my &lt;span class="technical"&gt;/home/me/.bash_profile&lt;/span&gt;:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;export CDPATH=.:~:~/Development&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;After sourcing (&lt;span class="technical"&gt;$ source .profile&lt;/span&gt;) my updated profile, I was able to jump to directories exactly as advertised. Moreover, tab completion worked brilliantly so, from my home directory, I could type &lt;span class="technical"&gt;cd w[TAB]&lt;/span&gt; and it would complete to &lt;span class="technical"&gt;cd www&lt;/span&gt;. Brilliant.&lt;/p&gt;

	&lt;p&gt;It wasn’t quite so easy on the Mac, though. I updated my &lt;span class="technical"&gt;.profile&lt;/span&gt;, but couldn’t get it to work. I thought I had a syntax error in my &lt;span class="technical"&gt;.profile&lt;/span&gt;, but after hours of trial and error, I was no closer.  I pinged the #lazyweb on Twitter to ask whether it worked for others on OS X and got more than a few affirmative responses which just confused me even more. A quick chat with &lt;a href="http://twitter.com/bgreenlee"&gt;Brad Greenlee&lt;/a&gt;, though, pointed out the error of my ways. It turned out that &lt;span class="technical"&gt;&lt;span class="caps"&gt;CDPATH&lt;/span&gt;&lt;/span&gt; was working great, but I was &lt;em&gt;assuming&lt;/em&gt; (yeah, I know) that tab completion would also work. It didn’t.&lt;/p&gt;

	&lt;p&gt;For me, something like &lt;span class="technical"&gt;&lt;span class="caps"&gt;CDPATH&lt;/span&gt;&lt;/span&gt; is only useful with tab completion because otherwise, I can tab complete the full path to the file before I can type the entire directory name (for all but the shortest directory names). Besides, the &lt;span class="technical"&gt;Tab&lt;/span&gt; key is completely woven into the fabric of my muscle memory now. I can’t give it up when I’m in the shell. After a little digging, I found the answer:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;$ sudo port install bash-completion&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;Yep, that’s it (assuming you have &lt;a href="www.macports.org"&gt;MacPorts&lt;/a&gt; installed).  Well, almost. You do have to update your &lt;span class="technical"&gt;.profile&lt;/span&gt; (or &lt;span class="technical"&gt;.bash_profile&lt;/span&gt;, &lt;span class="technical"&gt;.bashrc&lt;/span&gt;, etc.) to source the installed file at &lt;span class="technical"&gt;/opt/local/etc/bash_completion&lt;/span&gt;.  Instructions for doing so are printed in the output of the installation. In case you close your window too early, though:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if [ -f /opt/local/etc/bash_completion ]; then
    . /opt/local/etc/bash_completion
fi&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Happy completing.&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2009/01/14/tab-completion-for-cdpath-on-mac/</feedburner:origLink></entry>
    <entry>
        <title type="html">SSH Host Key Checking</title>
        <id>tag:robwilkerson.org,2009-01-05:/id/164/</id>
        <updated>2009-01-05T11:25:05-04:00</updated>
        <published>2009-01-05T11:16:07-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/7eifrVLWkJc/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;One of the things that’s always annoyed me, but not to such a degree that I’ve felt compelled to expend any effort “fixing” it, is the prompt that I get every time I &lt;acronym title="Secure SHell"&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt;&lt;/acronym&gt; to a machine that I haven’t connected to before. It looks a little something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;The authenticity of host 'host.domain.tld (192.168.1.16)' can't be established.
RSA key fingerprint is 58:3d:dc:39:b3:5c:44:0b:ah:9b:7d:01:8e:f2:f8:77.
Are you sure you want to continue connecting (yes/no)?&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Because it’s not a huge deal to type “yes” to create the connection, I’ve never cared enough to really look into it. &lt;/p&gt;

	&lt;p&gt;This morning, though, I was trying to do a pull from one of my git repositories only to find that the server signature had changed and my connection was terminated. As far as I know, the only way to re-establish a connection terminated for this reason is to remove that server from my list of known hosts. To do so I usually crack open my &lt;span class="technical"&gt;~/.ssh/known_hosts&lt;/span&gt; file, find the line that begins with the host name of the server I’m trying to connect to and delete that line. The next time I try to connect, the server is added back to the file (after typing “yes” again).&lt;/p&gt;

	&lt;p&gt;Unfortunately, I was working on my Linux machine this morning and I got an unpleasant surprise when I opened my &lt;span class="technical"&gt;~/.ssh/known_hosts&lt;/span&gt; file. Ubuntu, unlike every other Unix flavor I’ve worked with/in, encrypts the contents of that file. That meant I couldn’t find the line for the particular server whose signature changed for the purpose of surgical deletion. To reset that server as a known host, I’d have to delete the entire contents of the file. I connect to a number of servers and this has become a &lt;em&gt;big&lt;/em&gt; file; I didn’t want to have to type “yes” that many times so a “fixing” the annoyance took on a greater urgency.&lt;/p&gt;

	&lt;p&gt;This is when it’s really handy to work with a &lt;a href="http://sivel.net"&gt;Linux sys admin&lt;/a&gt;. He heard me expressing my annoyance in a semi-colorful manner and told me to just shut off the authentication prompt. Hearing the ability to kill two birds with one stone, I did a quick search, then cracked open my &lt;span class="caps"&gt;SSH&lt;/span&gt; config file (&lt;span class="technical"&gt;/etc/ssh/ssh_config&lt;/span&gt;) and edited the following line:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;# StrictHostKeyChecking ask&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;I uncommented the line and changed the value to “no” and I’m no longer prompted when connecting to new machines. Now it’s safe to clear my &lt;span class="technical"&gt;known_hosts&lt;/span&gt; file without bother. I do still get a warning that a new host has been added to my file (which is nice), but no interaction is required.&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2009/01/05/ssh-host-key-checking/</feedburner:origLink></entry>
    <entry>
        <title type="html">Defensio False Positives</title>
        <id>tag:robwilkerson.org,2009-02-10:/id/163/</id>
        <updated>2009-02-10T20:53:55-04:00</updated>
        <published>2009-01-04T11:26:52-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/MfS6bVcWRw0/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;In addition to the random false negative, I’ve had a number of folks report that comments they’ve left on various posts have been marked as spam. Defensio, like most spam filters, isn’t perfect. If this happens to you, assuming that you’re human and not a spamming jackhole, please drop me a line via the contact form and I’ll make sure that your comment gets added appropriately.&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2009/01/04/defensio-false-positives/</feedburner:origLink></entry>
    <entry>
        <title type="html">CakePHP: Recursive Finds</title>
        <id>tag:robwilkerson.org,2009-01-04:/id/162/</id>
        <updated>2009-01-04T01:16:47-04:00</updated>
        <published>2009-01-03T09:57:12-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/LX9qIT_7d8M/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;(a.k.a It is &lt;em&gt;not&lt;/em&gt; a boolean)&lt;/p&gt;

	&lt;p&gt;Being so new to &lt;a href="http://cakephp.org"&gt;CakePHP&lt;/a&gt;, I’ve spent a lot of time in the &lt;a href="http://book.cakephp.org/"&gt;documentation&lt;/a&gt;. I mean &lt;em&gt;a lot&lt;/em&gt; of time. Contrary to popular belief, the documentation is extensive, quite good and covers most, if not all, of the topics I’ve needed help with.  One thing I’ve found, though, is that the documentation has three very specific deficiencies in many cases:&lt;/p&gt;

	&lt;ol&gt;
		&lt;li&gt;Often, only simple cases are covered.&lt;/li&gt;
		&lt;li&gt;There are a lot of ambiguities that I’d like to see clarified.&lt;/li&gt;
		&lt;li&gt;It sometimes feels fragmented. The answer I’m looking for often isn’t found in (or even linked from) one place.&lt;/li&gt;
	&lt;/ol&gt;

	&lt;p&gt;Today I ran into the latter two issues when I needed to pull data from an extended model association. I have an &lt;span class="technical"&gt;Attraction&lt;/span&gt; model that has a many-to-many (&lt;span class="technical"&gt;hasAndBelongsToMany&lt;/span&gt;) relationship with an &lt;span class="technical"&gt;Event&lt;/span&gt; model. Each event takes place at a location, so my &lt;span class="technical"&gt;Event&lt;/span&gt; model &lt;span class="technical"&gt;belongsTo&lt;/span&gt; my &lt;span class="technical"&gt;Location&lt;/span&gt; model.&lt;/p&gt;

	&lt;p&gt;When doing a &lt;span class="technical"&gt;find ( ‘all’ )&lt;/span&gt; on my &lt;span class="technical"&gt;Attraction&lt;/span&gt; model, each result included, in addition to the &lt;span class="technical"&gt;Attraction&lt;/span&gt; itself, an &lt;span class="technical"&gt;Event&lt;/span&gt; – the model &lt;em&gt;directly&lt;/em&gt; associated with with my attraction. I wanted to be able to display &lt;span class="technical"&gt;Location&lt;/span&gt; information as well, so I looked at the &lt;span class="technical"&gt;recursive&lt;/span&gt; parameter in an effort to have &lt;span class="technical"&gt;find()&lt;/span&gt; retrieve data from the extended association.&lt;/p&gt;

	&lt;p&gt;The &lt;a href="http://book.cakephp.org/view/73/Retrieving-Your-Data"&gt;&lt;span class="technical"&gt;find()&lt;/span&gt; documentation&lt;/a&gt; really provides very little information about the &lt;span class="technical"&gt;recursive&lt;/span&gt; parameter, but there is a syntax example:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;'recursive' =&gt; 1, //int&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;When I looked at that, I read it to be a boolean value. To me, the parameter name itself sounds boolean and the only examples I found had a value of &lt;span class="technical"&gt;1&lt;/span&gt;, a value commonly used (though not explicitly enough for my tastes) to represent a boolean “true”. When I set the parameter to &lt;span class="technical"&gt;1&lt;/span&gt;, though, I got exactly the same result with the same lack of &lt;span class="technical"&gt;Location&lt;/span&gt; information.&lt;/p&gt;

	&lt;p&gt;As you may have guessed, I read it wrong. The &lt;span class="technical"&gt;recursive&lt;/span&gt; parameter is really a &lt;span class="technical"&gt;recursionLevels&lt;/span&gt; parameter. Once I set the value to &lt;span class="technical"&gt;2&lt;/span&gt;, I got information related to the models that were directly associated with the &lt;span class="technical"&gt;Event&lt;/span&gt; model which included my &lt;span class="technical"&gt;Location&lt;/span&gt; information.&lt;/p&gt;

	&lt;p&gt;This is one of those cases where the documentation isn’t &lt;em&gt;wrong&lt;/em&gt;, but it is fragmented and it’s not always easy for new developers to find what they need easily. As I get more familiar with CakePHP, more confident that I know what I’m doing and that I’m doing things the right (read: Cake) way, I’ll do my part to help clarify the documentation where I believe it necessary, but until then I’ll make my notes here in case they can help someone else or someone else can help me.&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2009/01/03/cakephp-recursive-finds/</feedburner:origLink></entry>
    <entry>
        <title type="html">CakePHP: Watch Out for the compact() Function</title>
        <id>tag:robwilkerson.org,2008-12-28:/id/160/</id>
        <updated>2008-12-28T18:10:47-04:00</updated>
        <published>2008-12-28T18:03:14-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/Azk8aRj4IKw/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;Okay, so maybe this caveat isn’t specific to CakePHP since the function is a native &lt;span class="caps"&gt;PHP&lt;/span&gt; function, but I just spent the past hour trying to figure out why variables that I clearly set in my controller weren’t available to my view. I’ll never get that hour back, but maybe I can keep someone else from losing it. As far as I’ve been able to tell, this particular behavior isn’t documented, but I haven’t done any kind of exhaustive search.&lt;/p&gt;

	&lt;p&gt;The &lt;a href="http://us3.php.net/compact"&gt;&lt;span class="technical"&gt;compact()&lt;/span&gt;&lt;/a&gt; function exists as a shorthand function to create an array of variables. The &lt;span class="caps"&gt;PHP&lt;/span&gt; documentation does a nice job of detailing the function and providing a few simple examples, so I won’t belabor that point. Within CakePHP, it’s a handy shortcut for passing variables from a controller to a view.  In my case, I have a vendor application form with a few variances that I need to manage.  Without using &lt;span class="technical"&gt;compact()&lt;/span&gt;, a snippet from the action method of my &lt;span class="technical"&gt;VendorsController&lt;/span&gt; would look like this:&lt;/p&gt;

	&lt;p&gt;&lt;pre&gt;&lt;code&gt;public function index() {
   …
   $vendor_type      = ‘Food’;
   $application_type = ‘Commercial’;
   $states           = $this-&gt;Vendor-&gt;Address-&gt;State-&gt;find ( 
      ‘list’, 
      array ( ‘order’ =&gt; ‘State.title’ ) 
   );&lt;/p&gt;

   $this-&gt;set ( ‘vendor_type’, $vendor_type );
   $this-&gt;set ( ‘application_type’, $application_type );
   $this-&gt;set ( ‘states’, $states );
   …
}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That’s not an intolerably verbose example, but it’s easy to see how it could become so. Being the laconic kind of guy that I am, though, I decided to use the &lt;span class="technical"&gt;compact()&lt;/span&gt; function to cut down on the verbiage. Now my action code looks like this:&lt;/p&gt;

	&lt;p&gt;&lt;pre&gt;&lt;code&gt;public function index() {
   …
   $vendor_type      = ‘Food’;
   $application_type = ‘Commercial’;
   $states           = $this-&gt;Vendor-&gt;Address-&gt;State-&gt;find ( 
      ‘list’, 
      array ( ‘order’ =&gt; ‘State.title’ ) 
   );&lt;/p&gt;

   $this-&gt;set ( compact ( ‘vendor_type’, ‘application_type’, ‘states’ ) );
   …
}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That’s a little better, but there’s a caveat. &lt;/p&gt;

	&lt;p&gt;Using this example, I went to my view code and tried to access my &lt;span class="technical"&gt;$vendor_type&lt;/span&gt; variable only to get an undefined variable error. After working my way through various debugging techniques, I pulled out the big gun. In my view, I dumped the output of &lt;span class="caps"&gt;PHP&lt;/span&gt;’s &lt;span class="technical"&gt;get_defined_vars()&lt;/span&gt; function and found that my &lt;span class="technical"&gt;$vendor_type&lt;/span&gt; variable had been renamed to &lt;span class="technical"&gt;$vendorType&lt;/span&gt;. I don’t know if the change was made by CakePHP or by &lt;span class="caps"&gt;PHP&lt;/span&gt; itself, but I didn’t expect it (nor do I have any reason to believe that I &lt;em&gt;should&lt;/em&gt; have expected it) and the difference is as fatal to an application as it is obvious.&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2008/12/28/cakephp-watch-out-for-the-compact-function/</feedburner:origLink></entry>
    <entry>
        <title type="html">CakePHP: Adding Dynamic Content to Layouts</title>
        <id>tag:robwilkerson.org,2008-12-15:/id/159/</id>
        <updated>2008-12-15T22:12:17-04:00</updated>
        <published>2008-12-15T21:40:07-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/G9UezDV_5cY/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;For the past few months, I’ve had this lingering item on my &lt;span class="caps"&gt;TODO&lt;/span&gt; list to &lt;em&gt;Learn CakePHP&lt;/em&gt;. When that item was added to the list, we had decided to use it as our default framework for building new apps at work and I wanted to &lt;em&gt;at least&lt;/em&gt; be aware of its basic capabilities, techniques and toolkits. Unfortunately, I don’t get as much time as I’d like to put my head down and write code at work, so this item has been taunting me until this week when some time presented itself.&lt;/p&gt;

	&lt;p&gt;I come into this brand new to &lt;a href="http://cakephp.org"&gt;CakePHP&lt;/a&gt;, but as an experienced web and &lt;acronym title="Object Oriented Programming"&gt;&lt;span class="caps"&gt;OOP&lt;/span&gt;&lt;/acronym&gt; developer. I have certain expectations of encapsulation, elegance and maintainability that I want to bring to my CakePHP project. As I run across scenarios where I don’t think that such elegance is obvious, I’ll document the solution I used here. Maybe someone else can benefit from my experience and maybe I can benefit from that of others.&lt;/p&gt;

	&lt;h2&gt;The Project&lt;/h2&gt;

	&lt;p&gt;Since I learn most effectively by doing, I needed a project. The project I chose was a rebuild of a site I did about a year ago; I was familiar with the needs as well as the things I would have liked to do differently, had there been enough time.&lt;/p&gt;

	&lt;p&gt;For the site I’m building, I have not only a header and a footer, but also a sidebar. The site has navigation menus in each of these areas of the template that I wanted to be data driven and several menu items are shared across menu locations.  Not an uncommon need, to be sure, but I wasn’t sure how to handle it with CakePHP because layouts don’t have models – or controllers – of their own to access the data and this layout would be shared by every page in the site – I didn’t want to add the logic to retrieve and manipulate menu data in more than one place.&lt;/p&gt;

	&lt;h2&gt;The Scenario&lt;/h2&gt;

	&lt;p&gt;The scenario, then, is the need to place dynamic content within a layout. Without going into excruciating detail, a CakePHP layout is analogous to a template in a &lt;acronym title="Content Management System"&gt;&lt;span class="caps"&gt;CMS&lt;/span&gt;&lt;/acronym&gt;. It’s the part of the page that is fixed and usually shared across multiple pages of a site. On &lt;a href="http://robwilkerson.org"&gt;robwilkerson.org&lt;/a&gt;, for example, the layout would include the header, the footer and the sidebar on the right. Everything else is the page content or, in CakePHP’s &lt;acronym title="Model-View-Controller"&gt;&lt;span class="caps"&gt;MVC&lt;/span&gt;&lt;/acronym&gt;-speak, the view template.&lt;/p&gt;

	&lt;h2&gt;The Data&lt;/h2&gt;

	&lt;p&gt;The backbone of a data driven solution, of course, is the database. For my menus problem, I created three tables: &lt;span class="technical"&gt;nav_menus&lt;/span&gt;, &lt;span class="technical"&gt;nav_menu_items&lt;/span&gt; and &lt;span class="technical"&gt;nav_menu_items_nav_menus&lt;/span&gt; following all of the conventions of CakePHP so that everything would work without any more effort than necessary. The last table, of course, is a linking table to identify which items exist on which menus. The many-to-many relationship it enables is what allows a single menu item to appear on more than one menu.&lt;/p&gt;

	&lt;h2&gt;The Models &amp; Controllers&lt;/h2&gt;

	&lt;p&gt;With the database prepared, I needed to provide access from my application and this is where CakePHP and most other frameworks I’m familiar with really shine.  Using CakePHP, I just “baked” models and controllers using the command line utility:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd path/to/cake/console
$ ./cake bake model nav_menu
$ ./cake bake controller nav_menus
$ ./cake bake model nav_menu_items
$ ./cake bake controller nav_menu_items&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That’s it. A few simple command line requests and I had all the files I needed. All that was left to get this scaffolded up was to define the associations between the models I’d just created. To do so, I opened each model file (located in &lt;span class="technical"&gt;app/models/&lt;/span&gt;) and added a single line of code to each. To &lt;span class="technical"&gt;app/models/nav_menu.php&lt;/span&gt;, I added the following:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;public $hasAndBelongsToMany = array ( 'NavMenuItem' );&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;Similarly, I added the following to &lt;span class="technical"&gt;app/models/nav_menu_item.php&lt;/span&gt;:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;public $hasAndBelongsToMany = array ( 'NavMenu' );&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;That’s all I needed to do to be able to create new menus and menu items. By requesting &lt;span class="technical"&gt;http://localhost/nav_menus/add&lt;/span&gt;, I was able to use CakePHP’s scaffolded interface to create new menus. Likewise, by accessing &lt;span class="technical"&gt;http://localhost/nav_menu_items/add&lt;/span&gt;, I could create new menu items and assign them to the appropriate menus.&lt;/p&gt;

	&lt;h2&gt;Sharing the Logic&lt;/h2&gt;

	&lt;p&gt;The non-obvious question in my mind was how do I get this dynamic data displayed on a layout? A layout doesn’t have its own controller and I sure has hell don’t want to have to tell every controller how to render my navigation. Inheritance to the rescue.&lt;/p&gt;

	&lt;p&gt;CakePHP’s controllers all extend the &lt;span class="technical"&gt;AppController&lt;/span&gt; class, so I dropped my menu logic there:&lt;/p&gt;

	&lt;p&gt;&lt;pre&gt;&lt;code&gt;class AppController extends Controller {
   public $uses = array ( ‘NavMenu’ );&lt;/p&gt;

   public function beforeRender() {		
      /**
       * Populate and expose menu data
       */
      $raw_menus = $this-&gt;NavMenu-&gt;find ( ‘all’ );
      $menus = $this-&gt;NavMenu-&gt;unobfuscateMenus ( $raw_menus );
      $this-&gt;set ( ‘nav_menus’, $menus );
   }
}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;In my mind, this is perfectly reasonable since this logic really &lt;em&gt;will&lt;/em&gt; be used on every single page request; there are no &lt;span class="caps"&gt;CPU&lt;/span&gt; cycles being wasted.&lt;/p&gt;

	&lt;h3&gt;An Associative Recordset&lt;/h3&gt;

	&lt;p&gt;If anyone’s wondering about the &lt;span class="technical"&gt;unobfuscateMenus()&lt;/span&gt; method, I created a custom method in my &lt;span class="technical"&gt;NavMenus&lt;/span&gt; model that would allow me to access and key on my menus as an associative array rather than as an indexed array.  I have three menus: Primary, Secondary and (surprise!) Tertiary.  By default, CakePHP exposes these as &lt;span class="technical"&gt;$nav_menus[ 0 ][‘Primary’]&lt;/span&gt;, &lt;span class="technical"&gt;$nav_menus[ 1 ][‘Secondary’]&lt;/span&gt;, etc. I wanted to be able to key on the menu name, though, so that in my layout, I had the ability to access the precise menu I wanted when I wanted it. &lt;/p&gt;

	&lt;p&gt;The &lt;span class="technical"&gt;unobfuscateMenus()&lt;/span&gt; method reorganizes the array slightly so that I can access &lt;span class="technical"&gt;$nav_menus[‘Primary’]&lt;/span&gt; when I want to display the primary menu without looping over all menus and testing for the menu name. This should become more clear in the code that renders the menu below.&lt;/p&gt;

	&lt;p&gt;With the code added to the &lt;span class="technical"&gt;AppController&lt;/span&gt; class, all of my controllers and, by extension, all of my layouts will have access to my menu data.  Since I have several menus on my layout, I not only wanted to share the logic, but also the output.&lt;/p&gt;

	&lt;h2&gt;Sharing the Output&lt;/h2&gt;

	&lt;p&gt;Duplicating presentation code is almost as distasteful to me as duplicating business logic, so I created a navigation element that would accept my &lt;span class="technical"&gt;$nav_menus&lt;/span&gt; array and iterate over each item to create an unordered list.  The menu array whose items will be displayed is passed to the element as the &lt;span class="technical"&gt;$menu&lt;/span&gt; variable.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;ul&gt;
   &lt;?php $i_item = 0; ?&gt;
   &lt;?php foreach ( $menu['items'] as $item ): ?&gt;
   &lt;?php
      $i_item++;
      $item_class = '';
      if ( $i_item  1 ) {
         $item_class = ' class="first"';
      }
      else if ( $i_item  count ( $menu['items'] ) ) {
         $item_class = ' class="last"';
      }
   ?&gt;
   &lt;li&lt;?php echo $item_class; ?&gt;&gt;
      &lt;a href="&lt;?php echo $item['target_uri']; ?&gt;" 
         title="&lt;?php echo $item['description']; ?&gt;"
         &gt;&lt;?php echo $item['title']; ?&gt;&lt;/a&gt;
   &lt;/li&gt;
   &lt;?php endforeach; ?&gt;
&lt;/ul&gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Wiring It All Together&lt;/h2&gt;

	&lt;p&gt;My logic, data and presentation code are all in place now, so the only thing left is to apply the context – the layout.  In my layout markup, I included the following code to display my primary menu:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;?php echo $this-&gt;element (
      'navigation',
      array (
         'id'   =&gt; 'primary',
         'menu' =&gt; $nav_menus['PRIMARY']
      )
   );
?&gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And for my secondary menu:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;?php echo
      $this-&gt;element (
      'navigation',
      array (
         'id'   =&gt; 'secondary',
         'menu' =&gt; $nav_menus['SECONDARY']
      )
   );
?&gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Key Points&lt;/h2&gt;

	&lt;p&gt;Here’s what I like about this solution, in no particular order:&lt;/p&gt;

	&lt;ol&gt;
		&lt;li&gt;One database query. I have three menus and I certainly could have retrieved each menu individually. Whenever it’s feasible, though, I like to avoid querying the database. In my experience, the database is almost always the bottleneck for an application; the less I have to communicate with it, the better.  With a little application logic (the &lt;span class="technical"&gt;unobfuscateMenus()&lt;/span&gt; method), I get all the benefits of three queries at the performance cost of just one.&lt;/li&gt;
		&lt;li&gt;It will scale. If I need six navigation menus, all that’s required is a little more data. The code can handle the additional menus without any changes.&lt;/li&gt;
		&lt;li&gt;There’s no waste. I’m very wary of dropping code in a super class, but in this case it works. The &lt;span class="technical"&gt;AppController&lt;/span&gt; class is loaded on every request and the logic it includes is used on every request. Symmetry.&lt;/li&gt;
		&lt;li&gt;Encapsulation of presentation. Within the element, there’s no logic that isn’t used exclusively for presentation. Because I unobfuscated the menus array, I’m able to pass in only the menu that needs to be rendered by the element at the time it’s called.&lt;/li&gt;
	&lt;/ol&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2008/12/15/cakephp-mixing-dynamic-content-with-static/</feedburner:origLink></entry>
    <entry>
        <title type="html">Give Firefox Fangs</title>
        <id>tag:robwilkerson.org,2008-12-09:/id/158/</id>
        <updated>2008-12-09T11:50:25-04:00</updated>
        <published>2008-12-09T11:49:42-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/_mgrXCY78aY/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;&lt;img src="http://robwilkerson.org/_resources/hotlink/blog/firefox-fangs-logo.gif" align="right" title="Fangs logo" alt="Fangs logo" /&gt;&lt;/p&gt;

	&lt;p&gt;&lt;a href="http://www.standards-schmandards.com/fangs"&gt;Fangs&lt;/a&gt; is a Firefox extension that presents a web page in a manner similar to how it would be read by a screen reader. I’m not an accessibility guru, nor am I and accessibility geek. I try to hit the high points of accessibility like employing skip navigation, alt tags, meaningful link text, etc. when I build sites, but at the same time I have to confess that I’ve never dug much deeper than that. As far as I can tell, Fangs doesn’t offer much in the way of education, but what I really like is that it provides another way of visualizing the structure of my content. Moreover, it’s a practical visualization since it emulates the way a screen reader will read that content rather than some kind of basic block diagram.&lt;/p&gt;

	&lt;p&gt;Although, my impression so far is that Fangs doesn’t offer much in the way of accessibility information or evaluation, there are some hints about how to effectively use Fang on the &lt;a href="http://www.standards-schmandards.com/fangs/help/index.php?l=chrome://global/locale/intl.properties&amp;v=1.0.4"&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;&lt;/a&gt;. Even with limited use so far, I’ve seen enough to know that there’s a place in my development toolbox for this extension.&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2008/12/09/give-firefox-fangs/</feedburner:origLink></entry>
    <entry>
        <title type="html">Make Linux Just a Little Sexier</title>
        <id>tag:robwilkerson.org,2008-12-08:/id/157/</id>
        <updated>2008-12-08T19:08:13-04:00</updated>
        <published>2008-12-08T19:07:04-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/jEzhGAt6W0M/howto-install-mac-fonts-on-ubuntu.html" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;Granted, I’m a Mac user, at least at home, but I like to think I’m not a &lt;em&gt;total&lt;/em&gt; fanboy.  When I moved to Linux at work and began customizing my machine, I saw countless recipes with instructions for skinning Linux to look like a Mac (or maybe there’s just one and everyone in the free world is linking to it). I don’t get that. Linux isn’t a Mac. A penguin in a tux is still a penguin, right?  The fact is, I like my operating systems to look like what they are and, besides, I’ve never had much luck with Linux themes. There’s always &lt;em&gt;something&lt;/em&gt; that gets left out and kind of ruins the whole effect.&lt;/p&gt;

	&lt;p&gt;The honest truth is, I kind of like the Linux aesthetic.  Most of it, anyway.  I’m not, however, a fan of the default fonts and I thought that installing Mac fonts might be just the thing to dress up the penguin without overdoing it. Turns out that they are.&lt;/p&gt;

	&lt;p&gt;Try it.  Here are my settings:&lt;/p&gt;

	&lt;p&gt;&lt;a href="http://robwilkerson.org/_resources/hotlink/blog/mac-font-settings.png"&gt;&lt;img src="http://robwilkerson.org/_resources/hotlink/blog/thumb/mac-font-settings.png" title="My Ubuntu font settings" alt="My Ubuntu font settings" /&gt;&lt;/a&gt;&lt;/p&gt;        </content>
    <feedburner:origLink>http://www.ubuntu-unleashed.com/2008/05/howto-install-mac-fonts-on-ubuntu.html</feedburner:origLink></entry>
    <entry>
        <title type="html">Fix Title Bar Issues in Ubuntu 8.10 (Intrepid Ibex)</title>
        <id>tag:robwilkerson.org,2008-12-08:/id/155/</id>
        <updated>2008-12-08T12:55:31-04:00</updated>
        <published>2008-12-08T12:34:07-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/XMt_nkwXWCo/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;Towards the end of November, I upgraded (read: &lt;a href="http://robwilkerson.org/2008/11/24/intrepid-ibex-vpn-connection-fails/"&gt;completely rebuilt&lt;/a&gt;) my Linux partition from 8.04 (Hardy Heron) to 8.10 (Intrepid Ibex). I’ll have more to say about the latter in a future post, but after the upgrade I was immediately faced with two problems. One, the inability to establish a &lt;span class="caps"&gt;VPN&lt;/span&gt; connection, that was critical to my ability to use this as my primary work computer and the second, an issue with my title bars that, though extremely annoying, was really just aesthetic.&lt;/p&gt;

	&lt;p&gt;The &lt;a href="http://robwilkerson.org/2008/11/24/intrepid-ibex-vpn-connection-fails/"&gt;solution to the &lt;span class="caps"&gt;VPN&lt;/span&gt; issue&lt;/a&gt; is detailed in an earlier post and today I finally got around to fixing the title bar issue.  It took me a while because, though the solution itself is relatively simple, I had a lot of trouble finding the &lt;em&gt;entire&lt;/em&gt; solution in one place. Thus, the birth of this post.&lt;/p&gt;

	&lt;h2&gt;The Problem&lt;/h2&gt;

	&lt;p&gt;They say that a picture is worth a thousand words, but unfortunately I neglected to take a screenshot before fixing the problem. Nonetheless, I’ll try to keep my description well under a thousand words. &lt;/p&gt;

	&lt;p&gt;Frequently and inconsistently, my active title bar would go grey and the appearance would fracture. I don’t know how to describe it any better except to say that if Picasso himself had painted a title bar in shades of grey, it would have probably looked much like mine. Cubist, indeed.&lt;/p&gt;

	&lt;p&gt;The problem, in a nutshell, is with the &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; video driver. If you don’t have an &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; video driver, you probably don’t have this problem. Intrepid Ibex ships with three proprietary &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; driver versions: 96, 173 and 177. I don’t remember which was installed by default, but I encourage you to trust me when I say that not one of them worked.&lt;/p&gt;

	&lt;h2&gt;The Solution&lt;/h2&gt;

	&lt;p&gt;First, of course, you need the right driver. I read somewhere that version 180.06 worked as expected so that’s the one I downloaded. I’ll save you the suspense and tell you that this version &lt;em&gt;did&lt;/em&gt; work for me. It can be downloaded from the &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; site, but be sure to select the &lt;a href="http://www.nvidia.com/object/linux_display_ia32_180.06.html"&gt;32 bit&lt;/a&gt; or &lt;a href="http://www.nvidia.com/object/linux_display_amd64_180.06.html"&gt;64 bit&lt;/a&gt; version, as appropriate.  I downloaded it to my desktop. Once you have the appropriate driver:&lt;/p&gt;

	&lt;ol&gt;
		&lt;li&gt;Close everything except for a terminal window. I do mean &lt;em&gt;everything&lt;/em&gt; because you’re about to stop the X Windows process.&lt;/li&gt;
		&lt;li&gt;In the terminal window, type &lt;span class="technical"&gt;sudo killall gdm&lt;/span&gt; and hit &lt;span class="technical"&gt;Enter&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;Once the screen goes black, hit &lt;span class="technical"&gt;Ctrl+Alt+F1&lt;/span&gt; to switch to a new terminal.&lt;/li&gt;
		&lt;li&gt;You should see a terminal prompt so switch to the directory where you downloaded the driver file. My command was &lt;span class="technical"&gt;cd ~/Desktop&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;It may be sufficient to just use &lt;strong&gt;sudo&lt;/strong&gt; here, but just to be sure, I dropped into a root shell by typing &lt;span class="technical"&gt;sudo -s&lt;/span&gt; and hitting &lt;span class="technical"&gt;Enter&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;Execute the driver file. If you didn’t rename the file, the terminal command should look something like this: &lt;span class="technical"&gt;./NVIDIA-Linux-x86_64-180.06-pkg2.run&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;Follow the prompts through the installation process. You may see some scary messages about the driver having “no precompiled kernel interface”, but allow the install to do what it needs to do (it’ll ask to check for one and, failing that, it will ask to compile its own). I let it go about its business and had no problems at all.&lt;/li&gt;
		&lt;li&gt;Once the install is complete, you can probably just type &lt;span class="technical"&gt;startx&lt;/span&gt; and hit &lt;span class="technical"&gt;Enter&lt;/span&gt;, but again, I wanted to be really, really sure, so I did a full reboot.  If you used &lt;span class="technical"&gt;sudo -s&lt;/span&gt; as I did and choose to simply restart X, I’d recommend logging out of the root shell first or else you’ll start X as root.&lt;/li&gt;
	&lt;/ol&gt;

	&lt;p&gt;That’s all there is to it.  So far, everything looks good, but I have noticed one thing that looks odd to me:&lt;/p&gt;

	&lt;p style="text-align:center;"&gt;&lt;img src="http://robwilkerson.org/_resources/hotlink/blog/ibex-hardware-drivers.png" title="Ubuntu Hardware Drivers Window" alt="Ubuntu Hardware Drivers Window" /&gt;&lt;/p&gt;

	&lt;p&gt;Seems Ubuntu thinks I’m still using version 177. As I said in my last post, Ubuntu is pretty solid, but not everything “just works”.&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2008/12/08/fix-title-bar-issues-in-ubuntu-810-intrepid-ibex/</feedburner:origLink></entry>
    <entry>
        <title type="html">Dropbox is Smart</title>
        <id>tag:robwilkerson.org,2008-11-29:/id/154/</id>
        <updated>2008-11-29T10:27:12-04:00</updated>
        <published>2008-11-29T10:21:22-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/YQnoo7e5ezk/dumbing_down_the_cloud.html" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;Rands in Repose on just what makes &lt;a href="http://getdropbox.com"&gt;Dropbox&lt;/a&gt; so special:&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;The magic of Dropbox is that it doesn’t ask you to think about what you do. You care about one thing: do I have access to the most recent version of my files? And with Dropbox, yes, you do. Wherever you are, so are your files.&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;I’ve been &lt;a href="http://robwilkerson.org/tag/dropbox"&gt;espousing Dropbox&lt;/a&gt; for a while now, but this is a well-articulated macro view.&lt;/p&gt;        </content>
    <feedburner:origLink>http://www.randsinrepose.com/archives/2008/11/25/dumbing_down_the_cloud.html</feedburner:origLink></entry>
    <entry>
        <title type="html">Intrepid Ibex VPN Connection Fails</title>
        <id>tag:robwilkerson.org,2008-12-08:/id/153/</id>
        <updated>2008-12-08T12:56:42-04:00</updated>
        <published>2008-11-24T13:08:35-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/GWROVyr43fM/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;At the end of last week, I performed an upgrade from Ubuntu 8.04 (Hardy Heron) to 8.10 (Intrepid Ibex). Although it’s not really part of this story, I should specify that I &lt;em&gt;tried&lt;/em&gt; to perform an upgrade. The upgrade was so catastrophically botched somehow, that it ended up being a complete repartitioning of my work laptop. Nonetheless, over the weekend I got back to a reasonable level of stability and productivity except that I was completely unable to connect to my office &lt;span class="caps"&gt;VPN&lt;/span&gt;.&lt;/p&gt;

	&lt;p&gt;Evidently this is a pretty well-reported bug affecting a number of folks.  My attempts to connect to &lt;span class="caps"&gt;VPN&lt;/span&gt; “out of the box” were greeted with a complaint that “no valid &lt;span class="caps"&gt;VPN&lt;/span&gt; secrets were found.” A number of folks reported success if they simply removed their password from the configuration dialog, but that didn’t work for me. After doing so, I got a spectacularly unhelpful message that my “Connection to [my network] failed.” Super. Thanks for playing.&lt;/p&gt;

	&lt;p&gt;I spent hours searching and trying various “solutions” before finally stumbling on a clearly articulated set of instructions that worked.  They did, however, require updated network-manager packages. In case I ever have to do this again, I don’t want to spend those same hours, so I’m going to try to document the steps I took so I can reflect on them later. Maybe they’ll help someone else too.  &lt;/p&gt;

	&lt;p&gt;To get those add the following source to &lt;span class="technical"&gt;/etc/apt/sources.list&lt;/span&gt;:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;deb http://ppa.launchpad.net/network-manager/ubuntu intrepid main&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;Once done, update:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;$ sudo apt-get update&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;Once updated, system updates should be reported and they should include &lt;strong&gt;network-manager&lt;/strong&gt; and &lt;strong&gt;network-manager-pptp&lt;/strong&gt;. Those need to be installed.  Once everything is installed, &lt;a href="http://www.ubuntu-forums.com/showpost.php?s=664a7f0807e0f754b37e74c83b6e85f2&amp;p=6187094&amp;postcount=10"&gt;these instructions&lt;/a&gt; should finish the job and provide a working &lt;span class="caps"&gt;VPN&lt;/span&gt; connection.&lt;/p&gt;

	&lt;p&gt;Ubuntu is pretty solid, but not everything “just works”. Quite.&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2008/11/24/intrepid-ibex-vpn-connection-fails/</feedburner:origLink></entry>
    <entry>
        <title type="html">Remove Conflicted Files from Dropbox</title>
        <id>tag:robwilkerson.org,2008-11-29:/id/152/</id>
        <updated>2008-11-29T10:28:21-04:00</updated>
        <published>2008-11-21T07:19:32-04:00</published>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/robwilkerson/~3/MYokbPuTlA4/" />
        <author>
            <name>Rob Wilkerson</name>
            <uri>http://robwilkerson.org</uri>
        </author>
        <content type="html">
            	&lt;p&gt;Because I use &lt;a href="http://getdropbox.com"&gt;Dropbox&lt;/a&gt; to &lt;a href="http://robwilkerson.org/2008/11/12/redux-synchronizing-firefox-through-dropbox/"&gt;share selected runtime data&lt;/a&gt; (read: Firefox profile information) across machines and because I occasionally forget to exit the runtime environment (read: Firefox) when I move between those machines, Dropbox creates conflicted files from time to time. The conflicted files are saved separately and are named something like this:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;places (my.machine.name's conflicted copy 2008-11-13).sqlite&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;The file above is my Firefox bookmarks database. I have no idea how it came to be in a conflicted state, but the ugly truth is that I don’t care. I assume that Dropbox saves these files as a safety measure against losing their customers’ data and so that the customer can perform a diff on those files if they choose. I don’t choose. I keep convenience files in my Dropbox, not critical files, so the files themselves are not worth the effort it would take to find and evaluate the delta between the “good” file and the conflicted file.&lt;/p&gt;

	&lt;p&gt;To that end, I’ve taken to simply removing them and because I don’t want to browse the directory structure or do this in any other manual way, I let my operating systems do the work for me.  This is easy in Unix and, since two of my machines (my two primary machines) are Unix-based (OS X and Linux), it’s easy for me:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd ~/Dropbox
$ find . -type f -name "* conflicted *" -exec rm -f {} \;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Poof. Now they’re deleted and Dropbox will delete them from my Windows boxes for me. I’m sure that there’s a way to do something similar on Windows, but my &lt;span class="caps"&gt;DOS&lt;/span&gt; skills atrophied many moons ago.&lt;/p&gt;        </content>
    <feedburner:origLink>http://robwilkerson.org/2008/11/21/remove-conflicted-files-from-dropbox/</feedburner:origLink></entry>
</feed>
