<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" version="2.0">

<channel>
	<title>A Noted Path by Theodore Nguyen-Cao</title>
	
	<link>http://www.theodorenguyen-cao.com</link>
	<description>Personal blog of Theodore Nguyen-Cao</description>
	<pubDate>Tue, 02 Jun 2009 18:29:30 +0000</pubDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/ANotedPath" type="application/rss+xml" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">ANotedPath</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Google App Engine adds Java support (Review)</title>
		<link>http://www.theodorenguyen-cao.com/2009/04/08/google-app-engine-adds-java-support-review/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/04/08/google-app-engine-adds-java-support-review/#comments</comments>
		<pubDate>Wed, 08 Apr 2009 20:30:32 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[geekery]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[appengine]]></category>

		<category><![CDATA[review]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=293</guid>
		<description><![CDATA[Last night Google announced Java support on Google App Engine.
After a bit of toying around, here are my findings.
The Eclipse plugin is pretty slick. Deploying and build is simple.
The dev server that you spin up locally looks to be jetty under the hood.
Objects intended for storage are JDO annotated and after compiling, you run the [...]]]></description>
			<content:encoded><![CDATA[<p>Last night Google <a href="http://googleappengine.blogspot.com/2009/04/seriously-this-time-new-language-on-app.html">announced</a> Java support on Google App Engine.</p>
<p>After a bit of toying around, here are my findings.</p>
<p>The Eclipse plugin is pretty slick. Deploying and build is simple.</p>
<p>The dev server that you spin up locally looks to be jetty under the hood.</p>
<p>Objects intended for storage are JDO annotated and after compiling, you run the .class files through the DataNucleus Enhancer which adds additional metadata so Google can map it to BigTable.  The Eclipse plugin automatically performs this step for you after compiling. The examples provide a bunch of ant macros to help facilitate building/deploying.</p>
<p>One issue that I had was that the project was building with Java 1.6 and I would get an error after compiling:</p>
<pre class="console">Caused by: java.lang.UnsupportedClassVersionError: Bad version number in .class file</pre>
<p></p>
<p>Even though they say they support Java 1.5 and 1.6, I guess this doesn’t work on the Java 1.6 for the Mac.  Switching the build to 1.5 allows the DataNucleus Enhancer to run successfully. </p>
<p>Even though they are using JPA, some features have not yet been implemented or supported ( see <a href="http://code.google.com/appengine/docs/java/datastore/usingjpa.html#Unsupported_Features_of_JPA">http://code.google.com/appengine/docs/java/datastore/usingjpa.html#Unsupported_Features_of_JPA</a>)</p>
<p>Overall, I like what I see so far and think this would be great for quick prototypes of web apps/services.</p>
<p>Going through the tutorial, my awesome <a href="http://notedpath.appspot.com/guestbook.jsp">Guestbook</a> application has been created and deployed.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/tmb45-7qUPPwykTYPnx30kLkrVo/0/da"><img src="http://feedads.g.doubleclick.net/~a/tmb45-7qUPPwykTYPnx30kLkrVo/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/tmb45-7qUPPwykTYPnx30kLkrVo/1/da"><img src="http://feedads.g.doubleclick.net/~a/tmb45-7qUPPwykTYPnx30kLkrVo/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/04/08/google-app-engine-adds-java-support-review/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Custom field names in Rails error messages</title>
		<link>http://www.theodorenguyen-cao.com/2009/04/06/custom-field-names-in-rails-error-messages/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/04/06/custom-field-names-in-rails-error-messages/#comments</comments>
		<pubDate>Tue, 07 Apr 2009 03:36:28 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[geekery]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=286</guid>
		<description><![CDATA[The defaults in Rails with ActiveRecord is beautiful when you are just getting started and are created everything for the first time.  But once you get into it and your database schema becomes a little more solidified, the things that would have been easy to do by relying on the conventions of Rails require [...]]]></description>
			<content:encoded><![CDATA[<p>The defaults in Rails with ActiveRecord is beautiful when you are just getting started and are created everything for the first time.  But once you get into it and your database schema becomes a little more solidified, the things that would have been easy to do by relying on the conventions of Rails require a little bit more work.</p>
<p>In my case, I had a form where there was a database column named &#8220;num_guests&#8221;, representing the number of guests.  When the field fails to pass validation, the error messages is something like</p>
<blockquote><p>Num guests is not a number</p></blockquote>
<p>Not quite the text that we want.  It would be better if it said</p>
<blockquote><p>Number of guests is not a number</p></blockquote>
<p>After doing a little bit of digging, I found the <a href="http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002244">human_attribute_name</a> method. You can override this method in your model class to provide alternative names for fields.  To change our error message, I did the following</p>
<pre name="code" class="ruby">
class Reservation < ActiveRecord::Base
  ...
  validates_presence_of :num_guests
  ...
  HUMAN_ATTRIBUTES = {
      :num_guests    => "Number of guests"
  }

  def self.human_attribute_name(attr)
      HUMAN_ATTRIBUTES[attr.to_sym] || super
  end
end
</pre>
<p>Since Rails 2.2, this method is used to support <a href="http://rails-i18n.org/wiki/pages/i18n-rails-guide">internationalization</a> (<a href="http://en.wikipedia.org/wiki/Internationalization_and_localization">i18n</a>).  Looking at it, it reminds me of Java&#8217;s <a href="http://java.sun.com/javase/6/docs/api/java/util/ResourceBundle.html">Resource Bundles</a> and <a href="http://static.springframework.org/spring/docs/2.5.5/reference/validation.html#validation-conversion">Spring MVC&#8217;s error messages</a>. Messages are defined based off a key and there&#8217;s a chain of look ups that get applied to resolve an error&#8217;s message.  </p>
<p>Although, I don&#8217;t see myself doing any i18n work in the near-term, it is cool that we have that option now in Rails.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/EIBVEZ2QBceXCnB7aGbo-Lw9Bvg/0/da"><img src="http://feedads.g.doubleclick.net/~a/EIBVEZ2QBceXCnB7aGbo-Lw9Bvg/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/EIBVEZ2QBceXCnB7aGbo-Lw9Bvg/1/da"><img src="http://feedads.g.doubleclick.net/~a/EIBVEZ2QBceXCnB7aGbo-Lw9Bvg/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/04/06/custom-field-names-in-rails-error-messages/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Recognizing talent (at the metro)</title>
		<link>http://www.theodorenguyen-cao.com/2009/03/30/recognizing-talent-at-the-metro/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/03/30/recognizing-talent-at-the-metro/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 03:42:45 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[thoughts]]></category>

		<category><![CDATA[talent]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=281</guid>
		<description><![CDATA[After reading about the violinist playing in the metro (which happened awhile ago), I think we are, at many times, too preoccupied with ourselves and the things that are happening in our lives when we should be taking a moment or a step back to recognize the great things that are happening right in front [...]]]></description>
			<content:encoded><![CDATA[<p>After reading about the <a href="http://urbanlegends.about.com/od/music/a/violinist_metro.htm">violinist playing in the metro</a> (which happened <a href="http://www.washingtonpost.com/wp-dyn/content/article/2007/04/04/AR2007040401721.html">awhile ago</a>), I think we are, at many times, too preoccupied with ourselves and the things that are happening in our lives when we should be taking a moment or a step back to recognize the great things that are happening right in front of us.</p>
<p>Do you think you would be able to recognize extraordinary talent when it is staring you in the face?</p>
<p>Video for viewing pleasure:<br />
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/myq8upzJDJc&#038;hl=en&#038;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/myq8upzJDJc&#038;hl=en&#038;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p>

<p><a href="http://feedads.g.doubleclick.net/~a/zjwtiu-_tJ2O7iVrixYY_mWyqps/0/da"><img src="http://feedads.g.doubleclick.net/~a/zjwtiu-_tJ2O7iVrixYY_mWyqps/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/zjwtiu-_tJ2O7iVrixYY_mWyqps/1/da"><img src="http://feedads.g.doubleclick.net/~a/zjwtiu-_tJ2O7iVrixYY_mWyqps/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/03/30/recognizing-talent-at-the-metro/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Checkboxes in Stripes and Spring MVC</title>
		<link>http://www.theodorenguyen-cao.com/2009/03/29/checkboxes-in-stripes-and-spring-mvc/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/03/29/checkboxes-in-stripes-and-spring-mvc/#comments</comments>
		<pubDate>Sun, 29 Mar 2009 06:42:01 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[geekery]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[tutorials]]></category>

		<category><![CDATA[web]]></category>

		<category><![CDATA[spring]]></category>

		<category><![CDATA[stripes]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=270</guid>
		<description><![CDATA[When building dynamic web sites with lots of javascript UI components being created on the client, understanding how the web framework you&#8217;re using will process the request and what must be done to update fields accordingly is even more important.
Specifically, checkboxes have always been a pain to deal with.  The gotcha with checkboxes are [...]]]></description>
			<content:encoded><![CDATA[<p>When building dynamic web sites with lots of javascript UI components being created on the client, understanding how the web framework you&#8217;re using will process the request and what must be done to update fields accordingly is even more important.</p>
<p>Specifically, checkboxes have always been a pain to deal with.  The gotcha with checkboxes are if a checkbox isn&#8217;t checked, the request doesn&#8217;t send the parameter so it requires some additional checks to detect that the user deselected something that was there to update the field accordingly.  I&#8217;ve been playing around with the <a href="http://www.stripesframework.org">Stripes framework</a> and ran into this issue.  </p>
<p>With Stripes, you can render a checkbox using their JSP tag:</p>
<pre name="code" class="html">
&lt;stripes:checkbox checked="true" name="property1" value="yes"/&gt;
&lt;stripes:checkbox checked="true" name="property2" value="no"/&gt;
</pre>
<p>When the &#8220;checked&#8221; value is equal to &#8220;value&#8221; value, Stripes will render the checkbox as checked.  So with the code shown, two checkboxes will be shown with the first checked and the second unchecked. </p>
<p>If a user reverses this by unchecking the first, checking the second, and submit the form, the HTTP request will only see that <code>property2=no</code>.  Before the form was submitted, &#8220;property1&#8243; had a value of &#8220;yes&#8221;. Now, &#8220;property1&#8243; won&#8217;t even appear in the request parameters, so we have to do special handling to check for the absent of the parameter to update &#8220;property1&#8243; to whatever value it should be when it is not checked.</p>
<p>In Spring MVC with form binding, checkboxes are dealt with a little differently. Using Spring MVC&#8217;s <a href="http://static.springframework.org/spring/docs/2.0.x/reference/spring-form.tld.html">form JSP tag</a>, you can do:</p>
<pre name="code" class="html">
  &lt;form:checkbox path="property1" value="yes"/&gt;
  &lt;form:checkbox path="property2" value="no"/&gt;
</pre>
<p>Assuming your command bean is named &#8220;person&#8221;, this will generate the following HTML:</p>
<pre name="code" class="html">
        &lt;input name="person.property1" type="checkbox" value="yes"/&gt;
        &lt;input type="hidden" value="1" name="_person.property1"/&gt;
        &lt;input name="person.property2" type="checkbox" value="no"/&gt;
        &lt;input type="hidden" value="1" name="_person.property2"/&gt;
</pre>
<p>As noted by the <a href="http://static.springframework.org/spring/docs/2.5.5/reference/mvc.html">docs</a>, </p>
<blockquote><p>What you might not expect to see is the additional hidden field after each checkbox. When a checkbox in an HTML page is not checked, its value will not be sent to the server as part of the HTTP request parameters once the form is submitted, so we need a workaround for this quirk in HTML in order for Spring form data binding to work. The checkbox tag follows the existing Spring convention of including a hidden parameter prefixed by an underscore (&#8221;_&#8221;) for each checkbox. By doing this, you are effectively telling Spring that “the checkbox was visible in the form and I want my object to which the form data will be bound to reflect the state of the checkbox no matter what”.</p></blockquote>
<p>Spring MVC  also provides a <a href="http://static.springframework.org/spring/docs/2.0.x/reference/spring-form.tld.html#spring-form.tld.checkboxes">&#8220;checkboxes&#8221; tag</a> which allows you to render a list of checkbox boxes without having to wrap the &#8220;checkbox&#8221; tag around a JSTL forEach.</p>
<p>Hopefully, that gives you some insight into how to work with checkboxes in Stripes and Spring MVC.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/QxXbngl7x_9qE0QRv9d5vqCo1UE/0/da"><img src="http://feedads.g.doubleclick.net/~a/QxXbngl7x_9qE0QRv9d5vqCo1UE/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/QxXbngl7x_9qE0QRv9d5vqCo1UE/1/da"><img src="http://feedads.g.doubleclick.net/~a/QxXbngl7x_9qE0QRv9d5vqCo1UE/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/03/29/checkboxes-in-stripes-and-spring-mvc/feed/</wfw:commentRss>
		</item>
		<item>
		<title>IBM to buy Sun? Yay for developers!</title>
		<link>http://www.theodorenguyen-cao.com/2009/03/26/ibm-to-buy-sun-yay-for-developers/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/03/26/ibm-to-buy-sun-yay-for-developers/#comments</comments>
		<pubDate>Fri, 27 Mar 2009 00:47:59 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[humor]]></category>

		<category><![CDATA[thoughts]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=261</guid>
		<description><![CDATA[There&#8217;s buzz going around that IBM is in talks to buy Sun.  Brian Aker, Director of Technology for MySQL at Sun, gives some insights into what he thinks will happen if this deal goes through.  Many have concerns that there&#8217;s a huge culture clash and IBM will just gobble up all the great [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s buzz going around that <a href="http://www.nytimes.com/2009/03/19/technology/companies/19sun.html?scp=3&amp;sq=sun%20ibm&amp;st=cse">IBM is in talks to buy Sun</a>.  Brian Aker, Director of Technology for MySQL at Sun, <a href="http://broadcast.oreilly.com/2009/03/brian-aker-what-would-an-ibm-b.html">gives some insights</a> into what he thinks will happen if this deal goes through.  Many have concerns that there&#8217;s a huge culture clash and IBM will just gobble up all the great things MySQL and Sun have produced.</p>
<p>All valid concerns.  However, if IBM can maintain the developer community relationship that Sun and MySQL have built  I think developers may have a lot to look forward to. Especially, government contractors.</p>
<p>First thing that popped into my mind when I read this was</p>
<blockquote><p>Sweet! No more heavy-weight Oracle development.  The government will allow devs to use MySQL now!</p></blockquote>
<p>After all, it&#8217;s backed by Big Blue.</p>
<p>And nobody ever got fired for choosing IBM.</p>
<p>Right?</p>
<p><small>Installing Oracle on a laptop still gives me nightmares. *shudders*</small></p>

<p><a href="http://feedads.g.doubleclick.net/~a/bBe7E0NeZ6lOzyXikJ-Nn54P0Y8/0/da"><img src="http://feedads.g.doubleclick.net/~a/bBe7E0NeZ6lOzyXikJ-Nn54P0Y8/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/bBe7E0NeZ6lOzyXikJ-Nn54P0Y8/1/da"><img src="http://feedads.g.doubleclick.net/~a/bBe7E0NeZ6lOzyXikJ-Nn54P0Y8/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/03/26/ibm-to-buy-sun-yay-for-developers/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Parallels Desktop vs VMWare Fusion</title>
		<link>http://www.theodorenguyen-cao.com/2009/02/09/parallels-desktop-vs-vmware-fusion/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/02/09/parallels-desktop-vs-vmware-fusion/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 04:36:49 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[reviews]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=249</guid>
		<description><![CDATA[Ever since I got my Macbook, I&#8217;ve used Parallels with my Book Camp partition to run Windows side-by-side with OSX.  I had heard that there was this other option of using VMWare Fusion but never really bothered to look into it.  This was true until this weekend.  It had been a couple [...]]]></description>
			<content:encoded><![CDATA[<p>Ever since I got my Macbook, I&#8217;ve used Parallels with my Book Camp partition to run Windows side-by-side with OSX.  I had heard that there was this other option of using VMWare Fusion but never really bothered to look into it.  This was true until this weekend.  It had been a couple of days since I recently upgraded to 4gb of ram.  I actually had not started up Parallels in awhile but I wanted to test something in the dreaded Internet Explorer so I started up Parallels.</p>
<p>I was presented with the following message:</p>
<pre>Windows could not start because the following file is missing or corrupt:
<windows root>system32hal.dll.
Please re-install a copy of the above file.</windows></pre>
<p>Uh, what?</p>
<p>Must be a fluke! So, let&#8217;s try this again.</p>
<pre>
Windows could not start because the following file is missing or corrupt:
<windows root>system32ntoskrnl.dll.
Please re-install a copy of the above file.
</windows></pre>
<p>Uh-oh.  This doesn&#8217;t look good.</p>
<p>After <a href="http://www.google.com/search?hl=en&#038;q=ntoskrnl.dll+parallels&#038;btnG=Search">googling</a> a <a href="http://www.google.com/search?hl=en&#038;q=hal.dll+parallels&#038;btnG=Search">bit</a>, it turns out Parallels does some pretty bad things like <a href="http://communities.vmware.com/message/770207#770207">modify</a> essential Windows boot up files to get Boot Camp to work with Parallels. They even <a href="http://www.google.com/search?hl=en&#038;q=parallels+boot.ini&#038;btnG=Search">modify boot.ini</a>!  So, I think what happened to me was that Parallels crashed at some point and corrupted/deleted these essential Windows files rendering my Windows partition unbootable.</p>
<p>This is what you call a deal breaker.  If your software&#8217;s purpose is to allow other operating systems to run,  rendering said operating system unusable is a big no no.</p>
<p><img src="http://www.theodorenguyen-cao.com/wp-content/uploads/2009/02/fusion-1.png" alt="fusion-1" title="fusion-1" width="476" height="405" class="aligncenter size-full wp-image-257" /><br />
So, I&#8217;ve been using Fusion for a day or two now, feature for feature pretty much has everything Parallels had. Even the user interface is fairly similar, they just call things a little different. For example, what Parallels calls Coherence, Fusion calls Unity.  Performance is about the same but I don&#8217;t really play games or anything other than startup Internet Explorer when running Windows.  Best of all, Fusion doesn&#8217;t seem to do terrible things like modify Windows boot up files.  Fusion beats Parallels hands down.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/kvteltDg424NS8MVi6ro3flIaRM/0/da"><img src="http://feedads.g.doubleclick.net/~a/kvteltDg424NS8MVi6ro3flIaRM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/kvteltDg424NS8MVi6ro3flIaRM/1/da"><img src="http://feedads.g.doubleclick.net/~a/kvteltDg424NS8MVi6ro3flIaRM/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/02/09/parallels-desktop-vs-vmware-fusion/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Setup Apache on Mac OSX Leopard</title>
		<link>http://www.theodorenguyen-cao.com/2009/01/28/setup-apache-on-mac-osx-leopard/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/01/28/setup-apache-on-mac-osx-leopard/#comments</comments>
		<pubDate>Wed, 28 Jan 2009 05:46:01 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[tutorials]]></category>

		<category><![CDATA[apache]]></category>

		<category><![CDATA[leopard]]></category>

		<category><![CDATA[mac]]></category>

		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=227</guid>
		<description><![CDATA[I&#8217;ve had my Macbook for a little over a year now. However, I just recently found out Leopard comes with apache (apache2 to be specific) already installed.  To verify this is true, open up Terminal and type

>> apachectl -V
Server version: Apache/2.2.9 (Unix)
Server built:   Sep 19 2008 10:58:54
Server's Module Magic Number: 20051115:15
Server loaded: [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had my Macbook for a little over a year now. However, I just recently found out Leopard comes with apache (apache2 to be specific) already installed.  To verify this is true, open up Terminal and type</p>
<pre class="console">
>> apachectl -V
Server version: Apache/2.2.9 (Unix)
Server built:   Sep 19 2008 10:58:54
Server's Module Magic Number: 20051115:15
Server loaded:  APR 1.2.7, APR-Util 1.2.7
Compiled using: APR 1.2.7, APR-Util 1.2.7
Architecture:   64-bit
Server MPM:     Prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/prefork"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_FLOCK_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=128
 -D HTTPD_ROOT="/usr"
 -D SUEXEC_BIN="/usr/bin/suexec"
 -D DEFAULT_PIDLOG="/private/var/run/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_LOCKFILE="/private/var/run/accept.lock"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="/private/etc/apache2/mime.types"
 -D SERVER_CONFIG_FILE="/private/etc/apache2/httpd.conf"
</pre>
<p>To start up apache, you can do it a couple of ways.</p>
<p>Type <code>sudo apachectl -k start</code></p>
<p>or</p>
<p><img src="http://www.theodorenguyen-cao.com/wp-content/uploads/2009/01/web-sharing.png" alt="web-sharing" title="web-sharing" width="500" height="419" class="aligncenter size-full wp-image-237" /></p>
<ol>
<li>Go to System Preferences</li>
<li>Click on Sharing</li>
<li>Check the box that says Web Sharing</li>
</ol>
<p>You can go to http://localhost or the URL provided in the Web Sharing screen to confirm apache is running and is able to serve up requests.</p>
<p>There is also a <code>~/Sites</code> directory in your home folder.  Apache is already setup to serve up files from this directory under <code>http://localhost/~<b>[username]</b></code> where <b>[username]</b> is your user account name. Any files here will be render for example ~/Sites/index.html is accessible from the browser via http://localhost/~<b>[username]</b>/index.html.</p>
<p>One note to get this to work.  Out of the box, all requests to /Sites result in a Forbidden 403 error. To resolve this issue, modify the conf file specified above as <code>SERVER_CONFIG_FILE</code> (<code>/private/etc/apache2/httpd.conf</code> in my case) from </p>
<pre class="console">
&lt;Directory /&gt;
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
&lt;/Directory&gt;
</pre>
<p>to</p>
<pre class="console">
&lt;Directory /&gt;
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Allow from all
&lt;/Directory&gt;
</pre>
<p>Restart apache (sudo apachectl -k restart) and try going to <code>http://localhost/~<b>[username]</b></code> again.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/3dITHfhuPcv09PEb6IbqPSFAEKU/0/da"><img src="http://feedads.g.doubleclick.net/~a/3dITHfhuPcv09PEb6IbqPSFAEKU/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/3dITHfhuPcv09PEb6IbqPSFAEKU/1/da"><img src="http://feedads.g.doubleclick.net/~a/3dITHfhuPcv09PEb6IbqPSFAEKU/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/01/28/setup-apache-on-mac-osx-leopard/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Happy Vietnamese New Year!</title>
		<link>http://www.theodorenguyen-cao.com/2009/01/26/happy-vietnamese-new-year/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/01/26/happy-vietnamese-new-year/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 06:18:31 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[personal]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=223</guid>
		<description><![CDATA[
May your pockets be filled with little red envelopes.  
]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.theodorenguyen-cao.com/wp-content/uploads/2008/02/envelopes.jpg" alt="red_envelopes" title="red_envelopes" width="475" height="350" class="aligncenter size-full wp-image-72" /></p>
<p>May your pockets be filled with little red envelopes. <img src='http://www.theodorenguyen-cao.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p><a href="http://feedads.g.doubleclick.net/~a/0nW9MEH5FbVs5HaGisMXmlitYBs/0/da"><img src="http://feedads.g.doubleclick.net/~a/0nW9MEH5FbVs5HaGisMXmlitYBs/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/0nW9MEH5FbVs5HaGisMXmlitYBs/1/da"><img src="http://feedads.g.doubleclick.net/~a/0nW9MEH5FbVs5HaGisMXmlitYBs/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/01/26/happy-vietnamese-new-year/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Cleaning up iPhoto</title>
		<link>http://www.theodorenguyen-cao.com/2009/01/25/cleaning-up-iphoto/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/01/25/cleaning-up-iphoto/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:30:35 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[tutorials]]></category>

		<category><![CDATA[iphoto]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=208</guid>
		<description><![CDATA[The longer I use iPhoto, the more I hate it.  When I initially started using it, I would import photos but choose not to copy the originals to the iPhoto Library.  In the past year or so, I&#8217;ve started to just allow iPhoto to copy the originals to the iPhoto Library. So now, [...]]]></description>
			<content:encoded><![CDATA[<p>The longer I use <a href="http://www.apple.com/ilife/iphoto/">iPhoto</a>, the more I hate it.  When I initially started using it, I would import photos but choose not to copy the originals to the iPhoto Library.  In the past year or so, I&#8217;ve started to just allow iPhoto to copy the originals to the iPhoto Library. So now, I ended up with photos scattered all over the place.  This was a pain to maintain and figure out where my photos were.</p>
<p>I decided that I want all photos to be in one place and if I was going to use iPhoto, I&#8217;m going to import by copying the originals to the iPhoto Library. Before I could get all of this to happen, I had to backup all of existing photos that were not in the iPhoto Library to an external hard drive.  Planning on importing these photos over again from the external hard drive, I then deleted all of these photos through Finder.  Going back into iPhoto, I still saw the thumbnails for the photos I just deleted. If I attempt to open any of them though, it complained it couldn&#8217;t find the original.  What a mess.  There doesn&#8217;t seem to be a way to refresh your iPhoto Library and it would remove photos it doesn&#8217;t have references to any more.</p>
<p>I figure the easiest way to get my iPhoto Library setup the way I want it is to start from scratch.  So I went under my Pictures directory and renamed iPhoto Library to iPhoto Library.original. Opening up iPhoto again, you get prompted to search for your Library or create a new one.  I choose create a new iPhoto Library and now I can begin importing my photos. </p>
<p> <img src="http://www.theodorenguyen-cao.com/wp-content/uploads/2009/01/iphoto-prefs.png" alt="iphoto-prefs" title="iphoto-prefs" width="477" height="248" class="aligncenter size-full wp-image-211" /></p>
<p>After making sure I have the option to copy items to iPhoto Library when importing, I can now import photos from my external hard drive.</p>
<p>Great! Now I have all of my scattered photos in iPhoto Library.  But what about the photos I had imported to the original iPhoto Library ( the ones under iPhoto Library.original)?  Well, there didn&#8217;t seem to be an easy way to import non-broken originals form one iPhoto Library to another from the GUI so I went to the command line.</p>
<p>All of the original photos that are imported to an iPhoto Library are under a folder called Originals.  However, due to the way iPhoto manages the photos, this also includes the broken files that reference the photos I had deleted. Basically I wanted to get rid of all of these broken references before importing all of the photos from my original iPhoto Library to the new one I am creating.  Here&#8217;s how I did it.</p>
<ol>
<li>Open up Terminal</li>
<li>Change directory to the original iPhoto Library&#8217;s Originals directory (~/Pictures/iPhoto Library.original/Originals)</li>
<li>The broken references aren&#8217;t actually symbolic links. They seem to be using extended file attributes to denote where the original file actually is (see <code>xattr</code>).  Since we deleted the actual photos, to identify these files type:
<pre class="console">
find . -size 0
</pre>
<p>to get a list of all of the 0 byte files.
</li>
<li>To remove them:
<pre class="console">
find . -name "*.jpg" -size 0 -exec rm {}  \;
</pre>
<p>or if you want to just move them elsewhere:</p>
<pre class="console">
find . -name "*.jpg" -size 0 -exec mv {} $dest \;
</pre>
<p>where $dest is the path to where you want to move the files
</li>
<li>To delete all of the empty directories (that represent your events) for clean up purposes:
<pre class="console">find . -depth -type d -empty -exec rmdir {} \;</pre>
</li>
</ol>
<p>Now your original iPhoto Library should only contain photos that were imported by copying the originals to the iPhoto Library.</p>
<p>To finish importing everything, open iPhoto, choosing your new iPhoto Library and import the Originals directory from the original iPhoto Library (~/Pictures/iPhoto Library.originals/Originals). You might have to copy this folder someplace else since the Import menu doesn&#8217;t allow you to specify going into the iPhoto Library.originals package.</p>
<p>After about 5 hours of battling with iPhoto, I think I finally have all of my photos reimported to a fresh iPhoto Library with no duplicates and broken file references.  Having to do all of this really makes me think to just switch to something else. How do you guys feel about iPhoto? What are some good alternatives?  <a href="http://picasa.google.com/">Picasa</a> anyone?</p>

<p><a href="http://feedads.g.doubleclick.net/~a/N-dRq69eiGCIfezK2TSq2ZQW9yg/0/da"><img src="http://feedads.g.doubleclick.net/~a/N-dRq69eiGCIfezK2TSq2ZQW9yg/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/N-dRq69eiGCIfezK2TSq2ZQW9yg/1/da"><img src="http://feedads.g.doubleclick.net/~a/N-dRq69eiGCIfezK2TSq2ZQW9yg/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/01/25/cleaning-up-iphoto/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Moving wordpress to another host</title>
		<link>http://www.theodorenguyen-cao.com/2009/01/21/moving-wordpress-to-another-host/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/01/21/moving-wordpress-to-another-host/#comments</comments>
		<pubDate>Thu, 22 Jan 2009 04:57:35 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[geekery]]></category>

		<category><![CDATA[apache]]></category>

		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=196</guid>
		<description><![CDATA[If you&#8217;ve been following my blog for awhile, you might have noticed I moved this blog from blog.notedpath.com to theodorenguyen-cao.com as it was more fitting domain.  I originally just registered the domain, added the DNS record, and updated my apache config to have theodorenguyen-cao.com to be an server alias to blog.notedpath.com.
This allowed requests to [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve been following my blog for awhile, you might have noticed I moved this blog from <a href="http://blog.notedpath.com">blog.notedpath.com</a> to <a href="http://www.theodorenguyen-cao.com">theodorenguyen-cao.com</a> as it was more fitting domain.  I originally just registered the domain, added the DNS record, and updated my apache config to have <a href="http://www.theodorenguyen-cao.com">theodorenguyen-cao.com</a> to be an server alias to blog.notedpath.com.</p>
<p>This allowed requests to blog.notedpath.com/* and theodorenguyen-cao/* respond with the same content.  I thought I was done.  I discovered this wasn&#8217;t the case when I saw blog.notedpath.com as a direct traffic source in my google analytics for <a href="http://www.theodorenguyen-cao.com">theodorenguyen-cao.com</a>.  To fix the screwed up analytics, I needed to make it so that all requests that go to blog.notedpath.com are permanently redirected (301) to <a href="http://www.theodorenguyen-cao.com">theodorenguyen-cao.com</a>.</p>
<p>To do this I had to apply an Apache mod_alias <a href="http://httpd.apache.org/docs/1.3/mod/mod_alias.html#redirect" target="_blank">redirect directive</a> as such:</p>
<pre name="code" class="xml" >
&lt;VirtualHost *:80&gt;
        VirtualDocumentRoot /var/www/blog
        ServerName blog.notedpath.com
        Redirect permanent / http://www.theodorenguyen-cao.com/
        ErrorLog /var/log/apache2/wp-error.log
        TransferLog /var/log/apache2/wp-access.log
&lt;/VirtualHost&gt;
</pre>
<p>The virtual host for <a href="http://www.theodorenguyen-cao.com">theodorenguyen-cao.com</a> looks like:</p>
<pre name="code" class="xml" >
&lt;VirtualHost *:80&gt;
    VirtualDocumentRoot /var/www/blog
    ServerName www.theodorenguyen-cao.com
    ServerAlias theodorenguyen-cao.com
    CustomLog /var/log/apache2/theodorenguyen-cao.com_access.log Combined
    ErrorLog /var/log/apache2/theodorenguyen-cao_error.log
&lt;/VirtualHost&gt;
</pre>
<p>At first I thought this would only fix the simple case of blog.notedpath.com redirecting to <a href="http://www.theodorenguyen-cao.com">theodorenguyen-cao.com</a>, but blog.notepath.com/foobar not being translated to theodorenguyen-cao.com/foobar.  However, this does exactly what I want. All blog.notedpath.com URLs will be replaced with <a href="http://www.theodorenguyen-cao.com">theodorenguyen-cao.com</a> URLs.  Old bookmarks will simply redirect to a theodorenguyen-cao.com URL and not 404.</p>
<p>Success!</p>
<p>I&#8217;m still waiting to see if Google will update the search result links that point to blog.notedpath.com to be <a href="http://www.theodorenguyen-cao.com">theodorenguyen-cao.com</a> URLs.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/Gj2VIY6agXCqX6vpHyVhgrNW24w/0/da"><img src="http://feedads.g.doubleclick.net/~a/Gj2VIY6agXCqX6vpHyVhgrNW24w/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/Gj2VIY6agXCqX6vpHyVhgrNW24w/1/da"><img src="http://feedads.g.doubleclick.net/~a/Gj2VIY6agXCqX6vpHyVhgrNW24w/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/01/21/moving-wordpress-to-another-host/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Using validates_presence_of on a boolean field? Should use validates_inclusion_of!</title>
		<link>http://www.theodorenguyen-cao.com/2009/01/12/using-validates_presence_of-on-a-boolean-field-should-use-validates_inclusion_of/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/01/12/using-validates_presence_of-on-a-boolean-field-should-use-validates_inclusion_of/#comments</comments>
		<pubDate>Mon, 12 Jan 2009 05:38:43 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[geekery]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[tutorials]]></category>

		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=191</guid>
		<description><![CDATA[rsvp.theoandpat.com had boolean flag to marked whether or not a visitor was going to be able to make it to our wedding. Unfortunately, if you selected you were not able to make it and submit the form, the application would return saying it could not process your submission because you have to say that you [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://rsvp.theoandpat.com">rsvp.theoandpat.com</a> had boolean flag to marked whether or not a visitor was going to be able to make it to our wedding. Unfortunately, if you selected you were not able to make it and submit the form, the application would return saying it could not process your submission because you have to say that you are going to make it. I argued, this is an RSVP form so you have to accept if you are RSVPing. That&#8217;s the point of the RSVP! Only people RSVP would bother submitting the form!  Pat wasn&#8217;t too happy about that and ask/told me to fix it.  </p>
<p>Digging into it, it turns out the way  for <code><a href="http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M001893">validates_presence_of</a></code> relies on <code>Object#blank</code> which of course when sent</p>
<pre name="code" class="ruby">
false.blank? # returns true
</pre>
<p>Reading up on the documentation, it is suggested to use <code><a href="http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M001898">validates_inclusion_of</a></code> when dealing with booleans.</p>
<p>The one line change solved the problem:</p>
<pre name="code" class="ruby">
validates_inclusion_of :accepted, :in => [true, false]
</pre>

<p><a href="http://feedads.g.doubleclick.net/~a/cd5JFLpBIO7_G6ITBllA32N-eec/0/da"><img src="http://feedads.g.doubleclick.net/~a/cd5JFLpBIO7_G6ITBllA32N-eec/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/cd5JFLpBIO7_G6ITBllA32N-eec/1/da"><img src="http://feedads.g.doubleclick.net/~a/cd5JFLpBIO7_G6ITBllA32N-eec/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/01/12/using-validates_presence_of-on-a-boolean-field-should-use-validates_inclusion_of/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Picasa vs Flickr</title>
		<link>http://www.theodorenguyen-cao.com/2009/01/12/picasa-vs-flickr/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/01/12/picasa-vs-flickr/#comments</comments>
		<pubDate>Mon, 12 Jan 2009 05:06:37 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[personal]]></category>

		<category><![CDATA[thoughts]]></category>

		<category><![CDATA[web]]></category>

		<category><![CDATA[photography]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=182</guid>
		<description><![CDATA[Pat got me a new camera for my birthday this past October so I have been trying to take more pictures lately.  One of my new years resolutions is to take more pictures!  As a result, I&#8217;ve been trying out Yahoo&#8217;s Flickr and Google&#8217;s Picasa over the past couple of weeks.  With [...]]]></description>
			<content:encoded><![CDATA[<p>Pat got me a new camera for my birthday this past October so I have been trying to take more pictures lately.  One of my new years resolutions is to take more pictures!  As a result, I&#8217;ve been trying out Yahoo&#8217;s <a href="http://www.flickr.com">Flickr</a> and Google&#8217;s <a href="http://www.picasa.com">Picasa</a> over the past couple of weeks.  With Picasa recently added <a href="http://picasa.google.com/mac/">support on the Mac</a> and Apple announcing iPhoto out-of-the-box Flickr integration, the feature sets from the desktop are pretty much identical.  Both support (or will support) face recognition, tagging, and exporting.</p>
<p>For the web galleries, I really liked Picasa&#8217;s layout over Flickr&#8217;s.  The web site is a lot more simplistic and easy to navigate.  Maybe it&#8217;s becase I&#8217;m so familiar with other Google services.  Flickr&#8217;s slideshow is so awesome though.  Viewing your photostream through <a href="http://www.cooliris.com">Cooliris</a> is such beautiful eye candy.</p>
<p style="text-align: center;"><img class="size-medium wp-image-186 aligncenter" title="cooliris" src="http://www.theodorenguyen-cao.com/wp-content/uploads/2009/01/picture-16-300x187.png" alt="cooliris" width="300" height="187" /></p>
<p>I started with the free accounts.  Google gives you a gig of space for the free account and you can create as many albums as you want. Flickr&#8217;s free account gives you 100 mb of upload per month and limits you to three sets.</p>
<p>For me, it really came down to pricing. In order to get more disk space for Picasa, you have to <a href="https://www.google.com/accounts/PurchaseStorage?hl=en_US">purchase more storage</a>.  Starting purchase goes for $20/yr for 10gigs up to $500/yr for 400GB.  This storage is actually not specific to Picasa but is shared by all other Google services that need to use extra space. Flickr offers a <a href="http://www.flickr.com/upgrade/">Pro account</a>, which gives you unlimited storage space for your videos and photos and allows you to create any number of sets and collections, for $24.95.</p>
<p>Given the number of photos I want to upload and my budget, I went with Flickr. Today, storage is so cheap. For $25 bucks, I should be able to get unlimited storage for a service like photo sharing. I&#8217;ve started to upload some photos I&#8217;ve had for awhile and never really shared them with those who would most enjoy them.  It&#8217;s been really fun going through old pictures. My photostream can be found <a href="http://flickr.com/photos/theodorenguyen-cao/">here</a>.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/Hrs-Vwrw9GY3pOeKVW_LJfcPtCw/0/da"><img src="http://feedads.g.doubleclick.net/~a/Hrs-Vwrw9GY3pOeKVW_LJfcPtCw/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/Hrs-Vwrw9GY3pOeKVW_LJfcPtCw/1/da"><img src="http://feedads.g.doubleclick.net/~a/Hrs-Vwrw9GY3pOeKVW_LJfcPtCw/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/01/12/picasa-vs-flickr/feed/</wfw:commentRss>
		</item>
		<item>
		<title>tiny URLs? HA! diminutive URLs for the win!</title>
		<link>http://www.theodorenguyen-cao.com/2009/01/11/tiny-urls-ha-diminutive-urls-for-the-win/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/01/11/tiny-urls-ha-diminutive-urls-for-the-win/#comments</comments>
		<pubDate>Mon, 12 Jan 2009 04:19:10 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[geekery]]></category>

		<category><![CDATA[humor]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=171</guid>
		<description><![CDATA[Inspired by a discussion of URL shortening, I took a weekend and implemented one of my own.  When thinking about tiny URLs, a quote always came to mind.
Don&#8217;t use a big word where a diminutive one will suffice.
So after finding out the domain was available, diminutiveurl.com was born.  Yes, it&#8217;s poking a little fun [...]]]></description>
			<content:encoded><![CDATA[<p>Inspired by a <a href="http://www.codinghorror.com/blog/archives/000935.html">discussion</a> of URL shortening, I took a weekend and implemented one of my own.  When thinking about tiny URLs, a <a href="http://www.quotationspage.com/quote/264.html">quote</a> always came to mind.</p>
<blockquote><p>Don&#8217;t use a big word where a diminutive one will suffice.</p></blockquote>
<p>So after finding out the domain was available, <a href="http://www.diminutiveurl.com">diminutiveurl.com</a> was born.  Yes, it&#8217;s poking a little fun at the idea of a tiny url but it was fun to hack on.  It&#8217;s very minimilistic at this point but I hope to add some interesting features.<br />
<center><a href="http://www.diminutiveurl.com"><img class="size-full wp-image-172" title="diminutiveurl.com" src="http://www.theodorenguyen-cao.com/wp-content/uploads/2009/01/wt496ac2561d2a0-thumb_medium.jpg" alt="diminutiveurl.com" width="320" height="240" /></a></center></p>
<p>For no other reason than to build something, I hope you enjoy it! I am glad to present <a href="http://www.diminitiveurl.com">diminitiveurl.com</a>!  Please <a href="http://diminutiveurl.uservoice.com/">let me know what you think</a>.</p>
<p>.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/Sp6wZk5fYXqgZUYbJM3sQbcJwio/0/da"><img src="http://feedads.g.doubleclick.net/~a/Sp6wZk5fYXqgZUYbJM3sQbcJwio/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/Sp6wZk5fYXqgZUYbJM3sQbcJwio/1/da"><img src="http://feedads.g.doubleclick.net/~a/Sp6wZk5fYXqgZUYbJM3sQbcJwio/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/01/11/tiny-urls-ha-diminutive-urls-for-the-win/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Introducing theoandpat.com</title>
		<link>http://www.theodorenguyen-cao.com/2009/01/11/introducing-theoandpatcom/</link>
		<comments>http://www.theodorenguyen-cao.com/2009/01/11/introducing-theoandpatcom/#comments</comments>
		<pubDate>Mon, 12 Jan 2009 04:03:04 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[personal]]></category>

		<category><![CDATA[pat]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=164</guid>
		<description><![CDATA[Over the course of the past months in her free time between work and planning a wedding, Pat&#8217;s been hard at work at creating a web site for our wedding. We felt we had enough to show it off to the rest o the world so I finally got around to deploying it.  I&#8217;m really [...]]]></description>
			<content:encoded><![CDATA[<p>Over the course of the past months in her free time between work and planning a wedding, Pat&#8217;s been hard at work at creating a web site for our wedding. We felt we had enough to show it off to the rest o the world so I finally got around to deploying it.  I&#8217;m really happy with the way it turned out. I think she did a pretty awesome job.  I contributed in a small way by setting up the web server, create the <a href="http://rsvp.theoandpat.com">RSVP</a> site, and installing the guestbook.  The whole concept and design is Pat&#8217;s creation.  She did all of the page layout and flash work.  I&#8217;m so proud of her. She&#8217;s turning into a web geek and she doesn&#8217;t even know it.</p>
<p style="text-align: center;"><img class="size-medium wp-image-167 aligncenter" title="theoandpat.com" src="http://www.theodorenguyen-cao.com/wp-content/uploads/2009/01/wt496abddf646a8-thumb_medium-300x225.jpg" alt="theoandpat.com" width="300" height="225" /></p>
<p>I&#8217;m sure there are some kinks to iron out but please check out <a href="http://www.theoandpat.com">theoandpat.com</a> and let us know what you think.  Oh, yeah also, <a href="http://rsvp.theoandpat.com">RSVP</a> for the wedding. If you&#8217;re reading my blog, chances are I know you and you&#8217;re invited. <img src='http://www.theodorenguyen-cao.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>-Theo</p>

<p><a href="http://feedads.g.doubleclick.net/~a/O_P6saOSTKiR1DjdjeBhvAWsfOU/0/da"><img src="http://feedads.g.doubleclick.net/~a/O_P6saOSTKiR1DjdjeBhvAWsfOU/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/O_P6saOSTKiR1DjdjeBhvAWsfOU/1/da"><img src="http://feedads.g.doubleclick.net/~a/O_P6saOSTKiR1DjdjeBhvAWsfOU/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2009/01/11/introducing-theoandpatcom/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Reduce MySQL memory usage</title>
		<link>http://www.theodorenguyen-cao.com/2008/12/07/reduce-mysql-memory-usage/</link>
		<comments>http://www.theodorenguyen-cao.com/2008/12/07/reduce-mysql-memory-usage/#comments</comments>
		<pubDate>Sun, 07 Dec 2008 23:13:35 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[tutorials]]></category>

		<category><![CDATA[how-to]]></category>

		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=160</guid>
		<description><![CDATA[As I am running more and more on my 256mb slice, I&#8217;m trying to squeeze more performance out of the system.  After a bit of digging, I&#8217;ve made a few changes.
First thing I did was switch out the default mysql config with one tweaked for smaller boxes.  This configuration actually came with the [...]]]></description>
			<content:encoded><![CDATA[<p>As I am running more and more on my 256mb <a href="https://manage.slicehost.com/customers/new?referrer=ea4080140dbc12aa766f25a2f4ad1c66 ">slice</a>, I&#8217;m trying to squeeze more performance out of the system.  After a bit of digging, I&#8217;ve made a few changes.</p>
<p>First thing I did was switch out the default mysql config with one tweaked for smaller boxes.  This configuration actually came with the mysql installation under <code>/usr/share/doc/mysql-server-5.0/examples/</code>. Just backup your existing my.cnf (mine is located under <code>/etc/mysql</code>) and use the following:</p>
<pre name="code" class="ruby">
# The following options will be passed to all MySQL clients
[client]
port		= 3306
socket		= /var/run/mysqld/mysqld.sock

# Here follows entries for some specific programs

# The MySQL server
[mysqld]
port		= 3306
socket		= /var/run/mysqld/mysqld.sock
skip-locking
key_buffer = 16K
max_allowed_packet = 1M
table_cache = 4
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 64K

# Don't listen on a TCP/IP port at all. This can be a security enhancement,
# if all processes that need to connect to mysqld run on the same host.
# All interaction with mysqld must be made via Unix sockets or named pipes.
# Note that using this option without enabling named pipes on Windows
# (using the "enable-named-pipe" option) will render mysqld useless!
#
#skip-networking
server-id	= 1

# Uncomment the following if you want to log updates
#log-bin=mysql-bin

# Uncomment the following if you are NOT using BDB tables
#skip-bdb

# Uncomment the following if you are using InnoDB tables
#innodb_data_home_dir = /var/lib/mysql/
#innodb_data_file_path = ibdata1:10M:autoextend
#innodb_log_group_home_dir = /var/lib/mysql/
#innodb_log_arch_dir = /var/lib/mysql/
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
#innodb_buffer_pool_size = 16M
#innodb_additional_mem_pool_size = 2M
# Set .._log_file_size to 25 % of buffer pool size
#innodb_log_file_size = 5M
#innodb_log_buffer_size = 8M
#innodb_flush_log_at_trx_commit = 1
#innodb_lock_wait_timeout = 50

[mysqldump]
quick
max_allowed_packet = 16M

[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates

[isamchk]
key_buffer = 8M
sort_buffer_size = 8M

[myisamchk]
key_buffer = 8M
sort_buffer_size = 8M

[mysqlhotcopy]
interactive-timeout
</pre>
<p>You can see estimated memory usage with a config if you just copy paste the configuration file <a href="http://www.omh.cc/mycnf/">here</a>.</p>
<p>Restart MySQL (<code>/etc/init.d/mysql restart</code>).</p>
<p>The second thing I did was check out <a href="http://wiki.mysqltuner.com/MySQLTuner">MySQLTuner</a>.  Just download the perl script and run it.  It will run some analysis on your mysql setup and provide some performance and configuration tweak recommendations.</p>
<p>Sample output looks like this:</p>
<pre name="code" class="console">
 >>  MySQLTuner 1.0.0 - Major Hayden <major@mhtx.net>
 >>  Bug reports, feature requests, and downloads at http://mysqltuner.com/
 >>  Run with '--help' for additional options and output filtering
Please enter your MySQL administrative login: root
Please enter your MySQL administrative password: 

-------- General Statistics --------------------------------------------------
[--] Skipped version check for MySQLTuner script
[OK] Currently running supported MySQL version 5.0.51a-3ubuntu5.4
[OK] Operating on 64-bit architecture

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +Archive -BDB -Federated +InnoDB -ISAM -NDBCluster
[--] Data in MyISAM tables: 867K (Tables: 18)
[--] Data in InnoDB tables: 704K (Tables: 40)
[!!] Total fragmented tables: 2

-------- Performance Metrics -------------------------------------------------
[--] Up for: 14h 57m 0s (17K q [0.316 qps], 699 conn, TX: 55M, RX: 3M)
[--] Reads / Writes: 96% / 4%
[--] Total buffers: 26.0M global + 824.0K per thread (100 max threads)
[OK] Maximum possible memory usage: 106.5M (41% of installed RAM)
[OK] Slow queries: 0% (0/17K)
[OK] Highest usage of available connections: 6% (6/100)
[!!] Key buffer size / total MyISAM indexes: 16.0K/381.0K
[!!] Key buffer hit rate: 88.5% (154K cached / 17K reads)
[!!] Query cache is disabled
[OK] Sorts requiring temporary tables: 0% (0 temp sorts / 4K sorts)
[!!] Temporary tables created on disk: 30% (1K on disk / 4K total)
[!!] Thread cache is disabled
[!!] Table cache hit rate: 0% (4 open / 7K opened)
[OK] Open file limit used: 0% (8/1K)
[OK] Table locks acquired immediately: 99% (17K immediate / 17K locks)
[OK] InnoDB data size / buffer pool: 704.0K/8.0M

-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    MySQL started within last 24 hours - recommendations may be inaccurate
    Enable the slow query log to troubleshoot bad queries
    When making adjustments, make tmp_table_size/max_heap_table_size equal
    Reduce your SELECT DISTINCT queries without LIMIT clauses
    Set thread_cache_size to 4 as a starting value
    Increase table_cache gradually to avoid file descriptor limits
Variables to adjust:
    key_buffer_size (> 381.0K)
    query_cache_size (>= 8M)
    tmp_table_size (> 32M)
    max_heap_table_size (> 16M)
    thread_cache_size (start at 4)
    table_cache (> 4)
</pre>
<p>I haven&#8217;t made any of the recommended changes yet though. I am going to try to see how this default small config performs.</p>
<p>I&#8217;ll try to follow up with any of my findings.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/b6Lrt9dAO9j9dbdrBr_t_igPchs/0/da"><img src="http://feedads.g.doubleclick.net/~a/b6Lrt9dAO9j9dbdrBr_t_igPchs/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/b6Lrt9dAO9j9dbdrBr_t_igPchs/1/da"><img src="http://feedads.g.doubleclick.net/~a/b6Lrt9dAO9j9dbdrBr_t_igPchs/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2008/12/07/reduce-mysql-memory-usage/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Rails initial request slow with mod_rails</title>
		<link>http://www.theodorenguyen-cao.com/2008/12/07/rails-initial-request-slow-with-mod-rails/</link>
		<comments>http://www.theodorenguyen-cao.com/2008/12/07/rails-initial-request-slow-with-mod-rails/#comments</comments>
		<pubDate>Sun, 07 Dec 2008 18:20:08 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[ruby]]></category>

		<category><![CDATA[tutorials]]></category>

		<category><![CDATA[how-to]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=158</guid>
		<description><![CDATA[Following up on my previous post , I&#8217;ve been experience slow load times (10-15 secs) on the initial request after application restarts.  This has to do with the way mod_rails manages application instances (Although, I experienced this when using mongrel_cluster and proxy balancers).  It will spin up instances on page request and each [...]]]></description>
			<content:encoded><![CDATA[<p>Following up on my previous <a href="http://www.theodorenguyen-cao.com/2008/12/06/setting-up-phusion-passenger-mod_rails-with-capistrano-support/">post</a> , I&#8217;ve been experience slow load times (10-15 secs) on the initial request after application restarts.  This has to do with the way mod_rails manages application instances (Although, I experienced this when using mongrel_cluster and proxy balancers).  It will spin up instances on page request and each instance has an idle timeout.  This just means after the timeout expires, mod_rails will shutdown that instance to conserve memory allocation.  While you can change timeout value (see <a href="http://www.modrails.com/documentation/Users%20guide.html#PassengerPoolIdleTime">PassengerPoolIdleTime</a>), this will only cause all instances that get spin up to live longer. After high load times, these instances will stick around longer than neccessary.</p>
<p>For low traffic sites (like mine), this idle timeout may be reached causing the next visitor to our website to experience a really long delay before page load.  What we really want is an option to set a minimum number of instances.  This would allow us to automatically spin up an instance during start up and keep it around.  Unfortunately at this time, it doesn&#8217;t look like there is a way to set this.  </p>
<p>As a workaround, I&#8217;ve setup a crontab that makes a request to my application every 5 minutes to prevent  mod_rails from killing off all application instances.</p>
<p>To do this just run:</p>
<pre name="code" class="console">crontab -e</pre>
<p>And then specific the following cron</p>
<pre name="code" class="console">
*/5 * * * * wget -O /dev/null http://www.myapp.com 2>/dev/null
</pre>
<p>You can verify this is working correctly but just tailing your application logs and verify every 5 minutes you get a request.</p>
<p>You can also run </p>
<pre name="code" class="console">
 passenger-status
</pre>
<p>You should see at least the count variable to be at least 1 instance.</p>
<p>Note, this workaround will not immediate start up an instance upon restart.  You can add an initial request as part of your post deploy capistrano task though.  You probably should be making sure your application is up after deploying or restarting the application anyways.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/QtFH3oZAeNfX211gnDWzO6gyG7Q/0/da"><img src="http://feedads.g.doubleclick.net/~a/QtFH3oZAeNfX211gnDWzO6gyG7Q/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/QtFH3oZAeNfX211gnDWzO6gyG7Q/1/da"><img src="http://feedads.g.doubleclick.net/~a/QtFH3oZAeNfX211gnDWzO6gyG7Q/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2008/12/07/rails-initial-request-slow-with-mod-rails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Setting up Phusion Passenger (mod_rails) with Capistrano support</title>
		<link>http://www.theodorenguyen-cao.com/2008/12/06/setting-up-phusion-passenger-mod_rails-with-capistrano-support/</link>
		<comments>http://www.theodorenguyen-cao.com/2008/12/06/setting-up-phusion-passenger-mod_rails-with-capistrano-support/#comments</comments>
		<pubDate>Sun, 07 Dec 2008 00:27:18 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[geekery]]></category>

		<category><![CDATA[tutorials]]></category>

		<category><![CDATA[apache]]></category>

		<category><![CDATA[how-to]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=144</guid>
		<description><![CDATA[I had heard of mod_rails awhile back but never had the time to take a closer look at it.  While setting up a new rails app, I was getting frustrated with all of the configuration I needed to do to get the mongrel clusters and proxy balancers setup.  So I decided to give passenger a [...]]]></description>
			<content:encoded><![CDATA[<p>I had heard of mod_rails awhile back but never had the time to take a closer look at it.  While setting up a new rails app, I was getting frustrated with all of the configuration I needed to do to get the mongrel clusters and proxy balancers setup.  So I decided to give passenger a chance.  I&#8217;m a fan now <img src='http://www.theodorenguyen-cao.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>The process was dead simple.</p>
<ol>
<li>Install the passenger gem
<pre class="console" name="code">sudo gem install passenger</pre>
</li>
<li>Install passenger as an Apache module
<pre class="console" name="code">passenger-install-apache2-module</pre>
</li>
<li>Load the passenger apache module by editing the Apache config
<pre class="console" name="code">
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.0.5/ext/apache2/mod_passenger.so
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.0.5
PassengerRuby /usr/bin/ruby1.8
</pre>
</li>
<li>Restart Apache</li>
</ol>
<p>If all things went well, you have everything installed you need. If there were some missing dependencies, you should be presented with how to install those dependencies.</p>
<p>In the installation output, it tells you how to mod_railsify your apps by creating a vhost as such:</p>
<pre class="console" name="code">
&lt;VirtualHost *:80&gt;
    ServerName www.mywebsite.com
    DocumentRoot /home/deploy/mywebsite/public
&lt;/VirtualHost&gt;
</pre>
<p>That&#8217;s it! No more of this proxy balancer and mongrel_cluster.yml configuration.</p>
<p>There&#8217;s some magic going on in the background.  As requests come in, passenger will spin up more application instances.  For more tweaking your configuration options check out the <a href="http://www.modrails.com/documentation/Users%20guide.html#_resource_control_and_optimization_options">user guide</a>.</p>
<p>Go to your website and you should see your rails app up and running.</p>
<p>So now we have your app up and running, how do we update or restart our app?  Passenger provides two ways for us to do this. </p>
<p>The first is whenever apache is restarted, your application is restarted.</p>
<p>The second way allows us to restart a specified application without affecting Apache.  Whenever passenger detects <code>tmp/restart.txt</code>, it will restart the application instances for us.  We can integrate this into our Capistrano deploy flow by adding the following  our <code>config/deploy.rb</code></p>
<pre name="code" class="ruby">
namespace :passenger do
  desc "Restart Application"
  task :restart do
    run "touch #{current_path}/tmp/restart.txt"
  end
end

after :deploy, "passenger:restart"
</pre>
<p>This will create that restart.txt after the cap:deploy task gets executed, causing the application to restart.</p>
<p>Finally, passenger comes with some pretty useful utilities.</p>
<p>Check out <code>passenger-status</code> which produces output showing current passenger server statuses.</p>
<p>Sample output: </p>
<pre name="code" class="console">
----------- General information -----------
max      = 6
count    = 1
active   = 0
inactive = 1
Using global queue: no
Waiting on global queue: 0

----------- Applications -----------
/home/deploy/www.myapp.com/releases/20081206183156:
  PID: 30784     Sessions: 0
</pre>
<p>Another utility <code>passenger-memory-status</code> gives you insight into how much memory is being used by apache and passenger.</p>
<p>Sample output:</p>
<pre name="code" class="console">
-------------- Apache processes ---------------
PID    PPID   Threads  VMSize    Private  Name
-----------------------------------------------
12841  1      1        225.9 MB  0.0 MB   /usr/sbin/apache2 -k start
28294  12841  1        248.4 MB  21.4 MB  /usr/sbin/apache2 -k start
28300  12841  1        243.7 MB  0.5 MB   /usr/sbin/apache2 -k start
28306  12841  1        248.4 MB  4.4 MB   /usr/sbin/apache2 -k start
28357  12841  1        249.1 MB  19.8 MB  /usr/sbin/apache2 -k start
29400  12841  1        249.4 MB  3.7 MB   /usr/sbin/apache2 -k start
29788  12841  1        249.3 MB  21.7 MB  /usr/sbin/apache2 -k start
29834  12841  1        245.8 MB  18.9 MB  /usr/sbin/apache2 -k start
29836  12841  1        245.8 MB  9.3 MB   /usr/sbin/apache2 -k start
29868  12841  1        245.8 MB  2.4 MB   /usr/sbin/apache2 -k start
29870  12841  1        246.5 MB  5.2 MB   /usr/sbin/apache2 -k start
### Processes: 11
### Total private dirty RSS: 107.44 MB

--------- Passenger processes ----------
PID    Threads  VMSize    Private  Name
----------------------------------------
28031  10       15.3 MB   0.1 MB   /usr/lib/ruby/gems/1.8/gems/passenger-2.0.5/ext/apache2/ApplicationPoolServerExecutable 0 /usr/lib/ruby/gems/1.8/gems/passenger-2.0.5/bin/passenger-spawn-server  /usr/bin/ruby1.8  /tmp/passenger_status.12841.fifo
28032  2        48.7 MB   0.6 MB   Passenger spawn server
29161  1        114.8 MB  0.7 MB   Passenger FrameworkSpawner: 2.1.2
30461  1        122.8 MB  32.3 MB  Passenger ApplicationSpawner: /home/deploy/www.myapp.com/releases/20081206183156
30784  1        129.3 MB  33.4 MB  Rails: /home/deploy/www.myapp.com/releases/20081206183156
### Processes: 5
### Total private dirty RSS: 67.08 MB
</pre>
<p>Pretty sweet.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/DX2m7ejNEz5oedd7ebYzgWJ9oTQ/0/da"><img src="http://feedads.g.doubleclick.net/~a/DX2m7ejNEz5oedd7ebYzgWJ9oTQ/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/DX2m7ejNEz5oedd7ebYzgWJ9oTQ/1/da"><img src="http://feedads.g.doubleclick.net/~a/DX2m7ejNEz5oedd7ebYzgWJ9oTQ/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2008/12/06/setting-up-phusion-passenger-mod_rails-with-capistrano-support/feed/</wfw:commentRss>
		</item>
		<item>
		<title>2 ways to fix transparent PNG files in IE6</title>
		<link>http://www.theodorenguyen-cao.com/2008/11/09/2-ways-to-fix-transparent-png-files-in-ie6/</link>
		<comments>http://www.theodorenguyen-cao.com/2008/11/09/2-ways-to-fix-transparent-png-files-in-ie6/#comments</comments>
		<pubDate>Sun, 09 Nov 2008 23:51:15 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[geekery]]></category>

		<category><![CDATA[tutorials]]></category>

		<category><![CDATA[web]]></category>

		<category><![CDATA[css]]></category>

		<category><![CDATA[how-to]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=139</guid>
		<description><![CDATA[I fired up Photoshop for the first time in a long time.  I created a transparent PNG for an image that would be used as a CSS background-image.  It keeps displaying with a gray background even though the page background color was something else.
This is a pretty well documented bug. Luckily, there are [...]]]></description>
			<content:encoded><![CDATA[<p>I fired up Photoshop for the first time in a long time.  I created a transparent PNG for an image that would be used as a CSS background-image.  It keeps displaying with a gray background even though the page background color was something else.</p>
<p>This is a pretty well documented <a href="http://support.microsoft.com/kb/294714">bug</a>. Luckily, there are a couple of ways to fix this.  </p>
<p>Here are my two favorites:</p>
<p>The first solution is well documented:</p>
<p>Download <a href="http://www.twinhelix.com/css/iepngfix/">iepngfix.zip</a>. The development version 2.0 Alpha 3 has support for background position and repeat.  Extract the zip and copy  <code>iepngfix.htc</code> and <code>blank.gif</code> somewhere.  I put in under <code>stylesheets</code>.</p>
<p>Add the following snippet to your CSS stylesheet:</p>
<pre name="code" class="css">
img {
	behavior: url(/stylesheets/iepngfix.htc);
}
</pre>
<p>And you&#8217;re done! Hit refresh in IE6 and transparent PNG images should render correctly now.</p>
<p>You can add apply this fix to other elements that may be using PNG images as CSS background images as such:</p>
<pre name="code" class="css">
img, #logo {
	behavior: url(/stylesheets/iepngfix.htc);
}
</pre>
<p>where logo is a div that has a background-image that is a transparent PNG.</p>
<p>Note: If you are using v2.0 and want to take advantage of background-repeat and position support, copy <code>iepngfix_tilebg.js</code> to your javascripts folder and include the js file in the HTML files you need it for.</p>
<p>The second way to fix this is to <a href="http://www.stopie6.org/">get everyone off IE6</a> but I guess that&#8217;s just wishful thinking&#8230;</p>

<p><a href="http://feedads.g.doubleclick.net/~a/tejaoSh-jo87qXb5d35ymuHle7o/0/da"><img src="http://feedads.g.doubleclick.net/~a/tejaoSh-jo87qXb5d35ymuHle7o/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/tejaoSh-jo87qXb5d35ymuHle7o/1/da"><img src="http://feedads.g.doubleclick.net/~a/tejaoSh-jo87qXb5d35ymuHle7o/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2008/11/09/2-ways-to-fix-transparent-png-files-in-ie6/feed/</wfw:commentRss>
		</item>
		<item>
		<title>undefined local variable or method `remote_gemspecs’</title>
		<link>http://www.theodorenguyen-cao.com/2008/11/08/undefined-local-variable-or-method-remote_gemspecs/</link>
		<comments>http://www.theodorenguyen-cao.com/2008/11/08/undefined-local-variable-or-method-remote_gemspecs/#comments</comments>
		<pubDate>Sat, 08 Nov 2008 17:50:45 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[geekery]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[tutorials]]></category>

		<category><![CDATA[how-to]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=136</guid>
		<description><![CDATA[I decided I wanted to dedicate some time this weekend working on some side projects. Of course before I start, I needed to get the latest and greatest updates so I ran gem update and got the following error

theo@theo~/dev $ sudo gem update
Updating installed gems
...
Updating rubygems-update
Successfully installed rubygems-update-1.3.1
ERROR:  While executing gem ... (NameError)
  [...]]]></description>
			<content:encoded><![CDATA[<p>I decided I wanted to dedicate some time this weekend working on some side projects. Of course before I start, I needed to get the latest and greatest updates so I ran <code>gem update</code> and got the following error</p>
<pre class="console">
theo@theo~/dev $ sudo gem update
Updating installed gems
...
Updating rubygems-update
Successfully installed rubygems-update-1.3.1
ERROR:  While executing gem ... (NameError)
    undefined local variable or method `remote_gemspecs' for #<Gem::Commands::UpdateCommand:0x12cfb2c>
</pre>
<p>Reading the <a href="http://rubyforge.org/forum/forum.php?forum_id=28071">release notes</a>:</p>
<blockquote><p>NOTE: RubyGems 1.1 and 1.2 have problems upgrading when there is no<br />
rubygems-update installed. You will need to follow the second set of update<br />
instructions if you see &#8220;Nothing to update&#8221;.
</p></blockquote>
<p>shows that we need to install and run the rubygem-update gem to get this fixed</p>
<pre class="console">
  theo@theo~/dev $ sudo gem install rubygems-update
Successfully installed rubygems-update-1.3.1
1 gem installed
  theo@theo~/dev $ sudo update_rubygems
Installing RubyGems 1.3.1
mkdir -p /Library/Ruby/Site/1.8
mkdir -p /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin
install -c -m 0644 rbconfig/datadir.rb /Library/Ruby/Site/1.8/rbconfig/datadir.rb
install -c -m 0644 rubygems/builder.rb /Library/Ruby/Site/1.8/rubygems/builder.rb
install -c -m 0644 rubygems/command.rb /Library/Ruby/Site/1.8/rubygems/command.rb
install -c -m 0644 rubygems/command_manager.rb /Library/Ruby/Site/1.8/rubygems/command_manager.rb
install -c -m 0644 rubygems/commands/build_command.rb /Library/Ruby/Site/1.8/rubygems/commands/build_command.rb
install -c -m 0644 rubygems/commands/cert_command.rb /Library/Ruby/Site/1.8/rubygems/commands/cert_command.rb
install -c -m 0644 rubygems/commands/check_command.rb /Library/Ruby/Site/1.8/rubygems/commands/check_command.rb
install -c -m 0644 rubygems/commands/cleanup_command.rb /Library/Ruby/Site/1.8/rubygems/commands/cleanup_command.rb
install -c -m 0644 rubygems/commands/contents_command.rb /Library/Ruby/Site/1.8/rubygems/commands/contents_command.rb
install -c -m 0644 rubygems/commands/dependency_command.rb /Library/Ruby/Site/1.8/rubygems/commands/dependency_command.rb
install -c -m 0644 rubygems/commands/environment_command.rb /Library/Ruby/Site/1.8/rubygems/commands/environment_command.rb
install -c -m 0644 rubygems/commands/fetch_command.rb /Library/Ruby/Site/1.8/rubygems/commands/fetch_command.rb
install -c -m 0644 rubygems/commands/generate_index_command.rb /Library/Ruby/Site/1.8/rubygems/commands/generate_index_command.rb
install -c -m 0644 rubygems/commands/help_command.rb /Library/Ruby/Site/1.8/rubygems/commands/help_command.rb
install -c -m 0644 rubygems/commands/install_command.rb /Library/Ruby/Site/1.8/rubygems/commands/install_command.rb
install -c -m 0644 rubygems/commands/list_command.rb /Library/Ruby/Site/1.8/rubygems/commands/list_command.rb
install -c -m 0644 rubygems/commands/lock_command.rb /Library/Ruby/Site/1.8/rubygems/commands/lock_command.rb
install -c -m 0644 rubygems/commands/mirror_command.rb /Library/Ruby/Site/1.8/rubygems/commands/mirror_command.rb
install -c -m 0644 rubygems/commands/outdated_command.rb /Library/Ruby/Site/1.8/rubygems/commands/outdated_command.rb
install -c -m 0644 rubygems/commands/pristine_command.rb /Library/Ruby/Site/1.8/rubygems/commands/pristine_command.rb
install -c -m 0644 rubygems/commands/query_command.rb /Library/Ruby/Site/1.8/rubygems/commands/query_command.rb
install -c -m 0644 rubygems/commands/rdoc_command.rb /Library/Ruby/Site/1.8/rubygems/commands/rdoc_command.rb
install -c -m 0644 rubygems/commands/search_command.rb /Library/Ruby/Site/1.8/rubygems/commands/search_command.rb
install -c -m 0644 rubygems/commands/server_command.rb /Library/Ruby/Site/1.8/rubygems/commands/server_command.rb
install -c -m 0644 rubygems/commands/sources_command.rb /Library/Ruby/Site/1.8/rubygems/commands/sources_command.rb
install -c -m 0644 rubygems/commands/specification_command.rb /Library/Ruby/Site/1.8/rubygems/commands/specification_command.rb
install -c -m 0644 rubygems/commands/stale_command.rb /Library/Ruby/Site/1.8/rubygems/commands/stale_command.rb
install -c -m 0644 rubygems/commands/uninstall_command.rb /Library/Ruby/Site/1.8/rubygems/commands/uninstall_command.rb
install -c -m 0644 rubygems/commands/unpack_command.rb /Library/Ruby/Site/1.8/rubygems/commands/unpack_command.rb
install -c -m 0644 rubygems/commands/update_command.rb /Library/Ruby/Site/1.8/rubygems/commands/update_command.rb
install -c -m 0644 rubygems/commands/which_command.rb /Library/Ruby/Site/1.8/rubygems/commands/which_command.rb
install -c -m 0644 rubygems/config_file.rb /Library/Ruby/Site/1.8/rubygems/config_file.rb
install -c -m 0644 rubygems/custom_require.rb /Library/Ruby/Site/1.8/rubygems/custom_require.rb
install -c -m 0644 rubygems/defaults.rb /Library/Ruby/Site/1.8/rubygems/defaults.rb
install -c -m 0644 rubygems/dependency.rb /Library/Ruby/Site/1.8/rubygems/dependency.rb
install -c -m 0644 rubygems/dependency_installer.rb /Library/Ruby/Site/1.8/rubygems/dependency_installer.rb
install -c -m 0644 rubygems/dependency_list.rb /Library/Ruby/Site/1.8/rubygems/dependency_list.rb
install -c -m 0644 rubygems/digest/digest_adapter.rb /Library/Ruby/Site/1.8/rubygems/digest/digest_adapter.rb
install -c -m 0644 rubygems/digest/md5.rb /Library/Ruby/Site/1.8/rubygems/digest/md5.rb
install -c -m 0644 rubygems/digest/sha1.rb /Library/Ruby/Site/1.8/rubygems/digest/sha1.rb
install -c -m 0644 rubygems/digest/sha2.rb /Library/Ruby/Site/1.8/rubygems/digest/sha2.rb
install -c -m 0644 rubygems/doc_manager.rb /Library/Ruby/Site/1.8/rubygems/doc_manager.rb
install -c -m 0644 rubygems/exceptions.rb /Library/Ruby/Site/1.8/rubygems/exceptions.rb
install -c -m 0644 rubygems/ext/builder.rb /Library/Ruby/Site/1.8/rubygems/ext/builder.rb
install -c -m 0644 rubygems/ext/configure_builder.rb /Library/Ruby/Site/1.8/rubygems/ext/configure_builder.rb
install -c -m 0644 rubygems/ext/ext_conf_builder.rb /Library/Ruby/Site/1.8/rubygems/ext/ext_conf_builder.rb
install -c -m 0644 rubygems/ext/rake_builder.rb /Library/Ruby/Site/1.8/rubygems/ext/rake_builder.rb
install -c -m 0644 rubygems/ext.rb /Library/Ruby/Site/1.8/rubygems/ext.rb
install -c -m 0644 rubygems/format.rb /Library/Ruby/Site/1.8/rubygems/format.rb
install -c -m 0644 rubygems/gem_openssl.rb /Library/Ruby/Site/1.8/rubygems/gem_openssl.rb
install -c -m 0644 rubygems/gem_path_searcher.rb /Library/Ruby/Site/1.8/rubygems/gem_path_searcher.rb
install -c -m 0644 rubygems/gem_runner.rb /Library/Ruby/Site/1.8/rubygems/gem_runner.rb
install -c -m 0644 rubygems/indexer.rb /Library/Ruby/Site/1.8/rubygems/indexer.rb
install -c -m 0644 rubygems/install_update_options.rb /Library/Ruby/Site/1.8/rubygems/install_update_options.rb
install -c -m 0644 rubygems/installer.rb /Library/Ruby/Site/1.8/rubygems/installer.rb
install -c -m 0644 rubygems/local_remote_options.rb /Library/Ruby/Site/1.8/rubygems/local_remote_options.rb
install -c -m 0644 rubygems/old_format.rb /Library/Ruby/Site/1.8/rubygems/old_format.rb
install -c -m 0644 rubygems/package/f_sync_dir.rb /Library/Ruby/Site/1.8/rubygems/package/f_sync_dir.rb
install -c -m 0644 rubygems/package/tar_header.rb /Library/Ruby/Site/1.8/rubygems/package/tar_header.rb
install -c -m 0644 rubygems/package/tar_input.rb /Library/Ruby/Site/1.8/rubygems/package/tar_input.rb
install -c -m 0644 rubygems/package/tar_output.rb /Library/Ruby/Site/1.8/rubygems/package/tar_output.rb
install -c -m 0644 rubygems/package/tar_reader/entry.rb /Library/Ruby/Site/1.8/rubygems/package/tar_reader/entry.rb
install -c -m 0644 rubygems/package/tar_reader.rb /Library/Ruby/Site/1.8/rubygems/package/tar_reader.rb
install -c -m 0644 rubygems/package/tar_writer.rb /Library/Ruby/Site/1.8/rubygems/package/tar_writer.rb
install -c -m 0644 rubygems/package.rb /Library/Ruby/Site/1.8/rubygems/package.rb
install -c -m 0644 rubygems/platform.rb /Library/Ruby/Site/1.8/rubygems/platform.rb
install -c -m 0644 rubygems/remote_fetcher.rb /Library/Ruby/Site/1.8/rubygems/remote_fetcher.rb
install -c -m 0644 rubygems/require_paths_builder.rb /Library/Ruby/Site/1.8/rubygems/require_paths_builder.rb
install -c -m 0644 rubygems/requirement.rb /Library/Ruby/Site/1.8/rubygems/requirement.rb
install -c -m 0644 rubygems/rubygems_version.rb /Library/Ruby/Site/1.8/rubygems/rubygems_version.rb
install -c -m 0644 rubygems/security.rb /Library/Ruby/Site/1.8/rubygems/security.rb
install -c -m 0644 rubygems/server.rb /Library/Ruby/Site/1.8/rubygems/server.rb
install -c -m 0644 rubygems/source_index.rb /Library/Ruby/Site/1.8/rubygems/source_index.rb
install -c -m 0644 rubygems/source_info_cache.rb /Library/Ruby/Site/1.8/rubygems/source_info_cache.rb
install -c -m 0644 rubygems/source_info_cache_entry.rb /Library/Ruby/Site/1.8/rubygems/source_info_cache_entry.rb
install -c -m 0644 rubygems/spec_fetcher.rb /Library/Ruby/Site/1.8/rubygems/spec_fetcher.rb
install -c -m 0644 rubygems/specification.rb /Library/Ruby/Site/1.8/rubygems/specification.rb
install -c -m 0644 rubygems/test_utilities.rb /Library/Ruby/Site/1.8/rubygems/test_utilities.rb
install -c -m 0644 rubygems/timer.rb /Library/Ruby/Site/1.8/rubygems/timer.rb
install -c -m 0644 rubygems/uninstaller.rb /Library/Ruby/Site/1.8/rubygems/uninstaller.rb
install -c -m 0644 rubygems/user_interaction.rb /Library/Ruby/Site/1.8/rubygems/user_interaction.rb
install -c -m 0644 rubygems/validator.rb /Library/Ruby/Site/1.8/rubygems/validator.rb
install -c -m 0644 rubygems/version.rb /Library/Ruby/Site/1.8/rubygems/version.rb
install -c -m 0644 rubygems/version_option.rb /Library/Ruby/Site/1.8/rubygems/version_option.rb
install -c -m 0644 rubygems.rb /Library/Ruby/Site/1.8/rubygems.rb
install -c -m 0644 ubygems.rb /Library/Ruby/Site/1.8/ubygems.rb
cp gem /tmp/gem
install -c -m 0755 /tmp/gem /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/gem
rm /tmp/gem
rm -f /Users/theo/.gem/source_cache
rm -f /Library/Ruby/Gems/1.8/source_cache
Removing old RubyGems RDoc and ri
rm -rf /Library/Ruby/Gems/1.8/doc/rubygems-1.2.0
Installing rubygems-1.3.1 ri into /Library/Ruby/Gems/1.8/doc/rubygems-1.3.1/ri
Installing rubygems-1.3.1 rdoc into /Library/Ruby/Gems/1.8/doc/rubygems-1.3.1/rdoc

------------------------------------------------------------------------------

= Announce: RubyGems Release 1.3.0

NOTE:  RubyGems 1.1 and 1.2 have problems upgrading when there is no
rubygems-update installed.  You will need to follow the second set of update
instructions if you see "Nothing to update".

Release 1.3.0 fixes some bugs.

Bugs fixed:

* Disregard ownership of ~ under Windows while creating ~/.gem.  Fixes
  issues related to no uid support under Windows.
* Fix requires for Gem::inflate, Gem::deflate, etc.
* Make Gem.dir respect :gemhome value from config.  (Note: this feature may be
  removed since it is hard to implement on 1.9.)
* Kernel methods are now private.  Patch #20801 by Stefan Rusterholz.
* Gem::location_of_caller now behaves on Windows.  Patch by Daniel Berger.
* Silence PATH warning.

Deprecation Notices:

* Gem::manage_gems will be removed on or after March 2009.

For a full list of changes to RubyGems and the contributor for each change, see
the ChangeLog file.

Special thanks to Chad Wooley for backwards compatibility testing and Luis
Lavena for continuing windows support.

== How can I get RubyGems?

NOTE:  If you have installed RubyGems using a package system you may want to
install a new RubyGems through the same packaging system.

If you have a recent version of RubyGems (0.8.5 or later), then all
you need to do is:

  $ gem update --system   (you might need to be admin/root)

NOTE:  RubyGems 1.1 and 1.2 have problems upgrading when there is no
rubygems-update installed.  You will need to follow the second set of update
instructions if you see "Nothing to update".

NOTE: You may have to run the command twice if you have any previosly
installed rubygems-update gems.

If you have an older version of RubyGems installed, then you can still
do it in two steps:

  $ gem install rubygems-update  (again, might need to be admin/root)
  $ update_rubygems              (... here too)

If you don't have any gems install, there is still the pre-gem
approach to getting software ... doing it manually:

1. DOWNLOAD FROM: http://rubyforge.org/frs/?group_id=126
2. UNPACK INTO A DIRECTORY AND CD THERE
3. INSTALL WITH:  ruby setup.rb  (you may need admin/root privilege)

== To File Bugs

The RubyGems bug tracker can be found on RubyForge at:
http://rubyforge.org/tracker/?func=add&#038;group_id=126&#038;atid=575

When filing a bug, `gem env` output will be helpful in diagnosing the issue.

If you find a bug where RubyGems crashes, please provide debug output. You can
do that with `gem --debug the_command`.

== Thanks

Keep those gems coming!

-- Jim &#038; Chad &#038; Eric (for the RubyGems team)

------------------------------------------------------------------------------

RubyGems installed the following executables:
	/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/gem

If `gem` was installed by a previous RubyGems installation, you may need
to remove it by hand.
</pre>

<p><a href="http://feedads.g.doubleclick.net/~a/L3cMeHo0ywE1-ZVdxVpBCI4H6eQ/0/da"><img src="http://feedads.g.doubleclick.net/~a/L3cMeHo0ywE1-ZVdxVpBCI4H6eQ/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/L3cMeHo0ywE1-ZVdxVpBCI4H6eQ/1/da"><img src="http://feedads.g.doubleclick.net/~a/L3cMeHo0ywE1-ZVdxVpBCI4H6eQ/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2008/11/08/undefined-local-variable-or-method-remote_gemspecs/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Pair Programming &gt; Code Reviews</title>
		<link>http://www.theodorenguyen-cao.com/2008/10/29/pair-programming-greater-than-code-reviews/</link>
		<comments>http://www.theodorenguyen-cao.com/2008/10/29/pair-programming-greater-than-code-reviews/#comments</comments>
		<pubDate>Wed, 29 Oct 2008 04:29:20 +0000</pubDate>
		<dc:creator>Theo</dc:creator>
		
		<category><![CDATA[geekery]]></category>

		<guid isPermaLink="false">http://www.theodorenguyen-cao.com/?p=132</guid>
		<description><![CDATA[With the rise in popularity of agile software methodologies, the practice of formal code reviews has been often put against pair programming.  There are proponents for both and some even recommend practicing both.
As time goes on, I&#8217;ve been able to do a little bit of both and I&#8217;ve developed a strong preference for pair programming [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;">With the rise in popularity of agile software methodologies, the practice of formal <a href="http://en.wikipedia.org/wiki/Code_review" target="_blank">code reviews</a> has been often put against <a href="http://en.wikipedia.org/wiki/Pair_programming" target="_blank">pair programming</a>.  There are proponents for both and some even recommend practicing both.</p>
<p style="text-align: left;">As time goes on, I&#8217;ve been able to do a little bit of both and I&#8217;ve developed a strong preference for pair programming over code reviews.</p>
<p style="text-align: left;">With code reviews, you get one or more other persons to review the code you just wrote and feel ready is to be checked in, deployed, or whatever the next step is.  These reviews can be very formal or just as simple as a line-by-line walk through the code.  The goal is to find any bugs or fixes before the code gets to the next step.  This is very analogous to the writer/editor/publisher workflow (kind of like this blog entry).  Writer writes the article, editor proofreads, and the article gets published.  Programmer writes the code, other developers review the code, and the code gets deployed.  It almost seems like the idea of code reviews came out of software methodologies like the <a href="http://en.wikipedia.org/wiki/Waterfall_model" target="_blank">Waterfall model</a>.  Everything is very sequential and done in distinct stages.</p>
<p style="text-align: left;">In pair programming, the focus is on developing &#8220;good&#8221; code the first time around.  We do this by having more than one pair of eyes on the working code as it is being written.  One person is the &#8220;driver&#8221; who is writing the code and the other is the guide or observer who is verifying the code being written and thinking of potential improvements. The developers switch roles whenever it makes sense which in many cases causes one developer to immediate use or have to work with the code that was written by their partner. It places emphasis on the idea that two heads are better than one.</p>
<p style="text-align: left;">Two things come to my mind when I think about pair programming and code reviews. First, code reviews seem to be a just-in-the-nick-of-time fix for finding bugs in code before it goes out the door.  The initial development effort as already been completed and now we are evaluating the work.  And realistic, this is code we&#8217;re looking at. Everyone has their opinion as how things should be structured, design philosophies, coding styles, etc.  Many times code review sessions end up focusing on higher level concepts like those previously listed and not on the code itself. These kind of debates are related to decisions that should have been made prior to writing this code.  Why are we asking ourselves why we did this this way now after we&#8217;ve already spent time and effort to write code for it? And the people part of the code review are not neccessarily the people that will be working with that piece of code.</p>
<p style="text-align: left;">That brings me to my second thought which is this is all reminiscent of Scrum pigs and chickens.</p>
<p><a href="http://www.theodorenguyen-cao.com/wp-content/uploads/2008/10/060911-scrumtoon.jpg"><img class="aligncenter size-full wp-image-133" title="060911-scrumtoon" src="http://www.theodorenguyen-cao.com/wp-content/uploads/2008/10/060911-scrumtoon.jpg" alt="" width="500" height="176" /></a><br />
In code reviews, people sit down to review someone&#8217;s code.  Everyone has an opinion but not everyone is going to be working with the code on a daily basis. At the time, everyone seems to be involved in the process but there is no vested interest. They are just looking at some code and asking themselves &#8220;does this code look good and is it correct?&#8221;.  It&#8217;s a very passive standpoint. On the other hand, pair programmers are completely invested (committed?) in the task at hand.  They immediately are using the code they are writing together and collobarating their thoughts on design, code layout, etc. Both programmers are taking on an active role and are emotionally invested in the task at hand because they are attacking the same problem together.</p>
<p>Most of the cons of pair programming can be attributed to developer social/ego issues. And they are not specific to pair programming.  Going down the list of drawbacks listed on Wikipedia:</p>
<blockquote>
<ul>
<li> Developer egos: Experienced developers may find it tedious to tutor a less experienced developer in a paired environment.</li>
<li> Developer intimidation: A less experienced developer may feel intimidated pairing with a more experienced developer which may result in less participation.</li>
<li> Developer work preference: Some engineers prefer to work alone, and may find the paired environment cumbersome.</li>
<li> Tutoring cost: Experienced developers working alone may be capable of producing code that is clean and accurate at the outset, and the additional theoretical gain from pairing might not be worth the cost of an additional developer. This is especially true when producing more trivial parts of the system.</li>
<li> Potential conflict: Differences in coding style may result in conflict, and personality conflicts can result in one or both developers feeling awkward or uncomfortable.</li>
<li> Chat sessions: Sometimes employees might talk together too much, straying excessively into off-topic subjects, such as major news events, personal problems, etc.</li>
<li> Annoying personal habits: Sometimes people can find each other much more annoying when working up close than at separate workstations.</li>
</ul>
</blockquote>
<p>Developer egos, intimidation, work preference, and tutoring costs are things that should be checked at the door.  As an experience developer, you should look for opportunities to help your fellow developers to learn and improve their skills.  As a more junior developer, the opportunity to take chances and try to prove yourself is one of the best ways to learn and develop better skills. I don&#8217;t know about other people but collaborative work environments seem to be a plus. Being able to discuss your ideas openly is one of the best ways to make what you&#8217;re building better than it is. As for potential conflicts, chat sessions, and annoying personal habits, these have more to do with personalities and mannerism in the work place. All of this can happen in code reviews as well but the point is being self-aware and respectful of your coworkers is just as important as writing awesome code.</p>
<p>While I&#8217;m not against code reviews, I feel that pair programming is better suited to improve both code and team quality.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/z1Vf6lJwr0cojBQvu5lFCNzCOkM/0/da"><img src="http://feedads.g.doubleclick.net/~a/z1Vf6lJwr0cojBQvu5lFCNzCOkM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/z1Vf6lJwr0cojBQvu5lFCNzCOkM/1/da"><img src="http://feedads.g.doubleclick.net/~a/z1Vf6lJwr0cojBQvu5lFCNzCOkM/1/di" border="0" ismap="true"></img></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.theodorenguyen-cao.com/2008/10/29/pair-programming-greater-than-code-reviews/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
