<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
   <title>Z1R0</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/" />
   <link rel="self" type="application/atom+xml" href="http://www.z1r0.com/atom.xml" />
   <id>tag:www.z1r0.com,2010://1</id>
   <updated>2009-12-10T02:41:57Z</updated>
   <subtitle>All your base are belong to us!</subtitle>
   <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.23-en</generator>


<entry>
   <title>Snow Leopard Mysteries</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2009/12/snow_leopard_mysteries_solved.html" />
   <id>tag:www.z1r0.com,2009://1.140</id>
   
   <published>2009-12-10T02:11:34Z</published>
   <updated>2009-12-10T02:41:57Z</updated>
   
   <summary> The upgrade to Snow Leopard left certain parts of my system non-functional. Not good considering that a number of these components are crucial to my development process. Here are the hacks/work-arounds I discovered restoring these services: Subversion Subversion running...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Eunichs" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="30" label="Fink" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="24" label="PostgreSQL" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="73" label="subversion" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<p>
The upgrade to Snow Leopard left certain parts of my system non-functional. Not good considering that a number of these components are crucial to my development process. Here are the hacks/work-arounds I discovered restoring these services:
</p>

<h2>Subversion</h2>

<p>
Subversion running locally on my MacBook Pro requires that the Remote Login privilege be enabled to support <code><b>svn+ssh</b></code> secure tunneling mode. For some strange reason, the upgrade to OS X 10.6 disabled this privilege breaking my ability to connect to my subversion server. Luckily, my installation notes reminded me of this requirement and after a visit to <b>System Preferences -> Sharing</b>, I was able to restore access.
</p>

<h2>PostgreSQL</h2>

<p>
As I documented with my previous post, the custom PostgreSQL user I created to run the database was deleted by the upgrade. This oversight did not extend to the database installation itself, but recreating the user did not automatically restore database functionality. After a bit of digging around, it seems that my previous PostgreSQL user was assigned a different user id. A peek at the ownership privileges on the database files and directories revealed ownership permissions which did not correspond to a valid system user. A quick <code><b>chmod -R</b></code> fixed the permission problem and allowed PostgreSQL to be started correctly.
</p>

<h2>Fink Commander</h2>

<p>
I've been using Fink Commander to manage packages I've installed on my system over the last two versions of OS X and encountered no obvious upgrade problems when migrating to newer versions of OS X. This changed with Snow Leopard. After upgrading to 10.6, I noticed that despite having updated Fink via the command line, Fink Commander refused to display any package information. Despite an exhaustive search when I first upgraded to Snow Leopard, I was thwarted; I had no clue how to fix this issue. Jump forward a few months and it seems that I was not alone: a solution was finally posted. Due to the number of different <code><b>perl</b></code> binaries packaged with OS X, an explicit path to the older perl binaries was required. Under Fink Commander 0.5.5, this path can be set by navigating to <b>Preferences -> Paths -> Paths to Perl</b>. For OS X 10.6, this value should be <code><b>/usr/bin/perl5.8.9</b></code>. The original post can be found <b><a href="http://finkcommander.sourceforge.net/news/">here</a></b>.
</p>

<p>Mysteries solved.</p>]]>
      
   </content>
</entry>

<entry>
   <title>Snow Leopard Gotchas</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2009/11/snow_leopard_gotchas.html" />
   <id>tag:www.z1r0.com,2009://1.139</id>
   
   <published>2009-11-18T03:18:34Z</published>
   <updated>2009-11-18T04:17:54Z</updated>
   
   <summary>Missing User After upgrading to Snow Leopard (OS X 10.6), I noticed that the PostgreSQL user I created for development using dscl had suddenly disappeared. Apparently any users that are not created through System Preferences -&gt; User Accounts are excluded...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Culture Jam" scheme="http://www.sixapart.com/ns/types#category" />
   
      <category term="Eunichs" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="49" label="Apple" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="26" label="OS X" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<h3>Missing User</h3>

<p>
After upgrading to Snow Leopard (OS X 10.6), I noticed that the PostgreSQL user I created for development using <code><b>dscl</b></code> had suddenly disappeared. Apparently any users that are not created through System Preferences -> User Accounts are excluded during the upgrade process. Strangely, the group associated with this PostgreSQL admin user was still present after the upgrade. It was trivial to restore functionality, but a bit irritating. At least I wasn't stung by the Guest user fiasco that has been finally fixed in 10.6.2. 
</p>
<p>
Now that's out of the way, why is my subversion launchd entry being ignored? Hrmmm ...
</p>

<h3>IR/EyeTV Oddities</h3>

<p>
Another thing I noticed was the complete miscommunication between the IR Remote that came standard with older Macs and EyeTV. IR controls were either mismapped (resulting in strange interactions with EyeTV) or completely non-functional. Thankfully, this was resolved easily with the installation of <a href="http://www.iospirit.com/labs/candelair/">Candalair</a> - an alternative driver for internal Apple IR Receivers. By enabling <b>Leopard Compatibility Mode</b>, things were back to normal. This is obviously a known problem given the very existence of a compatibility mode, but why won't Apple actually fix the problem? 
</p>

<h3>Printing?</h3>

<p>One of the primary reasons for me considering OS X a few years ago was the tight integration of device drivers (for things such as printers) with the OS. I was tired of trying to configure PS emulation for standard photo printers in Linux. Printer configuration was by far the biggest PITA under free *nix varieties. Being able to install a printer painlessly was, for me, a true measure of usability.</p>

<p>Boy, have times changed. Where as my initial experience with 10.4 was the pleasant surprise of "wow that worked the first time", Snow Leopard has changed this process into an all too familiar experience of disappointment. Broken driver support for a slew of existing printers formerly supported by Leopard (10.5) was painful, to say the least. The process of upgrading the drivers with Apple's driver fix failed to notify users that existing print queues would <b>NOT</b> function until they had been recreated was completely obtuse in a way reminiscent of Windows. Oh well, so much for the usability advantage.</p>

<p>To see just how badly this process has devolved, try setting up a Canon Pixma 420 for wireless network printing. A friend of my got one of these with his new iMac, and nothing short of a herculean effort got this printer to work with OS X. Can you say "obscure"?</p>

<h3>Quicktime X Black Screen</h3>

<p>A new and improved Quicktime was supposed to be a boon to Snow Leopard. Unfortunately, right out of the gate, Quicktime X support in Front Row was broken for almost all files. Attempting to play any media files in Front Row resulted in a black screen with no audio or video. 10.6.1 at least restored the ability to play .avi files, but I had to wait until the recent 10.6.2 update to finally have support restored for .mkv's. What happened to releasing a functional product? Given legacy Quicktime support is available in Snow Leopard, wouldn't it have been prudent to wait until this version of Quicktime was ready for prime time before releasing it for public use? At the very least, it shouldn't have broken existing functionality. Where are the QA regression tests?</p>

<h3>At What Cost?</h3>

<p>
I understand the primary motivation behind any public company is profit and Apple is no exception. But what is the cost of relentless push for greater market share if they start to diverge from their core philosophy of "just works"? From a consumer standpoint, there are increasingly compelling reasons to question Apple's current strategies, specially if it comes at the cost of keeping existing customers satisfied. I purchased Apple products because I did not want to contribute to the cycle of "disposable" electronics. Little did I know that by design, this is exactly what I've ended up with.</p>

<p>
<b>Hackintoshes are looking better every day ...</b>
</p>]]>
      
   </content>
</entry>

<entry>
   <title>Bad Apple</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2009/11/bad_apple.html" />
   <id>tag:www.z1r0.com,2009://1.138</id>
   
   <published>2009-11-18T01:42:32Z</published>
   <updated>2009-11-18T03:09:31Z</updated>
   
   <summary> OS X 10.6 has been out for quite a while now and in true form, I was quick to upgrade my systems to the latest version in the hopes that it would finally support the full 4GB of memory...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Culture Jam" scheme="http://www.sixapart.com/ns/types#category" />
   
      <category term="NaN" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="49" label="Apple" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="18" label="hardware" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<p>
OS X 10.6 has been out for quite a while now and in true form, I was quick to upgrade my systems to the latest version in the hopes that it would finally support the full 4GB of memory on my Merom Core2Duo based MacBook Pro. Alas, unless Apple feels particularly beneficent and releases an EFI update which circumvents this limitation, I'm stuck with a 32-bit EFI which also does not address my memory issue. I was aware of this when I purchased the machine almost 3 years ago, but unlike PCs which support firmware updates to work around issues like this, it seems that Apple's strategy of planned obsolescence will have finally caught me in it's clutches. To bad; this issue seems completely contrary to Apple's environmental initiatives if it essentially cripples older machines and relegates them to the scrap heap simply because it refuses to support older architectures. Instead of simply making greener computers, shouldn't they also consider the impact of existing systems they've sold and at the very least keep them out of the landfill for as long as humanly possible? This too can be considered environmental.
</p>

<p>
Another case in point; the iMac I bought around the same time as my Macbook Pro began to exhibit extreme instability due to the faulty cooling design of the GPU in the enclosure. I only found out about this when I attempted to replace the GPU itself. While I can appreciate the design chops that it takes to design increasingly thinner computers, what about actual engineering chops to ensure that the thermal envelope of the enclosure does not lead to premature component death? At the heart of the problem was a single measly cooling fan responsible for the passively relocated heat generated from the CPU and GPU. Active cooling should have been applied separately to the CPU and GPU to ensure adequate cooling. At the very least, the GPU heat sink should have been placed before the CPU heat sink in terms of fan proximity; after all, the CPU is not always busy, but the system cannot function without a working video card. At first, I thought that this problem could have been attributed to faulty capacitors in the NVidia 7300 GT GPU; an issue that has already been addressed in the Mac Pro versions of these cards. But a quick look in the Apple forums revealed that this is a problem endemic in <b>ALL</b> Merom based iMacs (the 20"/24" white plastic varieties manufactured around 2006/2007). 
</p>

<p>
After spending 4 hours disassembling the iMac, I came to the realization : these machines are <b>DESIGNED FOR OBSOLESCENCE</b>. From the obscure torx screws, to the insanely difficult access to components, I got the message loud and clear. <b>These machines do not have field replaceable components</b>. Without this fundamental capability to recycle existing functioning components, what I was left with was a two and a half year old computer that I'd paid a huge premium for that was designed to be rendered unusable by simple hardware failure that is easily remedied in your run-of-the-mill PC.
</p>

<p>
Luckily, my local Mac dealer was willing to get me a replacement GPU and with a little elbow grease, I was able revived my machine. Consider what would have happened if someone else without a technical background was affected. The cost of the replacement card was +$200. Once labour and taxes have been factored in, it would have cost $600 to fix the iMac with a video card that is laughable by today's performance standards. Whether you are discouraged by Apple through the inability to repair your machine with FRUs or the exorbitant cost of an out of warranty repair which makes buying a new machine a "feasible" alternative, the result is the same : electronic waste with a huge environmental impact. My only recommendation going forward for all Apple purchasers is to buy the extended warranty. It is cheaper than a single out of warranty repair, but still seems like an unnecessary cost considering the price premium we initially pay which should equate to "a more reliable" machine.
</p>

<p>
With any luck, the iMac issue will be addressed in a class action suit or a public acknowledgment and an out of warranty replacement/reimbursement. At the time this article was written, Apple still has not acknowledged any culpability with regards to this issue. If you too are facing this issue, add your voice here at <a href="http://www.petitionspot.com/petitions/imacrecall">PetitionSpot</a>.   
</p>

<p>
<b>Shame on you Apple; the greenwashing of environmental issues is a blight on your record. If this is the cost of your current popularity, I smell a worm.</b>
</p>]]>
      
   </content>
</entry>

<entry>
   <title>The New Music</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2009/11/the_new_music.html" />
   <id>tag:www.z1r0.com,2009://1.137</id>
   
   <published>2009-11-07T03:04:12Z</published>
   <updated>2009-11-07T03:50:17Z</updated>
   
   <summary>Listening to music for me has always been about exploration and discovering historical resonance in &quot;new music&quot;. It&apos;s akin to Bach&apos;s Goldberg Variations; each variation contributes its own identity in an entirely unique way. I find that I gravitate to...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="F*?KUDJ" scheme="http://www.sixapart.com/ns/types#category" />
   
      <category term="Podcasts" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="77" label="music" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<p>Listening to music for me has always been about exploration and discovering historical resonance in "new music". It's akin to Bach's Goldberg Variations; each variation contributes its own identity in an entirely unique way. I find that I gravitate to music with this quality; music that unabashedly is influence by the music of my youth.</p>

<p>Unfortunately, traditional means of discovery have been increasingly tainted by commercialism. Thankfully, the Net is a big place with lots of great alternatives. One podcast that I'd like to recommend is NPR's <b>All Songs Considered</b> with Bob Boilen. I can't say I agree with all of his choices, but a few have been bang on. As a tribute to this new find, I'm finally updating my current listening list:</p>

<ul>
<li><b>Asobe Seksu</b> - Transparence</li>
<li><b>Alistar Blaik Bundale</b> - The Day</li>
<li><b>The Gaslight Anthem</b> - The '59 Sound</li>
<li><b>Mesmer</b> - Teenage Dreams</li>
<li><b>White Lies</b> - Taxidermy</li>
<li><b>Gooseflesh</b> - Still Wild</li>
<li><b>Bad Lieutenant</b> - Sink or Swim</li>
<li><b>5 Cent Theatre</b> - Shifting Sands</li>
<li><b>Mumm-Ra</b> - She's Got You High</li>
<li><b>Chambers</b> - Sea Mistress</li>
<li><b>Kurt Vile</b> - Overnite Religion</li>
<li><b>The Coast</b> - Nueva York</li>
<li><b>Kanute</b> - Not Sleeping</li>
<li><b>The Love X Nowhere</b> - Northern Time</li>
<li><b>Phantogram</b> - Mouthful of Diamonds</li>
<li><b>Beat Radio</b> - Memoir of Lightening</li>
<li><b>Land of Talk</b> - May You Never</li>
<li><b>The Exploding Boy</b> - London</li>
<li><b>New Found Land</b> - Leave It Behind</li>
<li><b>Goyte</b> - learnalilgivinanlovin</li>
<li><b>Brite Lite Brite</b> - I Just Want U 2 Myself</li>
<li><b>Miracle Fortress</b> - Hold Your Secrets to Your Heart</li>
<li><b>The Pains of Being Pure at Heart</b> - Higher than the Stars</li>
<li><b>Bye Bye Bicycle</b> - Haby Baby</li>
<li><b>Evan Voytas</b> - Getting Higher</li>
<li><b>Ou Est Le Swimming Pool</b> - Dance the Way I Feel</li>
<li><b>Red Wire Black Wire</b> - Compass</li>
<li><b>Downtown Union</b> - Bright Idea</li>
<li><b>Wild Beasts</b> - Brave Bulging Buoyant Clairvoyants</li>
<li><b>The XX</b> - Blood Red Moon</li>
<li><b>The Ties and the Lies</b> - August is for City Lovers</li>
<li><b>Choir of Young Believers</b> - Action Reaction</li>
<li><b>Gossip</b> - Music for Men</li>
<li><b>The Swell Season</b> - Strict Joy</li>
<li><b>Oliver Schroer</b> - Camino</li>
</ul>

<p>Added to my regular rotation of Muse and Kings of Leon, these tracks ensure that I don't suffer from listening fatigue.</p>
]]>
      
   </content>
</entry>

<entry>
   <title>Testing is Insurance Against Technical Debt</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2009/03/testing_is_insurance_against_t.html" />
   <id>tag:www.z1r0.com,2009://1.134</id>
   
   <published>2009-03-18T00:10:08Z</published>
   <updated>2009-06-15T06:35:48Z</updated>
   
   <summary> Technical Debt Evaluate Your Technical Debt with Sonar I&apos;ve been ghosting YCombinator&apos;s Hacker News and one of the most interesting articles I recently read was by Martin Fowler on the idea of Technical Debt. Coined by Ward Cunningham, the...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Eunichs" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="70" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<ul>
<li><b><a href="http://www.martinfowler.com/bliki/TechnicalDebt.html">Technical Debt</a></b></li>
<li><b><a href="http://sonar.codehaus.org/evaluate-your-technical-debt-with-sonar/">Evaluate Your Technical Debt with Sonar</a></b></li>
</ul>

<p>
I've been ghosting YCombinator's Hacker News and one of the most interesting articles I recently read was by Martin Fowler on the idea of Technical Debt. Coined by Ward Cunningham, the idea is simple - taking a quick and dirty approach to a solution burdens a project with technical debt. This debt is the future effort required to refactor existing code into something more elegant, and ultimately more useful. While the concept explains why people may choose trade-offs in the name of expediency, what struck me most about the metaphor is how the role of testing in the development process could offset this technical debt as a form of "insurance". Tests preserve the original requirements without necessarily committing a developer to a specific implementation. So long as the implementation preserves the requirements, this technical debt can be managed. 
</p>

<p>
One of the most direct measurements of software productivity is the ability to deliver on schedule. By accumulating technical debt, part of your development time is spent either servicing the costs of that debt (by having to code around the original hacks) or paying down the principle (by refactoring). This is the true cost of technical debt. When this debt begins to dwarf the principle value of an application, it is all to easy to default on this debt by slipping deadlines. While tests do nothing to reduce this debt, they prevent it from accumulating additional interest. Without tests, the situation quickly becomes untenable. Instead of Insurance, what you have is a Credit Default Swap. At this point, productivity is a synthetic derivative which has no bearing in reality. All productivity is lost in Complexity. 
</p>

<p>
Put another way, <b>is it possible to pay down technical debt without tests?</b> I'm inclined to think not.
</p>

<p>
Since we're using economic metaphors, I'll use the prophetic words from the Oracle of Omaha which illuminate the cost associated with testing:
</p>

<blockquote>Price is what you pay, value is what you get.</blockquote>

<p>
The price incurred for having to implement and maintain tests far outweighs the value they provide for your application. The only certainty in development is that requirements will change as a program evolves. Tests are insurance against these "known unknowns". 
</p>

<p>As with all my articles, comments (not spam) are welcome.</p>
]]>
      
   </content>
</entry>

<entry>
   <title>Battlestar Galatica - Season 1</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2009/03/battlestar_galatica_-_season_1.html" />
   <id>tag:www.z1r0.com,2009://1.133</id>
   
   <published>2009-03-17T03:39:47Z</published>
   <updated>2009-06-06T21:15:57Z</updated>
   
   <summary>Spoiler Alert (about a year too late)!!! So I&apos;m 8 episodes into season one of BSG when the first glaring discontinuity raises it ugly head. Faced with the dilemma of finding a method for being able to detect Cylon infiltrators,...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Culture Jam" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="76" label="BSG" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<h4>Spoiler Alert (about a year too late)!!!</h4>

<p>
So I'm 8 episodes into season one of BSG when the first glaring discontinuity raises it ugly head.  Faced with the dilemma of finding a method for being able to detect Cylon infiltrators, the BSG crew serendipitously find a live copy of one of the two known Cylons/Human chimera in existence. Instead of using the Cylon to verify their screening procedure, they eject him out of an airlock. WTF!!! Using Boomer as the first beta candidate could easily have been attributed to a false positive, but comparing  the outcome of her test against a live Cylon baseline would have given them the ability to identify both another Cylon in their midst and repudiate the unsubstantiated claim that Adama was a Cylon. What were the writers thinking?</p> 

<p>
In general, I like the whole re-imagining of the BSG universe with the Manchurian Candidate take on the Cylon infiltrators and the moral quandaries faced by the survivors, but this type of oversight does not bode well for the rest of the series. Hopefully it won't be quite as bad as the season finale I had the unfortunate privilege of watching out of context. When Boomer returns to the Viper without a helmet, the jig's up. Doh! 
</p>
]]>
      
   </content>
</entry>

<entry>
   <title>Fink, ImageMagick, and RMagic Installation for Rails</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2009/02/fink_imagemagick_and_rmagic_in.html" />
   <id>tag:www.z1r0.com,2009://1.132</id>
   
   <published>2009-02-27T02:12:25Z</published>
   <updated>2009-02-27T03:25:34Z</updated>
   
   <summary> RMagic Installing RMagick on OS X using MacPorts It took me a while to figure out how to get Fink to install ImageMagick and the RMagic gem for use with attachment_fu and I thought I would share my method....</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Eunichs" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="70" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="45" label="rails" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<ul>
<li><a href="http://rmagick.rubyforge.org/">RMagic</a></li>
<li><a href="http://rmagick.rubyforge.org/install-osx.html">Installing RMagick on OS X using MacPorts</a></li>
</ul>

<p>It took me a while to figure out how to get Fink to install ImageMagick and the RMagic gem for use with <code><b>attachment_fu</b></code> and I thought I would share my method. From the <code><b>#rubyonrails</b></code> channel on freenode, it seems that I am a Luddite; most users prefer MacPorts. As I've written before, I think there is value in understanding the ports system you are using in OS X and that there be a clear separation between system binaries and those you add yourself. Polluting the <code><b>/usr</b></code> directory with unsupported 3rd party code can only lead to heartache. It also helps to acknowledge the underlying software dependencies in case your production environment varies from development (which is my case). That being said, I've provided the link for those who just <b>have</b> to use MacPorts.</p>

<h4>ImageMagick & Fink</h4>

<p>Before the <code><b>rmagic</b></code> gem can be used, ImageMagick needs to be installed on the machine. Fink is great at being able to build from source and resolving dependencies, but in this case, it took a bit of coercion to get ImageMagick installed. At various points during dependency resolution (for <b>ghostscript</b> and <b>dbus-dev</b>), I was required to abandon FinkCommander and issue the following commands from a Terminal:</p>

<pre>
# fink scanpackages
# sudo apt-get
# sudo apt-get install ghostscript=8.61-5
</pre>

<pre>
# fink scanpackages
# sudo apt-get
# sudo apt-get install dbus-dev=1.2.6-1
</pre>

<p>I'm assuming that order is important in the dependency resolution process, so I included both sets of commands which needed to be run separately at different points in the installation process.</p>

<p>This eventually installed ImageMagick, but unfortunately, the default configuration included the dreaded <code><b>--enable-hdri</b></code> option. Fixing this required digging into Fink source code management internals. By default, Fink keeps ports metadata information in <code><b>.info</b></code> files which are arranged based on stable/unstable trees as well as by function. For ImageMagick, the relevant files were located in the <code><b>/sw/fink/10.5/unstable/main/finkinfo/graphics</b></code> directory. A <code><b>grep</b></code> against the ImageMagick files revealed that <code><b>imagemagick-nox.info</b></code> and <code><b>imagemagic.info</b></code> both contain the option. Simply removing it from these files and rebuilding the ImageMagic port resulted in an <code><b>rmagic</b></code> compatible installation.</p>

<pre>
# fink rebuild imagemagick
</pre> 

<p>There are a number of supplementary packages that are required to build <code><b>rmagic</b></code>; I've included a list of the required ports:
</p>

<pre>
# imagemagick
# imagemagick1-dev
# imagemagick1-shlibs
# imagemagick1-svg
</pre>

<p>In particular, be sure to have the <code><b>imagemagick1-dev</b></code> port installed, otherwise <code><b>Magick-config</b></code> will not be installed which is required for gem installation.</p>

<h4>scripts/plugin fail</h4>

<p>I usually try to follow the path of least resistance - In this case, it was to use the built-in plugin managment utility in Rails. Unfortunately, no matter how I spelled <code><b>rmagic</b></code>, the plugin could not be found in the sources packaged with 2.2.2. I even tried to find the plugin with <code><b>rapt</b></code>. C'est la vie.</p>

<h4>RMagic Installation from Source</h4>

<p>Although the preferred method of installing Rails components is by using <code><b>gem</b></code>, OSX's fonts break the <code><b>rmagic</b></code> tests that run when documentation examples are being generated. This leaves the method of last resort - installing from source. The trick is to change the <code><b>allow-example-errors=no</b></code> parameter to <b>yes</b> in the <code><b>.config</b></code> located in the source directory. Once this is done, run the following commands:</p> 

<pre>
# sudo ruby ./setup.rb
# sudo ruby ./setup.rb install
</pre>

<p>Presto! At this point RMagic should be installed on your system. You can verify by running the following commands (as per the MacPorts installation doc):</p>

<pre>
# irb -rubygems -r RMagick
>> puts Magick::Long_version
This is RMagick 2.9.1 ($Date: 2009/01/12 23:08:35 $) Copyright (C) 2008 by Timothy P. Hunter
Built with ImageMagick 6.4.1 02/25/09 Q16 http://www.imagemagick.org
Built for ruby 1.8.6
Web page: http://rmagick.rubyforge.org
Email: rmagick@rubyforge.org
</pre>

<p>All in all, the process is not unlike a contortionist attempting to pick their nose with their pinky toe .... doable, but certainly uncomfortable. Comments welcome.</p>]]>
      
   </content>
</entry>

<entry>
   <title>RailRoad III</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2009/02/railroad_iii.html" />
   <id>tag:www.z1r0.com,2009://1.129</id>
   
   <published>2009-02-13T04:16:34Z</published>
   <updated>2009-02-13T04:48:54Z</updated>
   
   <summary>Testing You can&apos;t really follow the the Test Driven Development methodology without writing tests as you develop. While the ROR documentation is fairly complete to get started on building an application, the organization of the documentation (as well as most...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Eunichs" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="70" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="45" label="rails" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<h3>Testing</h3>

<p>You can't really follow the the Test Driven Development methodology without writing tests <b>as</b> you develop. While the ROR documentation is fairly complete to get started on building an application, the organization of the documentation (as well as most reference material) seems to put testing at a lower priority in the context of the learning  the Rails platform. It would be nice if the documentation illustrated TDD within the examples as well.</p>

<h4>Fixtures</h4>

<p>Rails provides a facility for quickly creating reproducible testing data through YAML fixture files. The key point of using a fixture as of 2.2.2 is that it is essentially a fully fledged ActiveRecord. When you run a test against a feature, one of the first things that happens is that Rails populates the database table with the fixture information. It is important that your fixture YAML file is syntactically correct - if the data specified in the file references an undefined column or violates a database constraint, Rails will fail to run the test and generate a whack tonne of arcane error messages. Don't do this unless you like to read stack traces.</p>

<p><b>Strange Boolean Behavior.</b> If <code><b>validates_presence_of</b></code>  is placed on a boolean attribute, it can only be assigned <code><b>true</b></code> values within the fixture. Attempting to assign <code><b>false</b></code> to the fixture attribute will break unit tests with the following error:</p>

<pre>
Attribute_name can't be blank.
<false> is not true.
</pre>

<p>In addition, when assigning boolean values within tests, you cannot use the <code><b>false</b></code> keyword. Doing so will create an invalid record. The numeric convention to assign <code><b>true</b></code> or <code><b>false</b></code> is to use <code><b>0</b></code> and <code><b>1</b></code> respectively.</p>

<p><b>Validation of Date versus DateTime Objects.</b> Fixtures can use eRB to embed ruby code within the fixture itself. Unfortunately, when it comes to Date / DateTime attributes, the object returned by the fixture record is database dependent. In most cases, to validate date/time attributes requires using the <code><b>strftime</b></code> comparison. There is no way to get a Date object from a DateTime object. Seems intuitive, but Rails does not provide this facility. For simplicity, I've included the format parameters for posterity:</p>

<pre>
%a - The abbreviated weekday name (``Sun'')
%A - The  full  weekday  name (``Sunday'')
%b - The abbreviated month name (``Jan'')
%B - The  full  month  name (``January'')
%c - The preferred local date and time representation
%d - Day of the month (01..31)
%H - Hour of the day, 24-hour clock (00..23)
%I - Hour of the day, 12-hour clock (01..12)
%j - Day of the year (001..366)
%m - Month of the year (01..12)
%M - Minute of the hour (00..59)
%p - Meridian indicator (``AM''  or  ``PM'')
%S - Second of the minute (00..60)
%U - Week  number  of the current year,
        starting with the first Sunday as the first
        day of the first week (00..53)
%W - Week  number  of the current year,
        starting with the first Monday as the first
        day of the first week (00..53)
%w - Day of the week (Sunday is 0, 0..6)
%x - Preferred representation for the date alone, no time
%X - Preferred representation for the time alone, no date
%y - Year without a century (00..99)
%Y - Year with century
%Z - Time zone name
%% - Literal ``%'' character
</pre>

<pre name="code" class="ruby">
t = Time.now
t.strftime("Printed on %m/%d/%Y")  
    #=> "Printed on 04/09/2003"
t.strftime("at %I:%M%p")            
    #=> "at 08:56AM"
</pre>

<p>Attempting to resolve the fixture issues highlights one of Rails glaring deficiencies - the lack of authoritative, comprehensive documentation. From IRC, to the blogs I researched to troubleshoot these issues, it was apparent that everyone had rather unsubstantiated opinions regarding built-in testing facilities on Rails which were largely incomplete. No application is perfect, but this is a rather obvious omission. </p>

<h4>testhelper.rb</h4>

<p>By default, the <code><b>testhelper.rb</b></code> file has the <code><b>fixtures :all</b></code> parameter enabled. If your scaffold YAML files are not valid, this setting will only throw a lot of unintelligible errors. To build up your test suite one model at a time, it might be useful to simply have a script with <code><b>ruby</b></code> commands to run tests you've already finished. For example, I have a file that I've <code><b>chown</b></code> to be executable which contains commands to run individual tests.</p>

<pre>
ruby unit/model1_test.rb
ruby unit/model2_test.rb
</pre>

<p>The <code><b>testhelper.rb</b></code> file is not all bad. In fact when used in it's primary capacity, it's quite useful. For example, instead of writing custom assertions for my unit tests, I placed a bunch of these in <code><b>testhelper.rb</b></code>. This allows you to follow the DRY (Don't Repeat Yourself) principle an simplify test suite creation. Combined with TextExpander, it's positively stunning how quickly you can create a fairly thorough test suite for a model. I've included some of my custom assertions so that others don't have quite the barrier to entry that I encounter:</p>

<pre name="code" class="ruby">
def assert_not_valid(object, 
    msg="Object is valid when it should be invalid")
  assert(!object.valid?, msg)
end
alias :assert_invalid :assert_not_valid
  
def assert_presence_required(object, field)
  # Test that the initial object is valid
  assert_valid object
   
  # Test that it becomes invalid by removing the field
  temp = object.send field
  object.send "#{field}=", nil
  assert_invalid object
  assert !object.save, 
    "Cannot save record with invalid #{field}"
  assert object.errors.invalid?(field), "Invalid #{field}"
   
  # Make object valid again
  object.send("#{field}=", temp)
end
     
def assert_has_attribute(object, field)
  assert object.has_attribute?(field), 
     "#{object}.klass is missing #{field}"
end
	
def assert_doesnt_have_attribute(object, field)
  assert !object.has_attribute?(field), 
    "#{object}.klass is includes #{field}"
end 
	
def assert_has_readonly_attribute(class_type, field)
  attribute = class_type.readonly_attributes.find { |attr| attr == field }
  assert_not_nil attribute, 
     "#{field} read only attribute was not found."
end
	
def assert_required_length_less_than(object, field, length)
  duplicate = object.dup

  # Valid at length-1
  duplicate.send "#{field}=", "a"*(length-1)
  assert_valid duplicate

  # Valid at length
  duplicate.send "#{field}=", "a"*length
  assert_valid duplicate

  # Invalid at length+1
  duplicate.send "#{field}=", "a"*(length+1)
  assert_invalid duplicate
  assert duplicate.errors.invalid?(field), 
    "Invalid length of : #{field}"
end
	
def assert_inclusion (object, *list)
  assert list.include?(object), "#{object} not in #{list}"	
end
	
def assert_numerical(field)
  assert Integer(field) || Float(field), 
    "The field is not a number."
end
	
def assert_positive_number(field)
  assert_numerical field
  assert field > 0 , "The field is not a positive number."
end
	
def assert_negative_number(field)
  assert_numerical field
  assert field < 0 , "The field is not a negative number."
end
	
def assert_uniqueness_of(object, field)
  duplicate = object.clone
		
  assert_invalid duplicate, 
    "The #{field} attribute must be unique."
  assert duplicate.errors.invalid?(field), "Invalid #{field}"
end
	
def assert_inheritance(object_class, object)
  assert_kind_of object_class, object, 
     "#{object} is not a kind of #{object_class}."
end
</pre>

<h4>Pluralization Conventions</h4>

<p>One of the things that I needed to get used to was the use of pluralization of objects in Rails. From table names in migrations, to polymorphic <code><b>has_many</b></code> associations, being able to specify either single or multiple objects requires being aware of when rails expects plurals. As I mentioned in a previous article, pluralization is controlled through <code><b>inflections.rb</b></code>. This is something to reiterate again, unless you want to learn the hard way.</p>

<p><b>Counter Cache attributes.</b> A counter cache attribute added to a model, is expected to be a pluralized (and possibly inflected) name. For example, to add a <code><b>Comment</b></code> object counter cache to another object requires the <code><b>comments_count</b></code> attribute to be present.</p>

<h4>Limitiations of Single Table Inheritance</h4>

<p>The implementation of object inheritance in Rails can only be described as extremely rudimentary. As per Fowler's description of this pattern, a single table is responsible for all base and subclass data. While this is great for subclasses that simply add attributes to a base class when they are subclassed, this does not work so well when derived subclasses have <b>different</b> attributes.</p>

<p><b>Lack of Class Attribute Encapsulation.</b> Essentially, Rails implementation of STI does not allow subclasses to specify which attributes belong exclusively to themselves. An attribute that is available from one subclass is <b>automatically</b> available to <b>all</b> sibling subclasses. There is no mechanism to disable attribute accessors for certain classes, and enable them for others. It seems the only advantage of STI in rails is to provide convenient way to encapsulate methods and provide a mechanism for storing an object Class name in a table. Not exactly what I would consider Object Oriented .... While it has been suggested that attribute accessors can be overridden within the models, this seems like too much of hack that could have unintended consequences with regards to ActiveRecord behavior. The trade off is to probably code in logic in the classes to ensure that only certain attributes have valid values - the lesser of two evils.</p>

<p><b>Storage of Class Name as the Base Type in Associations.</b> If polymorphic associations are used in conjunction with STI, the <code><b>association_type</b></code> by default must be the base Class name. If it is the actual class name, the association will fail. There are hacks that will allow the actual Class name to be stored by overriding the <code><b>association_type</b></code> attribute, but doing so is less than all encompassing. For example, having <code><b>:dependent => :destroy</b></code> conditions on the association will fail when this hack is implemented. This would then require manually destroying associated objects. Not really a great compromise in my opinion.</p>

<h4>Miscellaneous</h4>

<p>Sometimes things just don't work the way you expect them to. In most cases, it's probably just a case of the documentation not being updated with changes in the code. One particularly pernicious bug was the way in which ActiveRecord deals with <code><b>obj.clone</b></code> versus <code><b>obj.dup</b></code>.</p>

<ul>
<li><a href="http://www.ruby-forum.com/topic/175257">ActiveRecord handling of obj.dup vs obj.clone</a></li>
</ul>

<h4>Limitations actually a Good Thing?</h4>

<ul>
<li><a href="http://www.martinfowler.com/bliki/EnterpriseRails.html">Enterprise Rails</a></li>
</ul>

<p>While these limitations suggest that these areas of Rails are under developed, Martin Fowler has an interesting take on the rigidity shown by the core rails team to solving "enterprise" problems. In his article he suggests that Rails resistance to antiquated conventions which give strength to the existing system. This goes to prove just because you can do something, doesn't mean you should (such as attempting to create an Object Relational Mapper for Rails - RHibernate anyone?).</p>

<p>I reserve the right to withhold judgment ...</p>]]>
      
   </content>
</entry>

<entry>
   <title>Professional Developer Tools OS X</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2009/01/professional_developer_tools_o.html" />
   <id>tag:www.z1r0.com,2009://1.130</id>
   
   <published>2009-01-18T21:02:54Z</published>
   <updated>2009-01-26T03:46:40Z</updated>
   
   <summary>There are just some tools that make life easier. Although I&apos;m a self proclaimed CLI junkie, I think that adhering to fundamentalist attitudes only leads to atrophy. To that end, I&apos;d like to suggest a couple of tools that I...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Eunichs" scheme="http://www.sixapart.com/ns/types#category" />
   
      <category term="Ur" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="70" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<p>There are just some tools that make life easier. Although I'm a self proclaimed CLI junkie, I think that adhering to fundamentalist attitudes only leads to atrophy. To that end, I'd like to suggest a couple of tools that I grudgingly have to admit are better than their command line equivalents. Its not these tools should be used without knowledge of their CLI counterparts; it's just that having graphical equivalents somehow refines their usage and reduces cognitive resistance when you're in the Flow.
</p>
<h4>Cornerstone</h4>
<p>I can't say enough about Subversion, but trying to keep track of changes between commits and doing diff comparisons with your working set versus the last revision is nothing short of a PITA. Thankfully, there is mature, stable graphical Subversion client for OS X - <a href="xhttp://www.zennaware.com/cornerstone/">Cornerstone</a>. It does a great job of abstracting various Subversion operations and does not suffer from extreme featuritis. Give it a try if your tired of looking up man pages to get just the right <code><b>svn</b></code> syntax.</p>
<h4>Araxis Merge</h4>
<p>While diffing files is old hat, the output is just barely human readable. Too much effort is expended by the user trying to visually grep the output. They say a picture is worth a thousand words, in the in spirit of "Ut pictura poesis" I would have to agree when using a visual diff tool. Having side by side comparisons greatly improves the ability to use diffs in a more coherent manner. Thankfully, Araxis has ported their flagship <a href="http://www.araxis.com/merge_mac/index.html">Merge</a> tool to OS X. Like Cornerstone, the features are implemented with minimal clutter. This allows it to integrate cleanly into an XCode based work flow. With its seemless integration with Cornerstone, checking working copy diffs to a source code repository can't get any easier.</p>
<h4>O'Reilly Safari</h4>
<p>Do your self a favor and forget the forest of books that inevitably become obsolete and sign up for a Safari subscription. Technical books have a limited shelf life. Prevent become antiquated and get the latest documentation without the hassle of having to lug around a dead tree. It's not that I don't like physical books, but the rate at which technical documentation evolves makes it unrealistic to have a well stocked reference library without having to spend a fortune. Combined with the BookBag iPhone app, you can have your cake and eat it too.</p>


]]>
      
   </content>
</entry>

<entry>
   <title>RailRoad II</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2009/01/railroad_ii.html" />
   <id>tag:www.z1r0.com,2009://1.128</id>
   
   <published>2009-01-13T03:30:00Z</published>
   <updated>2009-01-13T03:56:38Z</updated>
   
   <summary>Here are a few additional notes regarding my experiences with Ruby on Rails. Although there is veritable dearth of information on these topics, the difficulty as ever lies in having a single consolidated reference for these issues. At best, documentation...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Eunichs" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="70" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="45" label="rails" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<p>Here are a few additional notes regarding my experiences with Ruby on Rails. Although there is veritable dearth of information on these topics, the difficulty as ever lies in having a single consolidated reference for these issues. At best, documentation on the web is complete with examples and thoughtful explanations; at worst, it is completely misleading and full of uninformed assumptions.</p>

<h4>Required database.yml parameter : database</h4>

<p>The <code><b>database.yml</b></code> file requires the <code><b>database :</b></code> parameter in order to establish a valid connection to the database for a given user. This parameter was not present in earlier versions of the <code><b>database.yml</b></code> configuration file. See below for more details documentation regarding the PostgreSQL connection adapter parameters.</p>

<h4>Database Adapters: pg versus postgres</h4>

<p>At the time of writing this (against rails 2.2.2), there still seems to be a preference in the Rails framework for the pg driver over the postgres driver. Without the pg driver installed, the following error is displayed to the user :</p>

<pre>
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:74:in `establish_connection': Please install the postgresql adapter: `gem install activerecord-postgresql-adapter` (no such file to load -- pg) (RuntimeError)
	from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:58:in `establish_connection'
	from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:53:in `establish_connection'
	from /Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/initializer.rb:392:in `initialize_database'
	from /Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/initializer.rb:139:in `process'
	from /Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/initializer.rb:112:in `send'
	from /Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/initializer.rb:112:in `run'
	from /Users/mel/Documents/Workspace/vuespace/src/config/environment.rb:13
	from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
	from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
	from /Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/commands/generate.rb:1
	from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
	from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
	from ./script/generate:3
aleph:src mel$ gem install activerecord-postgresql-adapter
ERROR:  could not find gem activerecord-postgresql-adapter locally or in a repository
aleph:src mel$ sudo gem install activerecord-postgresql-adapter
Password:
ERROR:  could not find gem activerecord-postgresql-adapter locally or in a repository
aleph:src mel$ sudo gem install activerecord-postgresql-adapter
ERROR:  could not find gem activerecord-postgresql-adapter locally or in a repository
aleph:src mel$ sudo gem -r install activerecord-postgresql-adapter
ERROR:  Invalid option: -r.  See 'gem --help'.
aleph:src mel$ sudo gem install -r activerecord-postgresql-adapter
ERROR:  could not find gem activerecord-postgresql-adapter locally or in a repository
</pre>

<p>To install the correct the correct <code><b>pg</b></code> gem, use the following command:</p>

<pre>
# sudo env ARCHFLAGS="-arch i386" gem install pg
</pre>

<p>There seems to be a version difference between the two difference postgres adapeters : <code><b>pg (0.7.9.2008.10.13)</b></code> versus <code><b>postgres (0.7.9.2008.01.28)</b></code>. Only time will tell if this will lead to framework incompatibilities.</p>

<h4>ActiveRecord</h4>

<p>To use the scaffolding in any meaningful manner requires a clear object model that can be used to represent system objects. The <code><b>ActiveRecord::Migration</b></code> class provides detailed usage information that is required to generate these classes and the associated database types. However, details such as the rails type to database type mappings are not easily found in Rails API. The following links highlight the most important features of ActiveRecord objects which will hopefully allow more informed use of this fundamental Rails object.</p>

<ul>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Aggregations/ClassMethods.html">ActiveRecord::Aggregations</a></b> - useful when representing attributes as value objects.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html">ActiveRecord::Associations</a></b> - describes the use of object associations such as many-to-many, inheritance, and polymorphism.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Base.html">ActiveRecord::Base</a></b> - describes the base ActiveRecord object and its associated methods and properties.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Calculations/ClassMethods.html">ActiveRecord::Calculations</a></b> - describes calculation methods available to ActiveRecord objects.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Callbacks.html">ActiveRecord::Callbacks</a></b> - describes the callbacks available during the lifetime of an ActiveRecord object.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/ConnectionHandler.html">ActiveRecord::ConnectionAdapters::ConnectionHandler</a></b> - describes the use of a ConnectionHandler to distribute an object hierarchy amongst different databases.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html">ActiveRecord::ConnectionAdapters::ConnectionPool</a></b> - describes ConnectionPools which can be used to synchronize thread access to a limited number of database connections. The Options section describes the use of the <code><b>:pool</b></code> and <code><b>wait_timeout</b></code> parameters in the <code><b>database.yml</b></code> configuration file.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html">ActiveRecord::ConnectionAdapters::PostgreSQLAdapter</a></b> - describes the <code><b>database.yml</b></code> configuration parameters for PostgreSQL as well as the native datatypes the adapter maps the migration datatypes to. 

<ul>
<li><code><b>:primary_key</b></code> - serial primary key</li>
<li><code><b>:string</b></code> - character varying(255)</li>
<li><code><b>:text</b></code> - text (upto 1GB of multi-byte characters</li>
<li><code><b>:integer</b></code> - integer</li>
<li><code><b>:float</b></code> - float</li>
<li><code><b>:decimal</b></code> - numeric (can be specified with :precision and :scale</li>
<li><code><b>:datetime</b></code> - timestamp without time zone</li>
<li><code><b>:timestamp</b></code> - timestamp without time zone</li>
<li><code><b>:time</b></code> - time</li>
<li><code><b>:date</b></code> - date</li>
<li><code><b>:binary</b></code> - bytea</li>
<li><code><b>:boolean</b></code> - boolean</li>
</ul>

</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Errors.html">ActiveRecord::Errors</a></b> - describes the errors associated with ActiveRecord object operations and how to access them.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Migration.html">ActiveRecord::Migration</a></b> - migration specifics.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Observer.html">ActiveRecord::Observer</a></b> - describes Observer configuration for ActiveRecord objects which implement lifecycle callbacks.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Reflection/ClassMethods.html">ActiveRecord::Reflection</a></b> - ActiveRecord object reflection methods.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Serialization.html">ActiveRecord::Serialization</a></b> - methods which support ActiveRecord object serialization.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Transactions/ClassMethods.html">ActiveRecord::Transactions</a></b> - describes atomic database transactions and their ActiveRecord implementation.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Validations/ClassMethods.html">ActiveRecord::Validations</a></b> - describes ActiveRecord object field and condition validation methods.</li>

</ul>

<h4>Object Associations</h4>

<p>As ever, the initial challenge when creating an application is to create an object model that reflects the system being designed without imposing unnecessary limitations. There are a number of relationships that can be modeled through Rails, but it is important to understand both the usage and limitation of these mechanisms.</p>

<ul>
<li><b>Rails only supports Single Table Inheritance</b> - By default only Single Table inheritance is supported by Rails. Essentially, different subclasses are represented by a <code><b>:type</b></code> field in the database table. To avoid confusion, treat <code><b>type</b></code> as a Rails keyword an only use it when you want to model Inheritance.</li><br/>
<li><b>Polymorphism is supported through the <code><b>:has_many :has_one/ :as</b></code> mechanism</b> - common functionality can be shared amongst objects by implementing an interface. This requires the implementing object to have <code><b>interface_id:integer</b></code> and <code><b>interface_type:string</b></code> columns within their database models.</li><br/>
<li><b>The difference between <code><b>:has_one</b></code> and <code><b>:belongs_to</b></code> is largely where the foreign key resides.</b> - The <code><b>:belongs_to</b></code> implementation should have the corresponding foreign key to the referenced object.</li><br/>
<li><b>Many-to-many relationships can be modeled in a number of ways.</b> Direct relationships can be modeled using <code><b>has_and_belongs_to_many</b></code>. If the association needs to be manipulated independently, the <code><b>has_many :through</b></code> relationship will do provided a join table is created to associate the two models.</li><br/>
<li><b>Secondary associations using <code><b>:through</b></code></b>. Both the <code><b>has_one</b></code> and <code><b>has_many</b></code> associations support secondary references through intermediate objects.</li>
</ul>

<h4>Object Hierarchies</h4>

<p>There are built-in mechanisms with Rails to model ordered lists, trees, and hierarchies.</p>

<ul>
<li><code><b>:act_as_list</b></code> - allows a collection of object to function as an ordered list. This requires a <code><b>position</b></code> column within the model.</li>
<li><code><b>:act_as_tree</b></code> - allows a collection to behave as a tree. Requires the <code><b>parent_id</b></code> column within the model.</li>
<li><code><b>:act_as_nested_set</b></code> - allows a collection to behave as a hierarchy. The advantage over <code><b>:act_as_tree</b></code> is that individual nodes can be retrieved with their dependent objects. This model requires the use of the following columns : <code><b>parent_id, lft, rgt</b></code>.</li>
</ul>

<h4>Validations</h4>

<p>Data sanitation is paramount to preventing a whole host of database injection attacks. Always assume that any publicly submitted data can be used to compromise the system. To mitigate these types of attacks, ActiveRecord supports validation of conditions and fields (see above). It is highly recommended that validations be exercised in the testing framework to ensure their proper functioning.</p>]]>
      
   </content>
</entry>

<entry>
   <title>The Intangible Doppleganger</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2009/01/the_intangible_doppleganger.html" />
   <id>tag:www.z1r0.com,2009://1.127</id>
   
   <published>2009-01-02T19:43:24Z</published>
   <updated>2009-01-13T04:13:22Z</updated>
   
   <summary>Can I resell my MP3&apos;s&gt; - the post-sale life of digital goods Can you own an idea? In the era of digital content, this is a question that seems to be occluded by questions of copyright and ownership, but resides...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Culture Jam" scheme="http://www.sixapart.com/ns/types#category" />
   
      <category term="NaN" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="74" label="copyright" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<a href="http://arstechnica.com/articles/culture/post-sale-life.ars"><b>Can I resell my MP3's> - the post-sale life of digital goods</b></a>

<p>Can you own an idea? In the era of digital content, this is a question that seems to be occluded by questions of copyright and ownership, but resides fundamentally at the heart of the issue. Although it is understood that the creator holds copyright with regards to the content created, the question of ownership is much murkier when content is duplicated for mass consumption. Who owns those duplicates? What rights are extended to the purchasers when content comes into their possession? Do they have resale rights? At what point does the original content creator relinquish their rights to the purchaser, if ever?
</p>

<p>These questions highlight the difficulty of assigning ownership and possession to the intangible. Tangibility or the lack thereof is digital media's Achilles heel.  The problem is that by its nature a tangible product or commodity is obviously limited in how many copies can be made of it. This is not true for digital goods. The simple act of transmission implies that it is being duplicated. A physical commodity does not have this characteristic. It can be resold, borrowed, but it is not duplicated in the process. In essence, tangibility is a counter agent to duplicability.</p>

<p>If we look at the definition of the word counterfeit:</p>

<blockquote>
... is an imitation that is made usually with the intent to deceptively represent its content or origins.
</blockquote>

<p>It is rooted in the physical nature of a commodity. Can the term "counterfeit" be applied to digital media when a copy is as perfect as the original? Does it deceptively represent its content? I think not.</p>

<p>There are those that will argue that media can be counterfeited. CDs, DVDs, books, can all be duplicated. This is true, but what is actually being counterfeited - the medium which delivers the content or the content itself? Ultimately, physical artifacts serve as simple distribution mechanisms. They only serve as repositories for the ideas/content they transport. This leads to a more accurate definition of media - as an amalgamation of physical distribution mechanism and content.</p>

<p>Most of our consumer rights focus on this the tangible asset as the focus of copyright. Once you remove the distribution mechanism out of the equation however and are left with dissociated content, what you actually own is an idea - a cultural meme without physical constraints. Can something this ephemeral ever be constrained to individual ownership?</p>


]]>
      
   </content>
</entry>

<entry>
   <title>RailRoad</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2008/12/railroad.html" />
   <id>tag:www.z1r0.com,2008://1.66</id>
   
   <published>2008-12-09T02:36:10Z</published>
   <updated>2008-12-28T23:27:33Z</updated>
   
   <summary>Here are some notes I&apos;ve collected as I&apos;ve worked through developing my application on Rails: PostgreSQL I generally prefer using PostgreSQL for my personal projects. PostgreSQL&apos;s pedigree and consistent level of technical superiority means that I&apos;ll never have to second...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Eunichs" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="24" label="PostgreSQL" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="70" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="45" label="rails" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<p>Here are some notes I've collected as I've worked through developing my application on Rails:</p>

<h3>PostgreSQL</h3>

<p>I generally prefer using PostgreSQL for my personal projects. PostgreSQL's pedigree and consistent level of technical superiority means that I'll never have to second guess my decision regarding the database as an application's use begins to scale. Given Monty Widenius' rant against MySQL 5.1, I don't foresee it approaching the capabilities of PostgreSQL anytime soon.</p>

<h4>Rails Database Adapters</h4>

<p>That being said, there were a few caveats to keep in mind for Rails to use PostgreSQL as a back end store. The first is clarification on which <code><b>gem</b></code> adapter module is required for rails configuration. There are two - one which is a pure ruby driver, the other a compiled native driver. The <code><b>postgres-pr</code></b> (the pure ruby PostgreSQL driver) worked right out of the box. The pros of this driver is it is implemented in ruby; the con however, is that it is relatively slow compared to the native driver.
</p>

<p> With the latest version of rails (2.2.2), I found that the <code><b>postgresql</b></code> gem is no longer recognized. It has been superceded by the <code><b>postgres</b></code> native adapter. Attempting to compile the <code><b>postgres</b></code> gem against my Fink managed PostgreSQL 8.3 installation resulted in the following errors:</p>

<pre>
Building native extensions.  This could take a while...
ERROR:  Error installing postgres:
	ERROR: Failed to build gem native extension.

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby extconf.rb install postgres

===========   WARNING   ===========

You are building this extension on OS X without setting the
ARCHFLAGS environment variable, and PostgreSQL does not appear
to have been built as a universal binary. If you are seeing this
message, that means that the build will probably fail.

Try setting the environment variable ARCHFLAGS
to '-arch i386' before building.

For example:
(in bash) $ export ARCHFLAGS='-arch i386'
(in tcsh) $ setenv ARCHFLAGS '-arch i386'

Then try building again.

===================================
checking for main() in -lpq... yes
checking for libpq-fe.h... yes
checking for libpq/libpq-fs.h... yes
checking for PQsetClientEncoding()... no
checking for pg_encoding_to_char()... no
checking for PQfreemem()... no
checking for PQserverVersion()... no
checking for PQescapeString()... no
creating Makefile

make
gcc -I. -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin9.0 -I. -DHAVE_LIBPQ_FE_H -DHAVE_LIBPQ_LIBPQ_FS_H -I/sw/include/postgresql  -fno-common -arch ppc -arch i386 -Os -pipe -fno-common  -c libpq-compat.c
libpq-compat.c: In function 'PQescapeBytea':
libpq-compat.c:104: warning: incompatible implicit declaration of built-in function 'sprintf'
libpq-compat.c:104: warning: pointer targets in passing argument 1 of 'sprintf' differ in signedness
libpq-compat.c: In function 'PQunescapeBytea':
libpq-compat.c:158: warning: incompatible implicit declaration of built-in function 'strlen'
libpq-compat.c:158: warning: pointer targets in passing argument 1 of 'strlen' differ in signedness
libpq-compat.c: In function 'PQescapeBytea':
libpq-compat.c:104: warning: incompatible implicit declaration of built-in function 'sprintf'
libpq-compat.c:104: warning: pointer targets in passing argument 1 of 'sprintf' differ in signedness
libpq-compat.c: In function 'PQunescapeBytea':
libpq-compat.c:158: warning: incompatible implicit declaration of built-in function 'strlen'
libpq-compat.c:158: warning: pointer targets in passing argument 1 of 'strlen' differ in signedness
gcc -I. -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin9.0 -I. -DHAVE_LIBPQ_FE_H -DHAVE_LIBPQ_LIBPQ_FS_H -I/sw/include/postgresql  -fno-common -arch ppc -arch i386 -Os -pipe -fno-common  -c postgres.c
postgres.c:41: error: static declaration of 'PQserverVersion' follows non-static declaration
/sw/include/postgresql/libpq-fe.h:262: error: previous declaration of 'PQserverVersion' was here
postgres.c:41: error: static declaration of 'PQserverVersion' follows non-static declaration
/sw/include/postgresql/libpq-fe.h:262: error: previous declaration of 'PQserverVersion' was here
postgres.c: In function 'Init_postgres':
postgres.c:2676: error: 'pgconn_protocol_version' undeclared (first use in this function)
postgres.c:2676: error: (Each undeclared identifier is reported only once
postgres.c:2676: error: for each function it appears in.)
postgres.c:2677: error: 'pgconn_server_version' undeclared (first use in this function)
postgres.c: In function 'Init_postgres':
postgres.c:2676: error: 'pgconn_protocol_version' undeclared (first use in this function)
postgres.c:2676: error: (Each undeclared identifier is reported only once
postgres.c:2676: error: for each function it appears in.)
postgres.c:2677: error: 'pgconn_server_version' undeclared (first use in this function)
lipo: can't open input file: /var/tmp//ccZF2c6t.out (No such file or directory)
make: *** [postgres.o] Error 1
</pre>

<p>The error appeared despite setting the <code><b>ARCHFLAGS</b></code> environment variable and supplying the <code><b>POSTGRES_INCLUDE</b></code> argument to the <code><b>gem install</b></code> command. I finally got it to compile correctly after a bit of digging:</p>

<pre>
# sudo env ARCHFLAGS="-arch i386" gem install postgres
</pre>

<p>Note how the <code><b>ARCHFLAGS</b></code> needed to be passed into <code><b>sudo</b></code>. Good to know someone out there already figured it out.</p> 

<p>To use either of these database adapters, you will need to ensure that the <code><b>config/database.yml</b></code> file specifies <code><b>postgresql</b></code> for the adapter parameter. The default is <code><b>sqlite3</b></code>. It's probably a good idea to have only either the ruby or native driver installed at any given time.</p>

<p>In addition, you should remove the <code><b>database</b></code> parameter from the <code><b>database.yml</b></code> file. These are only required for SQLite databases.</p>

<h4>PostgreSQL Application Accounts</h4>

<p>The last bit of configuration requires each of the different releases (development, test, and production) have their own database users. It is generally good practice to completely keep these environments isolated from one another to avoid accidental loss of data. The <code><b>config/database.yml</b></code> file requires additional information to configure these separate connections. Each entry in the <code><b>database.yml</b></code> should have the following parameters:</p>

<pre>
host : machine_name
username : database_user
password : database_password
</pre>

<p>Due to the sensitive nature of the information contained in the <code><b>database.yml</b></code> file, it is highly recommended that this file be <b>NOT</b> world readable.</p>

<p>All of this configuration is fruitless without actual PostgreSQL users. Use the following commands to create a database and user for each of these environments (these commands assume that you are the local PostgreSQL user):</p>

<pre>
# createuser -SdRlEP development
# createuser -SdRlEP test
# createuser -SdRlEP production
</pre>

<p>The options will result in PostgreSQL users which will not have superuser privileges or the ability to create new roles, but have privileges to create databases (for scaffold creation/teardown) and log in. As well, the account will have an encrypted password.</p>

<p>Once these accounts have been created, you will need databases to associate with each of them:</p>

<pre>
# createdb -E UTF8 -O development dev_database_name
# createdb -E UTF8 -O test test_database_name
# createdb -E UTF8 -O production prod_database_name
</pre>

<p>The last step requires enabling <code><b>psql</b></code> local machine connections so that you can inspect the structure of the database for each of these releases are the evolve over the development process. This requires modifying the <code><b>data/pg_hba.conf</b></code> file for PostgreSQL. There should be entries for each user and database for each local address group (localhost / local IPV4 / local IP6).</p>

<pre>
# "local" is for Unix domain socket connections only
local        dev_database_name              development	md5
local 	test_database_name            	test   		md5
local 	prod_database_name        	production	md5

# IPv4 local connections:
host 	dev_database_name	development	127.0.0.1/32	md5
host 	test_database_name	test   		127.0.0.1/32	md5
host 	prod_database_name	production	127.0.0.1/32	md5

# IPv6 local connections:
host 	dev_database_name	development	::1/128		md5
host 	test_database_name	test	        	::1/128		md5
host 	prod_database_name	production	::1/128		md5
</pre>

<p>By specifying the encrypt password option when creating the database roles, you ensure that passwords are never transmitted in clear text. As a consequence, you must use the <code><b>MD5</b></code> authentication method in the <code><b>pg_hba.conf</b></code> file.</p>

<p>As with any configuration changes, you will have to restart the server for the changes to be applied. Test the accounts by making local <code><b>psql</b></code> connections by specifying both the user and database as options:</p>

<pre>
# psql -U development -d dev_database_name
</pre>

<p>If you plan on making the PostgreSQL account accessible over the network it is <b>highly</b> recommended that you secure your connections using SSL. Please refer to the PostgreSQL documentation to configure the server with OpenSSL certificates.</p>

<p>Here are some useful PostgreSQL/Ruby links:</p>

<ul>
<li><a href="http://wiki.rubyonrails.org/rails/pages/PostgreSQL">Ruby on Rails - Postgres</a></li>
<li><a href="http://www.postgresql.org/docs/8.3/static/index.html">PosgreSQL Manual</a></li>
</ul>

<h3>Rails</h3>

<h4>Gem Management</h4>

<p>Here are some useful commands for rails:</p>
<p>Get the a remote list of gems available.</p>
<pre>
# gem list --remote
</pre>

<p>Find a gem either in the local or remote repository.</p>
<pre>
# gem search --both name_of_gem
</pre>

<p>Display a remote gem's specifications.</p>
<pre>
# gem specification --remote name_of_gem
</pre>

<p>Search for remote generator gems which can be installed.</p>
<pre>
# gem search -r generator
</pre>

<p>Here are a list of useful gems:</p>
<ul>
<li><b>ruby-debug</b></li>
</ul>

<h4>Rails Scaffolding</h4>

<p>Rails excels as a tool for rapid prototyping with a focus on web applications which adhere to the Model-View-Controller (MVC) design paradigm. Using a relatively succinct number of ruby scripts, project scaffolding can be generated quickly and efficiently. Before projects can be automatically run in Xcode, the project must first be configured for use. This requires the following steps:</p>

<ol>
<li><p>Generate the basic project framework using the following command:</p>
<pre>
# rails project_name
</pre>
<p>This will generate a core project scaffold which contains all the required files and default configuration for a basic rails application.</p>
</li>
<li>Open Xcode and drag the generated application directory into the <b>Project & Sources</b> category in the Organizer window.</li>
<li>Click the <b>Run</b> icon and select <b>Edit Actions ...</b></li>
<li>Create a new item named.
<ul>
<li>Create a new item named <b>start server</b>.</li>
<li>In the Directory drop down, select the <b>Top Level Organizer Item</b> option.</li>
<li>In the Command text box, enter the following command : <code><b>script/server</b></code>. This corresponds to a ruby script located in the <code><b>script</b></code> directory generated by the initial <code><b>rails</b></code> scaffolding command.</li>
<li>Ensure that there are no Arguments.</li>
<li>Click OK to save the Run Action.</li>
</ul>
</li>
<li>At this point, clicking the <b>Run</b> icon should start the ruby application on your local machine. Pointing a browser to the <code><b>http://localhost:3000</b></code> address should display the default web page for the application.</li>
</ol>

<p>By default, Rails uses the <b>Active Record</b> pattern to persist application objects to a relational database.</p>

<p>To generate scaffolding for application objects which create default entries for each of the MVC components issue the following command from the top of the application directory:</p>
<pre>
# ./script/generate scaffold object_name property:data_type property:data_type
</pre>

<p>where:</p>
<ul>
<li>the <b>object_name</b> is the class of application object you wish to create scaffolding for.</li>
<li>the <b>property</b> is a property or attribute of the application object.</li>
<li>the <b>data_type</b> is the storage data type of property.</li>
</ul>

<p>In addition to the MVC files, the <code><b>scaffold generate</b></code> script also creates a <b>migration</b> file which allows database schema to upgraded/downgraded as the application is developed. In addition, by specifying different development, test, and production databases in the configuration, these separate environments remain isolated.</p>

<h4>Caveats</h4>

<a href="http://guides.rubyonrails.org/2_2_release_notes.html">2.2.2 Release Notes</a>

<p>There are number of significant changes introduced to Rails 2.2.2. These result in older applications being unable to run in the new Rails environment. It is highly recommended that you read the Release Notes for 2.2.2 to be sure that your application is not broken by this upgrade. The following is a list of a number of issues that I encountered.</p>

<hr/>

<p>The following command is deprecated in Rails 2.2.2
in config/environments/development.rb: </p>
<blockquote>
config.action_view.cache_template_extensions         = false 
</blockquote>

<hr/>

<p>Using Inflectors requires a change to the default <code><b>inflections.rb</b></code> in Rails 2.2.2 :</p>

<pre name="code" class="ruby">
 ActiveSupport::Inflector.inflections do |inflect|
   inflect.plural /^(ox)$/i, '\1en'
   inflect.singular /^(ox)en/i, '\1'
 end
</pre>

<p>Failing to add the <code><b>ActiveSupport</b></code> namespace qualifier will result in the following initialization error :</p>

<pre>
/Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:445:in `load_missing_constant': uninitialized constant Inflector (NameError)
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:77:in `const_missing'
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:89:in `const_missing'
	from /Users/mel/Documents/Workspace/vuespace/src/config/initializers/inflections.rb:5
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:142:in `load_without_new_constant_marking'
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:142:in `load'
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:521:in `new_constants_in'
	from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:142:in `load'
	from /Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/initializer.rb:550:in `load_application_initializers'
	 ... 32 levels...
	from /Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/commands/server.rb:49
	from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
	from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
	from /Users/mel/Documents/Workspace/vuespace/src/script/server:3
</pre>

<hr/>

<p>Rails now supports database connection pooling to support larger numbers of concurrent users. This feature is enabled by default in the supplied <code><b>database.yml</b></code> file where the <code><b>pool</b></code> parameter  (which specifies the maximum number of connections to use) is specified with a default. In addition, configuration now also supports the <code><b>wait_timeout</b> (the amount of time to wait before trying another connection; the default is 5 seconds)</code> parameter. </p>]]>
      
   </content>
</entry>

<entry>
   <title>Subversion Primer</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2008/12/subversion_primer.html" />
   <id>tag:www.z1r0.com,2008://1.65</id>
   
   <published>2008-12-08T01:21:42Z</published>
   <updated>2008-12-17T05:38:37Z</updated>
   
   <summary> The Red Book SVN Reference Card There comes a time when version control becomes a necessity; that&apos;s when Subversion comes to the rescue. Having worked with both CVS and Subversion, I recommend avoiding the baroque intricacies of CVS for...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Eunichs" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="70" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="73" label="subversion" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<ul>
<li><a href="http://svnbook.red-bean.com/">The Red Book</a></li>
<li><a href="/upload/svn-refcard.pdf">SVN Reference Card</a></li>
</ul>

<p>There comes a time when version control becomes a necessity; that's when Subversion comes to the rescue. Having worked with both CVS and Subversion, I recommend avoiding the baroque intricacies of CVS for the simplicity of Subversion. This is specially true if you have a project with an evolving source tree. Follow the links above for an introduction to Subversion.</p>

<p>There are a few things to note however, when attempting to use Xcode 3.1 with Subversion 1.5.x. It seems that Xcode is hardwired to verify the repository version. A repository created with the 1.4 version of the <code><b>svnadmin</b></code> returns a version identifier of 2, whereas the 1.5 of the command creates a version 3 repository. This may have to do with the back end databases used by the repository. Without significant <b><a href="http://lists.apple.com/archives/Xcode-users/2008/Sep/msg00289.html">hacking</a></b>, it seems like a lot of work with marginal benefit. For now, I'd recommend using the packaged 1.4.4 that comes with OS X 10.5.5.</p>

<p>One last thing: it seems that <code><b>launchctl</b></code> will be the default method for managing startup daemons going forward in OS X. This means that the older SystemStarter service will be deprecated in the near future. There is an article at <a href="http://www.wishingline.com/notebook/2007/03/launchsvnserveatstartup/">The Wishing Line</a> which discussed a method for automating <code><b>svnserve</b></code> startups using <code><b>launchctl</b></code>. Be sure to modify the <code><b>.plist</b></code> to use the correct paths for your binaries and repository. As with PostgreSQL, I created symbol links from <code><b>/usr/local</b></code> to the actual repository to keep a clean separation between the system defaults versus any customizations that I introduce into my computing environment through 3rd party applications.</p>

<p>With OS X 10.5.5, I found that the 1.4.4 version of <code><b>svnserve</b></code> included with the developer tools was located in the <code><b>/usr/bin</b></code> directory. You can verify this on your system with the following command:</p>

<pre>
# which svnserve
</pre>

<p>Take note of the path returned by this command; it is necessary for the <code><b>.plist</b></code> file.</p>

<p>One last customization to the <code><b>.plist</b></code> file was changing the default <code><b>--daemon</b></code> command argument and replacing it with the <code><b>--tunnel</b></code> argument to support <code><b>svn+ssh</b></code>. If you plan to use this feature for a network accessible Subversion server, keep in mind that you will also have to enable the Remote Login privilege to be enabled on your machine under System Preferences -> Sharing.</p>

<p>For the sake of completeness, here is my modified <code><b>.plist</b></code> file:</p>

<ul>
<li><a href="http://www.z1r0.com/uploads/org.tigris.Subversion.plist"">Subversion .plist</a></li>
</ul>

<pre name="code" class="xml">
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>org.tigris.Subversion</string>
	<key>ProgramArguments</key>
	<array>
		<string>/usr/bin/svnserve</string>
		<string>--tunnel</string>
		<string>--root</string>
		<string>/usr/local/svn</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
	<key>ServiceDescription</key>
	<string>Subversion Server</string>
	<key>StandardErrorPath</key>
	<string>/dev/null</string>
	<key>UserName</key>
	<string>root</string>
</dict>
</plist>
</pre>

<p>As with all these articles, please feel free to comment if you find and error or wish to add something that I've overlooked.</p>]]>
      
   </content>
</entry>

<entry>
   <title>OpenBSD Cheat Sheet</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2008/11/openbsd_cheat_sheet.html" />
   <id>tag:www.z1r0.com,2008://1.63</id>
   
   <published>2008-11-27T02:03:07Z</published>
   <updated>2008-11-27T02:37:49Z</updated>
   
   <summary>I always find myself having to dig out the following commands after I&apos;ve upgraded my systems. Here&apos;s my contribution to working smarter, not harder. Ports Unpack ports.tgz in the /usr directory. The following command will update the ports tree using...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Eunichs" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="71" label="openbsd" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[I always find myself having to dig out the following commands after I've upgraded my systems. Here's my contribution to working smarter, not harder.

<h3>Ports</h3>
<ul>
<li>Unpack <code><b>ports.tgz</b></code> in the <code><b>/usr</b></code> directory.</li>
<li><p>The following command will update the ports tree using anonymous cvs:</p>
<pre>
# cvs -q -d anoncvs@anoncvs3.usa.openbsd.org:/cvs up -r \
OPENBSD_4_4 -Pd
</pre>
<p>For a list of anoncvs servers look <a href="http://www.openbsd.org/anoncvs.html">here</a>.</p>
</li>
<li><p>To find where a package lives in the ports tree, use the following command:</p>
<pre>
# make search key=programName
</pre>
<p>Beats visual grepping all the port directories.</p>
</li>
<li><p>To show available package flavors:</p>
<pre>
# make show=FLAVORS
</pre>
<p>To build a flavor:</p>
<pre>
# env FLAVOR="flavorName" make install
</pre>
</li>
</ul>

<h3>Base System Source Code</h3>

<ul>
<li>Unpack <code><b>src.tgz</b></code> and <code><b>sys.tgz</b></code> in the <code><b>/usr/src</b></code>. Do <b>NOT</b> unpack these archives in the <code><b>/usr</b></code> directory unless you want trouble.</li>
<li><p>Apply patches from the top of the source tree - <code><b>/usr/src</b></code> using the following command:</p>
<pre>
# patch -p0 < pathToPatch/001_patchname
</pre>
<p>The instructions are fairly clear with regards what needs to happen after application of the patch. Don't skip any steps or bad shit will happen.</p>
</li>
<li><p>Rebuild the kernel using the following commands:</p>
<pre>
# cd /usr/src/sys/arch/i386/conf && config GENERIC && \
cd ../compile/GENERIC && make depend bsd && mv /bsd /bsd.old && \
cp bsd /
</pre>
<p>I usually put this into an executable script in the <code><b>/usr/src</b></code> directory so that I can easily rebuild the kernel. You might want to install <code><b>screen</b></code> from ports before attempting to run this command on a Soekris 4801 or have the patience of a saint. If you've applied of patches in succession, you can issue a single rebuild instead of rebuilding per patch. That's just masochistic.</p>
</li>
</ul>]]>
      
   </content>
</entry>

<entry>
   <title>Installing OpenBSD 4.4 on a Soekris 4801</title>
   <link rel="alternate" type="text/html" href="http://www.z1r0.com/2008/11/installing_openbsd_44_on_a_soe.html" />
   <id>tag:www.z1r0.com,2008://1.62</id>
   
   <published>2008-11-26T02:38:27Z</published>
   <updated>2008-11-26T05:37:24Z</updated>
   
   <summary>Not a very sexy title, but entirely to the point. It&apos;s been a while since I installed on my trusty Soekris 4801 and time has been both kind and capricious by dulling my memory regarding the arcana required to make...</summary>
   <author>
      <name>xirkus</name>
      <uri>www.z1r0.com</uri>
   </author>
   
      <category term="Eunichs" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="71" label="openbsd" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="72" label="soekris" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.z1r0.com/">
      <![CDATA[<p>Not a very sexy title, but entirely to the point. It's been a while since I installed on my trusty Soekris 4801 and time has been both kind and capricious by dulling my memory regarding the arcana required to make this combo work. To save myself future frustration, I've decided to document the steps and commit them to the collective unconscious. 
</p>

<p>Just a little background; I began this project when I retired my rather thirsty and ancient Pentium Pro  that served as my personal firewall/gateway for my home LAN a couple of years ago. I wanted a device that would not compromise on security and flexibility (hence the requirement to support OpenBSD) but also consume a reasonable amount of power. Enter the Soekris 4801 - an AMD Geode based embedded system. Base power consumption is 5W - 12W at peek. Not a powerful machine by modern standards, but certainly more powerful than my old system and more than sufficient for my needs.  This system was cutting edge in the embedded systems space when I got it, but has been superceded by the newer 5501-60. For the record, the 4801-60 has the following specifications:
</p>
 
<ul>
<li>233 Mhz i386 compatible AMD Geode CPU</li>
<li>128 Mbyte SDRAM (embedded)</li>
<li>3 SIS 10/100BaseT Ethernet ports (embeded)</li>
<li>2 RS232 Serial extensions with a single 9 pin port</li>
<li>1 32-bit Compact Flash socket</li>
<li>1 44 pin IDE 66 connector</li>
<li>1 Mini-PCI socket</li>
<li>1 3.3V PCI connector</li>
<li>1 1621 dual port SIS 10/100BaseT Ethernet card attached to the PCI connector</li>
</ul> 

<p>Soekris Engineering also manufactures an add-in mini-PCI VPN accelerator (vpn1411), but I haven't gotten around to installing one of these yet. Although, the Soekris is ideally suited for flash based firewall distros, I opted to have a full version of OpenBSD. Storage for the OS is provided through a CF adapter which houses a 6GB Hitachi Microdrive.</p>

<p>Like most embedded systems, there is no built-in support for external peripherals, such as keyboards, mice, and video. All communications happens through one of the two serial ports. Thankfully, the engineers at Soekris were kind enough to wire up a port, otherwise you'd be left to your own devices to rig one up for yourself. The 4801 supports comBIOS, meaning you can use a null serial cable and a communications program (such as minicom) to manage the device through its entire boot cycle. This brings us to my first tidbit; communication parameters. The 4801 supports the following :</p>

<pre>
19200 8N1
hardware and software flowcontrol off 
</pre>

<p>Be sure that your communication software is configured with these parameters - their importance will become apparent when we attempt to update the 4801 with the latest BIOS firmware. It is good practice to use the latest vendor supplied firmware to reduce the possibility of potential hardware conflicts. However, without the correct parameters, attempting to update the firmware using the built-in BIOS monitor is impossible and will result in spurious cryptic errors being thrown. There were sites which suggested that the following <code><b>xmodem</b></code> parameters be changed to enable communications compatibility with the 4801:</p>

<pre>
/usr/sbin/sx -vv -b -X
</pre>

<p>but from my experience, disabling hardware flow control was sufficient to ensure seemless serial communications.</p>

<p>The process for updating the firmware is as follows and assumes that you are already connected to the 4801 through a serial cable :</p>

<ol>
<li>Download the latest firmware from <a href="https://www.soekris.com/downloads.htm">Soekris</a>.</li>
<li>Reboot the 4801. At the boot prompt, interrupt the boot process using <code><b>CTRL-P</b></code>. This will bring up the boot monitor.</li>
<li><p>The official documentation refers to the <code><b>download</b></code> command to initiate file transfer. There is an undocumented option to this command however which will correctly initialize the file transfer session.
</p>
<pre>download -</pre>
<p>Failing to provide the additional <code><b>-</b></code> argument will result in NAK errors when attempting to establish the communications channel.</p>
</li>
<li><p>Once the file has been uploaded, issue the following command:</p>
<pre>flashupdate</pre>
</li>
<li>Reboot.</li>
</ol>

<p>For more detailed instructions, please see the <a href="Updating Bios">Updating the Soekris BIOS</a>.</p>

<p>As there is no direct way to supply install media directly to the 4801, updating the 4801 requires configuration for PXE booting. At this point, I'd like to point out my second major caveat regarding the upgrade process:</p>

<blockquote><b>The Soekris 4801 does not support PXE booting on any other interface other than the first ethernet port (ETH1).
</b>
</blockquote>

<p>I wasted a precious amount of time learning this lesson. Heed it well. This limitation also implies that to upgrade the 4801 requires it being in a network environment where the primary network interface can be configured. If this is not the case (such as when the 4801 resides on the network boundary), you will have to move it. Kiss goodbye to an in-place upgrade.</p>

<p>There are two services that are required to facilitate PXE booting - <code><b>tftp</b></code> and <code><b>dhcp</b></code>. The DHCP server has to be configured to supply an optional <code><b>filename</b></code> to a lease request made from the 4801's primary network interface. This implies that you know the MAC address of this interface. If you do not already have it, you can get it by forcing the 4801 into booting off the network using the BIOS monitor. See below.</p> 

<p>The following is an example of a <code><b>dhcpd.conf</b></code> file that supports PXE booting</p>

<pre>
# dhcpd.conf
#
# Configuration file for ISC dhcpd (see 'man dhcpd.conf')
#

## GLOBAL OPTIONS
ddns-update-style ad-hoc;
default-lease-time 1200;
max-lease-time 9600;

subnet 10.0.1.0 netmask 255.255.255.0 
	{
		range 10.0.1.101 10.0.1.200;
		option broadcast-address 10.0.1.255;
		option routers 10.0.1.1;
		option domain-name "domain.com";
	}

host soekris
	{
		hardware ethernet 00:00:24:c3:90:f8;
		fixed-address 10.0.1.100;
		filename "pxeboot";
		option host-name "soekris";
		next-server 10.0.1.10;
	}
</pre>

<p>Please note the following :</p>
<ul>
<li><b>The argument to <code><b>filename</b></code> is not an absolute path. It is simply the name of the pxeboot file.</b></li>
<li><b>The <code><b>next-server</b></code> option is required.</b></li>
<li><b>The <code><b>ddns-update-style</b></code> global option is required for newer versions of <code><b>dhcpd</b></code>.</b></li>
</ul>

<p>Following these guidelines when configuring <code><b>dhcpd</b></code> will save you from needless troubleshooting.</p>

<p>TFTP is usually managed through <code><b>inetd/xinetd</b></code>. Unfortunately, this results in <code><b>arp</b></code> network issues. It is recommended that <code><b>tftpd</b></code> run in standalone mode to avoid these issues.</p>

<p>The last part of the <code><b>tftpd</b></code> configuration requires creating a directory to serve out the <code><b>pxeboot</b></code> and <code><b>bsd.rd</b></code> files. Keep in mind that by default, <code><b>tftpd</b></code> runs as an unprivileged user (such as <code><b>nobody</b></code>). Ensure that wherever you place these PXE files, they have appropriate permissions for the daemon to access. Because we are using the console to manage the boot process, this PXE installation also requires an <code><b>etc</b></code> directory with a <code><b>boot.conf</b></code> file to configure the installer to use the console. The contents of the file are as follows:</p>

<pre>
stty com0 19200
set tty com0
boot bsd.rd
</pre>

<p><b>The order of these configuration parameters is important. The <code><b>stty</b></code></b> must come before the <code><b>set</b></code> command.</p>

<p>Believe it or not, at this point, you are ready to install OpenBSD. To get the 4801 to boot over the network requires the following steps:</p>

<ol>
<li>Reboot. Interrupt the boot process using <code><b>CTRL-P</b></code> to enter the BIOS monitor.</li>
<li><p>Issue the following boot command:</p>
<pre>
boot f0
</pre>
</li>
</ol>

<p>I won't belabor the install details; you can get these directly from the main OpenBSD site. There is however one last caveat in this upgrade process: when the installer has completed unpacking the file sets, you are asked whether you want to set the current serial console as the default terminal. <b>Say Yes!</b> If you don't, when the 4801 reboots, it will hang attempting to load the kernel. This unfortunately leads to the boot process simply hanging at the following message:</p>

<blockquote>entry point at 0x200120 </blockquote>

<p>Took me a while to figure this out. Hopefully others will not have to suffer quite as much as I did. Thankfully, OpenBSD has finally "modernized" and supplied a cleaner upgrade path than in previous releases. Hurray!!! About fucking time.</p>

]]>
      
   </content>
</entry>

</feed>
