<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
 
 <title>Recursive Design</title>
 
 <link href="http://recursive-design.com/" />
 <updated>2011-09-14T11:30:06+12:00</updated>
 <id>http://recursive-design.com/</id>
 <author>
   <name>Recursive</name>
   <email>mail@recursive-design.com</email>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/recursive-design/feed" /><feedburner:info uri="recursive-design/feed" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>Hiding ruby gem 'is deprecated with no replacement' messages</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/RxotGRFK6Ps/hiding-ruby-gem-is-deprecated-with-no-replacement-messages" />
   <updated>2011-05-21T00:00:00+12:00</updated>
   <id>http://recursive-design.com/blog/2011/05/21/hiding-ruby-gem-is-deprecated-with-no-replacement-messages</id>
   <content type="html">&lt;time datetime="2011-05-21T00:00:00+12:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;MAY&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;21&lt;/span&gt; &lt;span class="year"&gt;2011&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2011/05/21/hiding-ruby-gem-is-deprecated-with-no-replacement-messages"&gt;Hiding ruby gem &amp;#8216;is deprecated with no replacement&amp;#8217; messages&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/quickie/"&gt;quickie&lt;/a&gt;, &lt;a href="/blog/category/rails/"&gt;rails&lt;/a&gt;, &lt;a href="/blog/category/ruby/"&gt;ruby&lt;/a&gt;, and &lt;a href="/blog/category/rvm/"&gt;rvm&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;I recently installed ruby 1.9.2 via &lt;a href="https://rvm.beginrescueend.com/" class="external" rel="nofollow" target="_blank"&gt;rvm&lt;/a&gt;, and suddenly every command started spitting out hundreds of line of deprecation messages :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;
&lt;span class="no"&gt;NOTE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="c1"&gt;#default_executable= is deprecated with no replacement. It will be removed on or after 2011-10-01.&lt;/span&gt;
&lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="c1"&gt;#default_executable= called from /Users/dave/.rvm/gems/ruby-1.9.2-p0@global/specifications/rubygems-update-1.8.2.gemspec:11.&lt;/span&gt;
&lt;span class="no"&gt;NOTE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="c1"&gt;#default_executable= is deprecated with no replacement. It will be removed on or after 2011-10-01.&lt;/span&gt;
&lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="c1"&gt;#default_executable= called from /Users/dave/.rvm/gems/ruby-1.9.2-p0@rails3/specifications/annotate-models-1.0.4.gemspec:10.&lt;/span&gt;
&lt;span class="no"&gt;NOTE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="c1"&gt;#default_executable= is deprecated with no replacement. It will be removed on or after 2011-10-01.&lt;/span&gt;
&lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="c1"&gt;#default_executable= called from /Users/dave/.rvm/gems/ruby-1.9.2-p0@rails3/specifications/beefcake-0.3.1.gemspec:10.&lt;/span&gt;
&lt;span class="no"&gt;NOTE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="c1"&gt;#default_executable= is deprecated with no replacement. It will be removed on or after 2011-10-01.&lt;/span&gt;
&lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="c1"&gt;#default_executable= called from /Users/dave/.rvm/gems/ruby-1.9.2-p0@rails3/specifications/bundler-1.0.7.gemspec:10.&lt;/span&gt;
&lt;span class="no"&gt;NOTE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="c1"&gt;#default_executable= is deprecated with no replacement. It will be removed on or after 2011-10-01.&lt;/span&gt;
&lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="c1"&gt;#default_executable= called from /Users/dave/.rvm/gems/ruby-1.9.2-p0@rails3/specifications/churn-0.0.12.gemspec:10.&lt;/span&gt;
&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;                        
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Booting&lt;/span&gt; &lt;span class="no"&gt;WEBrick&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="n"&gt;starting&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;development&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="ss"&gt;:/&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Call&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;detach&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Ctrl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;shutdown&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2011&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mo"&gt;05&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;  &lt;span class="no"&gt;WEBrick&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2011&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mo"&gt;05&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;  &lt;span class="n"&gt;ruby&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2010&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x86_64&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;darwin10&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2011&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mo"&gt;05&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;  &lt;span class="no"&gt;WEBrick&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTPServer&lt;/span&gt;&lt;span class="c1"&gt;#start: pid=52918 port=3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;A bit of googling turned up &lt;a href="http://stackoverflow.com/questions/5909108/how-to-avoid-deprecation-messages-from-rubygems" class="external" rel="nofollow" target="_blank"&gt;this stack overflow post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Run the suggested &lt;em&gt;gem pristine&lt;/em&gt; command and restart rails, and voilà:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; gem pristine --all --no-extensions
&amp;gt; rails &lt;span class="nv"&gt;server&lt;/span&gt;             
&lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; Booting &lt;span class="nv"&gt;WEBrick&lt;/span&gt;
&lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; Rails 3.0.7 application starting in development on http://0.0.0.0:3000
&lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; Call with -d to &lt;span class="nv"&gt;detach&lt;/span&gt;
&lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; Ctrl-C to shutdown server
&lt;span class="o"&gt;[&lt;/span&gt;2011-05-21 20:12:23&lt;span class="o"&gt;]&lt;/span&gt; INFO  WEBrick 1.3.1
&lt;span class="o"&gt;[&lt;/span&gt;2011-05-21 20:12:23&lt;span class="o"&gt;]&lt;/span&gt; INFO  ruby 1.9.2 &lt;span class="o"&gt;(&lt;/span&gt;2010-08-18&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;x86_64-darwin10.7.0&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;2011-05-21 20:12:23&lt;span class="o"&gt;]&lt;/span&gt; INFO  WEBrick::HTTPServer#start: &lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;52918 &lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The post above and &lt;a href="http://stackoverflow.com/questions/5909108/how-to-avoid-deprecation-messages-from-rubygems" class="external" rel="nofollow" target="_blank"&gt;this other one&lt;/a&gt; both also recommend this if you&amp;#8217;re using &lt;em&gt;rvm&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; rvm rubygems current
Cannot switch to 1.3.7 &lt;span class="k"&gt;for &lt;/span&gt;this interpreter.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&amp;#8230; which just spat out that error in my case and didn&amp;#8217;t seem to do anything else, but it&amp;#8217;s possible it may work for you if &lt;em&gt;gem pristine&lt;/em&gt; doesn&amp;#8217;t.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/RxotGRFK6Ps" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2011/05/21/hiding-ruby-gem-is-deprecated-with-no-replacement-messages</feedburner:origLink></entry>
 
 <entry>
   <title>'405 Not Allowed' error serving Facebook apps with nginx</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/ci-ITFWIxWs/405-not-allowed-error-serving-facebook-apps-with-nginx" />
   <updated>2011-05-20T00:00:00+12:00</updated>
   <id>http://recursive-design.com/blog/2011/05/20/405-not-allowed-error-serving-facebook-apps-with-nginx</id>
   <content type="html">&lt;time datetime="2011-05-20T00:00:00+12:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;MAY&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;20&lt;/span&gt; &lt;span class="year"&gt;2011&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2011/05/20/405-not-allowed-error-serving-facebook-apps-with-nginx"&gt;&amp;#8216;405 Not Allowed&amp;#8217; error serving Facebook apps with nginx&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/facebook/"&gt;facebook&lt;/a&gt;, &lt;a href="/blog/category/linux/"&gt;linux&lt;/a&gt;, &lt;a href="/blog/category/nginx/"&gt;nginx&lt;/a&gt;, and &lt;a href="/blog/category/programming/"&gt;programming&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;ve spent the last couple of evenings playing around with some &lt;em&gt;Hello World&lt;/em&gt;-type stuff for Facebook app development in preparation for an up-coming Facebook/Rails gig.&lt;/p&gt;
&lt;p&gt;After creating a new app on Facebook, you are presented with the code for a basic starter-page for the app:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&lt;/span&gt;
      &lt;span class="na"&gt;xmlns:fb=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.facebook.com/2008/fbml&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/html; charset=UTF-8&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello World!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;fb:login&lt;/span&gt;&lt;span class="na"&gt;-button&lt;/span&gt; &lt;span class="na"&gt;autologoutlink=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;/fb:login-button&amp;gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;fb:like&amp;gt;&amp;lt;/fb:like&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fb-root&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fbAsyncInit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;FB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;appId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;xxxxxxxxxxxxxxx&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="nx"&gt;xfbml&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;script&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;text/javascript&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
          &lt;span class="s1"&gt;&amp;#39;//connect.facebook.net/en_US/all.js&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;async&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;fb-root&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}());&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;While I&amp;#8217;m not quite sure what all of that does yet, I threw it up on a server as &lt;em&gt;index.html&lt;/em&gt; just for kicks, added a quick subdomain to &lt;em&gt;Nginx&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;server {
    listen       80;
    server_name  facebook.recursive-design.com;

    # Main location
    location / {
         root /var/www/facebook.recursive-design.com;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&amp;#8230;and lo-and-behold we have our &lt;em&gt;Hello World&lt;/em&gt;:&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2011-05-20-405-not-allowed-error-serving-facebook-apps-with-nginx/Hello_World.png" /&gt;&lt;/figure&gt;
&lt;p&gt;While everything is fine-and-dandy so far, accessing this from within Facebook is another story:&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2011-05-20-405-not-allowed-error-serving-facebook-apps-with-nginx/405_Not_Allowed.png" /&gt;&lt;/figure&gt;
&lt;p&gt;After triple-checking the Nginx config (and there&amp;#8217;s not much that could go wrong there) I was none the wiser what was triggering the &lt;em&gt;405 Not Allowed&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A bit of googling turned up a post on the &lt;a href="http://forum.nginx.org/read.php?2,2414,47301" class="external" rel="nofollow" target="_blank"&gt;Nginx forums&lt;/a&gt; that shed some light on the matter:&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2011-05-20-405-not-allowed-error-serving-facebook-apps-with-nginx/Static_Content.png" /&gt;&lt;/figure&gt;
&lt;p&gt;News to me. Since everything that comes from Facebook appears to be a &lt;em&gt;&lt;span class="caps"&gt;POST&lt;/span&gt;&lt;/em&gt;, we&amp;#8217;re not going to get anywhere with this static &lt;em&gt;index.html&lt;/em&gt; app of ours.&lt;/p&gt;
&lt;p&gt;As mentioned in the thread, &lt;a href="http://sysoev.ru/en/" class="external" rel="nofollow" target="_blank"&gt;Igor&lt;/a&gt; has posted a &lt;a href="http://article.gmane.org/gmane.comp.web.nginx.english/1941/match=post+405+static" class="external" rel="nofollow" target="_blank"&gt;workaround&lt;/a&gt;, or alternatively you can proxy the page to apache or something upstream which doesn&amp;#8217;t complain. I went the upstream apache root (though in hindsight the workaround seems like less work), and voilà:&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2011-05-20-405-not-allowed-error-serving-facebook-apps-with-nginx/Success.png" /&gt;&lt;/figure&gt;
&lt;p&gt;I&amp;#8217;d love to know the motivation behind this restriction &amp;#8211; I can&amp;#8217;t think of any security issues that posting to a static file would cause, but then again i&amp;#8217;m no Igor Sysoev :)&lt;/p&gt;
&lt;p&gt;Any ideas?&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/ci-ITFWIxWs" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2011/05/20/405-not-allowed-error-serving-facebook-apps-with-nginx</feedburner:origLink></entry>
 
 <entry>
   <title>Continuous integration for PHP with phpUnderControl</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/KA0RGK5OhUk/continuous-integration-for-php-with-php-under-control" />
   <updated>2011-05-13T00:00:00+12:00</updated>
   <id>http://recursive-design.com/blog/2011/05/13/continuous-integration-for-php-with-php-under-control</id>
   <content type="html">&lt;time datetime="2011-05-13T00:00:00+12:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;MAY&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;13&lt;/span&gt; &lt;span class="year"&gt;2011&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2011/05/13/continuous-integration-for-php-with-php-under-control"&gt;Continuous integration for &lt;span class="caps"&gt;PHP&lt;/span&gt; with phpUnderControl&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/ant/"&gt;ant&lt;/a&gt;, &lt;a href="/blog/category/continuous.integration/"&gt;continuous.integration&lt;/a&gt;, &lt;a href="/blog/category/java/"&gt;java&lt;/a&gt;, &lt;a href="/blog/category/php/"&gt;php&lt;/a&gt;, and &lt;a href="/blog/category/programming/"&gt;programming&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;Whenever I start a new &lt;span class="caps"&gt;PHP&lt;/span&gt; project for a client, one of the first things I set up is usually &lt;a href="http://phpundercontrol.org" class="external" rel="nofollow" target="_blank"&gt;phpUnderControl&lt;/a&gt; &amp;#8211; a CI (&lt;a href="http://en.wikipedia.org/wiki/Continuous_integration" class="external" rel="nofollow" target="_blank"&gt;continuous integration&lt;/a&gt;) server specifically for &lt;span class="caps"&gt;PHP&lt;/span&gt; built on top of &lt;a href="http://cruisecontrol.sourceforge.net/" class="external" rel="nofollow" target="_blank"&gt;CruiseControl&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It provides a bunch of stuff out-of-the box, from the essential (broken-build email alerts) to the nice-to-have (code mess-detection, copy/paste-detection) to the quite frankly bewildering (yes I&amp;#8217;m looking at you, &lt;a href="/images/posts/2011-05-13-continuous-integration-for-php-with-php-under-control/PDepend_Metrics.png"&gt;mystifying code-dependency graph&lt;/a&gt;).&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2011-05-13-continuous-integration-for-php-with-php-under-control/PDepend_Metrics.png" /&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;a href="http://pear.php.net/package/PHP_CodeSniffer/" class="external" rel="nofollow" target="_blank"&gt;&lt;span class="caps"&gt;PHP&lt;/span&gt; CodeSniffer&lt;/a&gt; integration is worth the price of admission by itself, and if nothing else you can impress your non-tech boss with some nice shiny graphs :&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2011-05-13-continuous-integration-for-php-with-php-under-control/Metrics_Tab.png" /&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#8230; and a nice row of green ticks to show that your tests are all passing :&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2011-05-13-continuous-integration-for-php-with-php-under-control/Unit_Tests.png" /&gt;&lt;/figure&gt;
&lt;p&gt;I&amp;#8217;ve installed this on Ubuntu twice in the last month, and finally got sick enough of figuring-it-out-from-scratch to actually write down some reproducible install steps.&lt;/p&gt;
&lt;p&gt;Since &lt;em&gt;CruiseControl&lt;/em&gt; is Java-based, we need to install Java first :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; sudo aptitude install sun-java6-jre sun-java6-jdk
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You&amp;#8217;ll need to agree to some licenses etc while this is installing.&lt;/p&gt;
&lt;p&gt;In more recent versions of Ubuntu (10.4 onwards), these packages have been moved to a partner repository, and are no longer part of the default &lt;em&gt;Lucid&lt;/em&gt; repositories. If this is the case, you will get some errors similar to the following when you try to install them:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;No candidate version found &lt;span class="k"&gt;for &lt;/span&gt;sun-java6-jre
No candidate version found &lt;span class="k"&gt;for &lt;/span&gt;sun-java6-jdk
No candidate version found &lt;span class="k"&gt;for &lt;/span&gt;sun-java6-jre
No candidate version found &lt;span class="k"&gt;for &lt;/span&gt;sun-java6-jdk
No packages will be installed, upgraded, or removed.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If this is the case, you need to add the following line to the end of your &lt;em&gt;/etc/apt/sources.list&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;deb http://archive.canonical.com/ lucid partner
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&amp;#8230; and then update the source list:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; sudo apt-get update
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Next, install some of the required &lt;span class="caps"&gt;PHP&lt;/span&gt; packages&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; sudo aptitude install php5-dev php-pear php5-xdebug
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;em&gt;phpUnderControl&lt;/em&gt; needs the &lt;a href="http://www.xdebug.org/" class="external" rel="nofollow" target="_blank"&gt;Xdebug&lt;/a&gt; &lt;span class="caps"&gt;PHP&lt;/span&gt; extension to work its magic, so make sure that &lt;em&gt;xdebug.ini&lt;/em&gt; is present and contains the appropriate config (it should be somewhere like /etc/php5/conf.d/xdebug.ini) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; more /etc/php5/conf.d/xdebug.ini
&lt;span class="nv"&gt;zend_extension&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/lib/php5/20090626/xdebug.so
xdebug.profiler_enable_trigger &lt;span class="o"&gt;=&lt;/span&gt; onc
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Check the &lt;span class="caps"&gt;PHP&lt;/span&gt; info output to make sure it&amp;#8217;s installed correctly&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; php -i | grep xdebug
/etc/php5/cli/conf.d/xdebug.ini,
xdebug
xdebug &lt;span class="nv"&gt;support&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; enabled
xdebug.auto_trace &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; &lt;span class="nv"&gt;Off&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; Off
...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Next, we need to install &lt;em&gt;CruiseControl&lt;/em&gt; itself. We&amp;#8217;re going to do this in &lt;em&gt;/opt/&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /opt/
&amp;gt; sudo wget http://heanet.dl.sourceforge.net/sourceforge/cruisecontrol/cruisecontrol-bin-2.8.4.zip
&amp;gt; sudo unzip cruisecontrol-bin-2.8.4.zip
&amp;gt; sudo ln -s cruisecontrol-bin-2.8.4 cruisecontrol
&amp;gt; sudo rm cruisecontrol-bin-2.8.4.zip
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;We also need to create a start-up script for &lt;em&gt;CruiseControl&lt;/em&gt;, since it doesn&amp;#8217;t come with one by default. Save the following as &lt;em&gt;/etc/init.d/cruisecontrol&lt;/em&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:
. /lib/lsb/init-functions
&lt;span class="nv"&gt;JAVA_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/lib/jvm/java-6-sun
&lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cruisecontrol
&lt;span class="nv"&gt;DAEMON&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/cruisecontrol/cruisecontrol.sh
&lt;span class="nv"&gt;PIDFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/cruisecontrol/cc.pid
 
&lt;span class="nb"&gt;test&lt;/span&gt; -x &lt;span class="nv"&gt;$DAEMON&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;5
 
&lt;span class="nv"&gt;RUNASUSER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;www-data
&lt;span class="nv"&gt;UGID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;getent passwd &lt;span class="nv"&gt;$RUNASUSER&lt;/span&gt; | cut -f 3,4 -d:&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="nb"&gt; &lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; in
start&lt;span class="o"&gt;)&lt;/span&gt;
log_daemon_msg &lt;span class="s2"&gt;&amp;quot;Starting Cruisecontrol server&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cc&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;quot;$UGID&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;; &lt;span class="k"&gt;then&lt;/span&gt;
log_failure_msg &lt;span class="s2"&gt;&amp;quot;user \&amp;quot;$RUNASUSER\&amp;quot; does not exist&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /opt/cruisecontrol/
./cruisecontrol.sh &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
log_end_msg &lt;span class="nv"&gt;$?&lt;/span&gt;
;;
stop&lt;span class="o"&gt;)&lt;/span&gt;
log_daemon_msg &lt;span class="s2"&gt;&amp;quot;Stopping Cruisecontrol server&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cc&amp;quot;&lt;/span&gt;
start-stop-daemon --stop --quiet --oknodo --pidfile &lt;span class="nv"&gt;$PIDFILE&lt;/span&gt;
log_end_msg &lt;span class="nv"&gt;$?&lt;/span&gt;
rm -f &lt;span class="nv"&gt;$PIDFILE&lt;/span&gt;
;;
restart|force-reload&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$0&lt;/span&gt; stop &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sleep 2 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt; start
;;
status&lt;span class="o"&gt;)&lt;/span&gt;
pidofproc -p &lt;span class="nv"&gt;$PIDFILE&lt;/span&gt; &lt;span class="nv"&gt;$DAEMON&lt;/span&gt; &amp;gt;/dev/null
&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$status&lt;/span&gt; -eq 0 &lt;span class="o"&gt;]&lt;/span&gt;; &lt;span class="k"&gt;then&lt;/span&gt;
log_success_msg &lt;span class="s2"&gt;&amp;quot;Cruisecontrol server is running.&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
log_failure_msg &lt;span class="s2"&gt;&amp;quot;Cruisecontrol server is not running.&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="nv"&gt;$status&lt;/span&gt;
;;
*&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Usage: $0 {start|stop|restart|force-reload|status}&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;exit &lt;/span&gt;2
;;
&lt;span class="k"&gt;esac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;We need to make this script executable :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; sudo chmod a+x /etc/init.d/cruisecontrol
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;We also want &lt;em&gt;CruiseControl&lt;/em&gt; to start up automatically when the server boots up &amp;#8211; use &lt;em&gt;update-rc.d&lt;/em&gt; to do this :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; sudo update-rc.d cruisecontrol defaults
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;I had problems with &lt;em&gt;CruiseControl&lt;/em&gt; not knowing where &lt;em&gt;JAVA_HOME&lt;/em&gt; was for some reason. This probably points to some kind of Java mis-configuration on my end, but since I don&amp;#8217;t use Java for anything else on the build server it&amp;#8217;s easier just to fix it by defining &lt;em&gt;JAVA_HOME&lt;/em&gt; in the &lt;em&gt;CruiseControl&lt;/em&gt; startup script by editing the script itself :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; sudo vi /opt/cruisecontrol/cruisecontrol.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;.. and adding a line after the initial bash line :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nv"&gt;JAVA_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/usr/lib/jvm/java-6-sun&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;At this point, you should be able to start &lt;em&gt;CruiseControl&lt;/em&gt; (keeping in mind we haven&amp;#8217;t installed &lt;em&gt;phpUnderControl&lt;/em&gt; itself yet) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; /etc/init.d/cruisecontrol start
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;After a minute or so (it takes a while to start up), you should be able to see the basic &lt;em&gt;CruiseControl&lt;/em&gt; page at &lt;a href="http://localhost:8080/cruisecontrol/" class="external" rel="nofollow" target="_blank"&gt;http://localhost:8080/cruisecontrol/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The next step is to install &lt;em&gt;phpUnderControl&lt;/em&gt; itself. One of the main dependencies here is &lt;a href="https://github.com/sebastianbergmann/phpunit/" class="external" rel="nofollow" target="_blank"&gt;PHPUnit&lt;/a&gt;, and it is here that I usually hit the first hurdle.&lt;/p&gt;
&lt;p&gt;By default, Ubuntu installs &lt;em&gt;&lt;span class="caps"&gt;PEAR&lt;/span&gt;&lt;/em&gt; version 1.9.0 &amp;#8211; this version doesn&amp;#8217;t support the current version of &lt;em&gt;PHPUnit&lt;/em&gt;, which is required by &lt;em&gt;phpUnderControl&lt;/em&gt;. Depending on your system, you may not need to upgrade anything at this point, but on a fresh Ubuntu system I usually get the following error performing the next steps :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;phpunit/PHPUnit requires PEAR Installer &lt;span class="o"&gt;(&lt;/span&gt;version &amp;gt;&lt;span class="o"&gt;=&lt;/span&gt; 1.9.2&lt;span class="o"&gt;)&lt;/span&gt;, installed version is 1.9.0
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;To avoid this, we want to make sure we have the latest version of &lt;em&gt;&lt;span class="caps"&gt;PEAR&lt;/span&gt;&lt;/em&gt; before we try and install more dependencies :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; sudo pear upgrade pear
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Depending on your setup, you may also need to install a newer version of &lt;em&gt;Xdebug&lt;/em&gt;. You can check the version you have installed with :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; php -i | grep Xdebug   
with Xdebug v2.2.0-dev, Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; 2002-2011, by Derick Rethans
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you have a version less that &lt;em&gt;2.0.5&lt;/em&gt;, you&amp;#8217;re probably going to hit the wall later on in the installation with the error :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;phpunit/PHP_CodeCoverage requires PHP extension &lt;span class="s2"&gt;&amp;quot;xdebug&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;version &amp;gt;&lt;span class="o"&gt;=&lt;/span&gt; 2.0.5&lt;span class="o"&gt;)&lt;/span&gt;, installed version is 2.0.4
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you have a version less than &lt;em&gt;2.0.5&lt;/em&gt;, save yourself some hurt in the next couple of minutes and just go ahead and upgrade it now. Your &lt;span class="caps"&gt;PHP&lt;/span&gt; module directory may differ depending on the Ubuntu version, but should be somewhere under &lt;em&gt;/usr/lib/php5/&lt;/em&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /tmp
&amp;gt; svn co svn://svn.xdebug.org/svn/xdebug/xdebug/trunk xdebug
&amp;gt; &lt;span class="nb"&gt;cd &lt;/span&gt;xdebug
&amp;gt; phpize
&amp;gt; ./configure --enable-xdebug
&amp;gt; make
&amp;gt; sudo mv /usr/lib/php5/20060613+lfs/xdebug.so /usr/lib/php5/20060613+lfs/xdebug.so.orig
&amp;gt; sudo cp modules/xdebug.so /usr/lib/php5/20060613+lfs/
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Now that everything is up-to-date, we want to install some of the &lt;span class="caps"&gt;PHP&lt;/span&gt; dependencies, as well as &lt;em&gt;phpUnderControl&lt;/em&gt; itself.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; sudo pear channel-discover components.ez.no
&amp;gt; sudo pear install -a ezc/Graph
&amp;gt; sudo pear config-set preferred_state beta
&amp;gt; sudo pear channel-discover pear.phpunit.de
&amp;gt; sudo pear channel-discover pear.symfony-project.com
&amp;gt; sudo pear channel-discover pear.phpundercontrol.org
&amp;gt; sudo pear install --alldeps --force phpuc/phpUnderControl-beta
&amp;gt; sudo pear channel-discover pear.pdepend.org
&amp;gt; sudo pear install channel://pear.pdepend.org/PHP_Depend-0.9.11
&amp;gt; sudo pear channel-discover pear.phpmd.org
&amp;gt; sudo pear install channel://pear.phpmd.org/PHP_PMD-0.2.4
&amp;gt; sudo pear install --alldeps phpunit/phpcpd 
&amp;gt; sudo pear channel-discover pear.phing.info
&amp;gt; sudo pear config-set preferred_state alpha
&amp;gt; sudo pear install --alldeps --force phing/phing
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If everything installed correctly, we should now be able to apply the &lt;em&gt;phpUnderControl&lt;/em&gt; patches to &lt;em&gt;CruiseControl&lt;/em&gt;, which will give us our nice shiny &lt;span class="caps"&gt;PHP&lt;/span&gt;-tailored interface :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; sudo phpuc install /opt/cruisecontrol 
&amp;gt; sudo /etc/init.d/cruisecontrol restart
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Next we want to remove the example project that ships with &lt;em&gt;CruiseControl&lt;/em&gt;, and add our actual &lt;span class="caps"&gt;PHP&lt;/span&gt; project. We&amp;#8217;re going to call our new project &lt;em&gt;php-example&lt;/em&gt; , and assume we&amp;#8217;re checking it out from &lt;em&gt;subversion&lt;/em&gt; (although &lt;em&gt;git&lt;/em&gt; is do-able too) &amp;#8211; you&amp;#8217;ll need to adjust the following instructions to fit your own project and checkout procedure.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /opt/cruisecontrol/projects
&amp;gt; sudo rm -Rf connectfour/
&amp;gt; sudo mkdir -p php-example/build/api
&amp;gt; sudo mkdir php-example/build/charts
&amp;gt; sudo mkdir php-example/build/coverage
&amp;gt; sudo mkdir php-example/build/graph
&amp;gt; sudo mkdir php-example/build/logs
&amp;gt; sudo svn co svn://path/to/php-example/trunk php-example/source
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;At this point you also want to set up your newly checked-out project so that database connections work, unit tests pass etc. Creating a &lt;em&gt;PHPUnit&lt;/em&gt; test suite is beyond the scope of this article, but if you don&amp;#8217;t have any tests yet, grab the documentation from the &lt;a href="https://github.com/sebastianbergmann/phpunit/" class="external" rel="nofollow" target="_blank"&gt;PHPUnit page&lt;/a&gt;, write and commit a couple of simple tests, then come back here afterwards &amp;#8211; we&amp;#8217;ll wait for you!&lt;/p&gt;
&lt;p&gt;After you are confident that your unit tests are running correctly, your new project will need a &lt;em&gt;build.xml&lt;/em&gt; file to tell &lt;em&gt;CruiseControl&lt;/em&gt; how to build it. Make an &lt;em&gt;/opt/cruisecontrol/projects/php-example/build.xml&lt;/em&gt; file similar to the one below (and make sure you add it to version control too). &lt;em&gt;phpUnderControl&lt;/em&gt; will use this file to perform the build process for your project.&lt;/p&gt;
&lt;p&gt;Obviously you&amp;#8217;ll need to customize this to fit the needs of your own project &amp;#8211; make note of the entries with &lt;em&gt;path-to-ignore&lt;/em&gt; and &lt;em&gt;path-to-check&lt;/em&gt; and adjust them according to your own needs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;lt;?xml &lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;?&amp;gt;
&amp;lt;project &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;php-example&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;build&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;basedir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&amp;gt;

  &amp;lt;!--
  Helper target that initializes the CruiseControl project and creates the base 
  directory structure. 
  --&amp;gt;
  &amp;lt;target &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;init&amp;quot;&lt;/span&gt;&amp;gt;
    &amp;lt;!-- Create the &lt;span class="nb"&gt;source &lt;/span&gt;directory --&amp;gt;
    &amp;lt;mkdir &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;source&amp;quot;&lt;/span&gt; /&amp;gt;
    
    &amp;lt;!-- Create the different build directories --&amp;gt;
    &amp;lt;mkdir &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;build&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;mkdir &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;build/api&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;mkdir &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;build/charts&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;mkdir &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;build/coverage&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;mkdir &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;build/graph&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;mkdir &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;build/logs&amp;quot;&lt;/span&gt; /&amp;gt;
    
    &amp;lt;!-- Checkout phpUnderControl trunk into &lt;span class="nb"&gt;source&lt;/span&gt; --&amp;gt;
    &amp;lt;&lt;span class="nb"&gt;exec &lt;/span&gt;&lt;span class="nv"&gt;executable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;svn&amp;quot;&lt;/span&gt;&amp;gt;
      &amp;lt;arg &lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;co /path/to/php-example/trunk source&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;/exec&amp;gt;
  &amp;lt;/target&amp;gt;
    
  &amp;lt;!--
  The clean target is used to remove build artefacts of previous builds. Otherwise
  CruiseControl will present old, maybe successful results, even &lt;span class="k"&gt;if &lt;/span&gt;your build 
  process fails.
  --&amp;gt;
  &amp;lt;target &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;clean&amp;quot;&lt;/span&gt;&amp;gt;
  	&amp;lt;!-- Remove old log files --&amp;gt;
    &amp;lt;delete&amp;gt;
      &amp;lt;fileset &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${basedir}/build/logs&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;includes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;**.*&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;/delete&amp;gt;
  	&amp;lt;!-- Remove old api documentation --&amp;gt;
    &amp;lt;delete&amp;gt;
      &amp;lt;fileset &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${basedir}/build/api&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;includes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;**.*&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;/delete&amp;gt;
  	&amp;lt;!-- Remove old coverage report --&amp;gt;
    &amp;lt;delete&amp;gt;
      &amp;lt;fileset &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${basedir}/build/coverage&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;includes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;**.*&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;/delete&amp;gt;
        &amp;lt;!-- Remove old graphs --&amp;gt;
    &amp;lt;delete&amp;gt;
      &amp;lt;fileset &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${basedir}/build/graph&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;includes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;**.*&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;/delete&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;!--
  The default build target &lt;span class="k"&gt;for &lt;/span&gt;this project. It simply depends on all sub tasks
  that perform the project build. The sub targets are executed in the listed 
  order.
  
  1. &lt;span class="s1"&gt;&amp;#39;clean&amp;#39;&lt;/span&gt; Clean old project build artefacts
  2. &lt;span class="s1"&gt;&amp;#39;checkout&amp;#39;&lt;/span&gt; Update project working copy
  3. &lt;span class="s1"&gt;&amp;#39;php-documentor&amp;#39;&lt;/span&gt; Generate api documentation
  4. &lt;span class="s1"&gt;&amp;#39;php-codesniffer&amp;#39;&lt;/span&gt; Check &lt;span class="k"&gt;for &lt;/span&gt;coding violations.
  4. &lt;span class="s1"&gt;&amp;#39;pdepend&amp;#39;&lt;/span&gt; Code dependency information.
  4. &lt;span class="s1"&gt;&amp;#39;phpcpd&amp;#39;&lt;/span&gt; Copy-paste detection.
  4. &lt;span class="s1"&gt;&amp;#39;phpcpd&amp;#39;&lt;/span&gt; Mess detection.
  5. &lt;span class="s1"&gt;&amp;#39;phpunit&amp;#39;&lt;/span&gt; Execute unit tests, generate metrics, coverage etc. 
  --&amp;gt;
  &amp;lt;target &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;build&amp;quot;&lt;/span&gt; 
          &lt;span class="nv"&gt;depends&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;clean,checkout,php-documentor,php-codesniffer,pdepend,phpcpd,phpmd,phpunit&amp;quot;&lt;/span&gt; /&amp;gt;

  &amp;lt;!--
  Performs an &lt;span class="s1"&gt;&amp;#39;svn up&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;the working copy.
  --&amp;gt;
  &amp;lt;target &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;checkout&amp;quot;&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span class="nb"&gt;exec &lt;/span&gt;&lt;span class="nv"&gt;executable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;svn&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${basedir}/source&amp;quot;&lt;/span&gt;&amp;gt;
      &amp;lt;arg &lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;up&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;/exec&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;!--
  Generates the project documentation into the &amp;lt;project&amp;gt;/build/api directory.
  phpUnderControl uses the &lt;span class="nb"&gt;command &lt;/span&gt;line output of PhpDocumentor that is logged
  by CruiseControl.
  --&amp;gt;
  &amp;lt;target &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;php-documentor&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;depends&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;init&amp;quot;&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span class="nb"&gt;exec &lt;/span&gt;&lt;span class="nv"&gt;executable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;phpdoc&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${basedir}/source&amp;quot;&lt;/span&gt;&amp;gt;
      &amp;lt;arg &lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-ct type -ue on -t ${basedir}/build/api &lt;/span&gt;
&lt;span class="s2"&gt;                 -tb /usr/share/php/data/phpUnderControl/data/phpdoc/ -o HTML:Phpuc:phpuc&lt;/span&gt;
&lt;span class="s2"&gt;                 -d ${basedir}/source&lt;/span&gt;
&lt;span class="s2"&gt;                 -q&lt;/span&gt;
&lt;span class="s2"&gt;    	           -i paths-to-ignore1,paths-to-ignore2&amp;quot;&lt;/span&gt;/&amp;gt;
    &amp;lt;/exec&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;!--
  Execute code sniffer. You can use a different coding standard &lt;span class="k"&gt;if&lt;/span&gt;
&lt;span class="k"&gt;  &lt;/span&gt;you want &lt;span class="o"&gt;(&lt;/span&gt;--standard&lt;span class="o"&gt;=&lt;/span&gt;Squiz&lt;span class="o"&gt;)&lt;/span&gt; - check the php-codesniffer docs
  &lt;span class="k"&gt;for &lt;/span&gt;more information.
  --&amp;gt;
  &amp;lt;target &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;php-codesniffer&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;depends&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;init&amp;quot;&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span class="nb"&gt;exec &lt;/span&gt;&lt;span class="nv"&gt;executable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;phpcs&amp;quot;&lt;/span&gt; 
          &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${basedir}/source&amp;quot;&lt;/span&gt; 
          &lt;span class="nv"&gt;error&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/dev/null&amp;quot;&lt;/span&gt;
          &lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${basedir}/build/logs/checkstyle.xml&amp;quot;&lt;/span&gt;&amp;gt;
      &amp;lt;arg &lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--report=checkstyle &lt;/span&gt;
&lt;span class="s2"&gt;                 --standard=Squiz &lt;/span&gt;
&lt;span class="s2"&gt;                 --extensions=php &lt;/span&gt;
&lt;span class="s2"&gt;                 --tab-width=4 &lt;/span&gt;
&lt;span class="s2"&gt;                 -n&lt;/span&gt;
&lt;span class="s2"&gt;                 --ignore=path-to-ignore1,path-to-ignore2&lt;/span&gt;
&lt;span class="s2"&gt;                 ./path-to-check1 ./path-to-check2&amp;quot;&lt;/span&gt;/&amp;gt;
    &amp;lt;/exec&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;!--
  Calculates dependencies and adds new graphs to the metrics page.
  --&amp;gt;
  &amp;lt;target &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;pdepend&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;depends&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;init&amp;quot;&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span class="nb"&gt;exec &lt;/span&gt;&lt;span class="nv"&gt;executable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;pdepend&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${basedir}/source&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;logerror&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;on&amp;quot;&lt;/span&gt;&amp;gt;
      &amp;lt;arg &lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--summary-xml=${basedir}/build/logs/pdepend.xml&lt;/span&gt;
&lt;span class="s2"&gt;                 --jdepend-chart=${basedir}/build/charts/jdepend.svg&lt;/span&gt;
&lt;span class="s2"&gt;                 --overview-pyramid=${basedir}/build/charts/overview-pyramid.svg&lt;/span&gt;
&lt;span class="s2"&gt;                 --coderank-mode=inheritance,property,method&lt;/span&gt;
&lt;span class="s2"&gt;                 ./path-to-check1,/path-to-check2&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;/exec&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;!--
  Copy-paste detection.
  --&amp;gt;
  &amp;lt;target &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;phpcpd&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;depends&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;init&amp;quot;&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span class="nb"&gt;exec &lt;/span&gt;&lt;span class="nv"&gt;executable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;phpcpd&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;failonerror&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&amp;gt;
      &amp;lt;arg &lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--log-pmd ${basedir}/build/logs/pmd-cpd.xml &lt;/span&gt;
&lt;span class="s2"&gt;                 --exclude ${basedir}/path-to-ignore1&lt;/span&gt;
&lt;span class="s2"&gt;                 --exclude ${basedir}/path-to-ignore2&lt;/span&gt;
&lt;span class="s2"&gt;                 ${basedir}/path-to-check1 ${basedir}/path-to-check2&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;/exec&amp;gt;
  &amp;lt;/target&amp;gt;


  &amp;lt;!--
  Checks that the project &lt;span class="nb"&gt;source &lt;/span&gt;does not contain any &lt;span class="s1"&gt;&amp;#39;mess&amp;#39;&lt;/span&gt;.
  --&amp;gt;
  &amp;lt;target &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;phpmd&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;depends&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;init&amp;quot;&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span class="nb"&gt;exec &lt;/span&gt;&lt;span class="nv"&gt;executable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;phpmd&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;failonerror&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&amp;gt;
      &amp;lt;arg &lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${basedir}/source&lt;/span&gt;
&lt;span class="s2"&gt;                 xml&lt;/span&gt;
&lt;span class="s2"&gt;                 codesize,unusedcode,naming&lt;/span&gt;
&lt;span class="s2"&gt;                 --reportfile ${basedir}/build/logs/pmd.xml&lt;/span&gt;
&lt;span class="s2"&gt;                 --exclude path-to-ignore1,path-to-ignore2&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;/exec&amp;gt;
  &amp;lt;/target&amp;gt;
  
  &amp;lt;!--
  Executes the project unit tests and stores the different logs in the 
  &amp;lt;project&amp;gt;/build/logs directory. Furthermore it generates the coverage report
  under &amp;lt;project&amp;gt;/build/coverage.
  --&amp;gt;
  &amp;lt;target &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;phpunit&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;depends&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;init&amp;quot;&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span class="nb"&gt;exec &lt;/span&gt;&lt;span class="nv"&gt;executable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;phpunit&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${basedir}/source&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;failonerror&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;on&amp;quot;&lt;/span&gt;&amp;gt;
      &amp;lt;arg &lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--log-junit       ${basedir}/build/logs/phpunit.xml &lt;/span&gt;
&lt;span class="s2"&gt;                 --coverage-clover ${basedir}/build/logs/phpunit.coverage.xml &lt;/span&gt;
&lt;span class="s2"&gt;                 --coverage-html   ${basedir}/build/coverage&lt;/span&gt;
&lt;span class="s2"&gt;                 --configuration   ${basedir}/tests/phpunit.xml&lt;/span&gt;
&lt;span class="s2"&gt;                 ${basedir}/path-to-check&amp;quot;&lt;/span&gt;/&amp;gt;
    &amp;lt;/exec&amp;gt;
  &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Now that our project has a &lt;em&gt;build.xml&lt;/em&gt; file, we need to tell &lt;em&gt;CruiseControl&lt;/em&gt; where it is. Edit the main config file ( &lt;em&gt;/opt/cruisecontrol/config.xml&lt;/em&gt; ) and enter something similar to the following :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;lt;?xml &lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt;?&amp;gt;
&amp;lt;cruisecontrol&amp;gt;

  &amp;lt;project &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;php-example&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;buildafterfailed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&amp;gt;
    &amp;lt;plugin &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;svnbootstrapper&amp;quot;&lt;/span&gt; 
            &lt;span class="nv"&gt;classname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;net.sourceforge.cruisecontrol.bootstrappers.SVNBootstrapper&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;plugin &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;svn&amp;quot;&lt;/span&gt; 
            &lt;span class="nv"&gt;classname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;net.sourceforge.cruisecontrol.sourcecontrols.SVN&amp;quot;&lt;/span&gt; /&amp;gt;

    &amp;lt;listeners&amp;gt;
      &amp;lt;currentbuildstatuslistener &lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;logs/${project.name}/status.txt&amp;quot;&lt;/span&gt;/&amp;gt;
    &amp;lt;/listeners&amp;gt;

    &amp;lt;modificationset&amp;gt;
      &amp;lt;svn &lt;span class="nv"&gt;localWorkingCopy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;projects/${project.name}/source/&amp;quot;&lt;/span&gt;/&amp;gt;
    &amp;lt;/modificationset&amp;gt;

    &amp;lt;bootstrappers&amp;gt;
      &amp;lt;svnbootstrapper &lt;span class="nv"&gt;localWorkingCopy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;projects/${project.name}/source/&amp;quot;&lt;/span&gt; /&amp;gt;
    &amp;lt;/bootstrappers&amp;gt;

    &amp;lt;schedule &lt;span class="nv"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;60&amp;quot;&lt;/span&gt;&amp;gt;
      &amp;lt;ant &lt;span class="nv"&gt;anthome&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;apache-ant-1.7.0&amp;quot;&lt;/span&gt; 
           &lt;span class="nv"&gt;buildfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;projects/${project.name}/build.xml&amp;quot;&lt;/span&gt;/&amp;gt;
    &amp;lt;/schedule&amp;gt;

    &amp;lt;log &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;logs/${project.name}&amp;quot;&lt;/span&gt;&amp;gt;
      &amp;lt;merge &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;projects/${project.name}/build/logs/&amp;quot;&lt;/span&gt;/&amp;gt;
    &amp;lt;/log&amp;gt;

    &amp;lt;publishers&amp;gt;
      &amp;lt;!--
      Copies the generated api documentation into project artifacts directory.  
      --&amp;gt;
      &amp;lt;artifactspublisher &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;projects/${project.name}/build/api&amp;quot;&lt;/span&gt; 
                          &lt;span class="nv"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;artifacts/${project.name}&amp;quot;&lt;/span&gt;                          &lt;span class="nv"&gt;subdirectory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;api&amp;quot;&lt;/span&gt;/&amp;gt;
      &amp;lt;!--
      Copies the generated code coverage report into project artifacts directory.  
      --&amp;gt;
      &amp;lt;artifactspublisher &lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;projects/${project.name}/build/coverage&amp;quot;&lt;/span&gt; 
                          &lt;span class="nv"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;artifacts/${project.name}&amp;quot;&lt;/span&gt; 
                          &lt;span class="nv"&gt;subdirectory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;coverage&amp;quot;&lt;/span&gt;/&amp;gt;
                          
      &amp;lt;!--
      Generates the different metric charts with the phpUnderControl ezcGraph
      extension. 
      --&amp;gt;
      &amp;lt;execute &lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;phpuc graph logs/${project.name} artifacts/${project.name}&amp;quot;&lt;/span&gt;/&amp;gt;
      
      &amp;lt;!--
      Sends simple text emails after a project build. For nicer html emails, 
      checkout the original CruiseControl documentation.
    
        * http://cruisecontrol.sourceforge.net/main/configxml.html#email
        * http://cruisecontrol.sourceforge.net/main/configxml.html#htmlemail 
      --&amp;gt;
      &amp;lt;email &lt;span class="nv"&gt;mailhost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;smtp.localhost&amp;quot;&lt;/span&gt;
             &lt;span class="nv"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;username&amp;quot;&lt;/span&gt;
             &lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;password&amp;quot;&lt;/span&gt;
             &lt;span class="nv"&gt;returnaddress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;build@php-example.com&amp;quot;&lt;/span&gt;
             &lt;span class="nv"&gt;buildresultsurl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://build.php-example.com/buildresults/${project.name}&amp;quot;&lt;/span&gt;
             &lt;span class="nv"&gt;skipusers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;true&amp;quot;&lt;/span&gt; 
             &lt;span class="nv"&gt;spamwhilebroken&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&amp;gt;
        &amp;lt;always &lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;build@php-example.com&amp;quot;&lt;/span&gt;/&amp;gt;
        &amp;lt;failure &lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;build@php-example.com&amp;quot;&lt;/span&gt;/&amp;gt;
      &amp;lt;/email&amp;gt;
    &amp;lt;/publishers&amp;gt;

  &amp;lt;/project&amp;gt;
  
&amp;lt;/cruisecontrol&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Note that the project name you enter (&lt;em&gt;php-example&lt;/em&gt;) &lt;strong&gt;must&lt;/strong&gt; match the name of the folder you checked your source files out to earlier.&lt;/p&gt;
&lt;p&gt;Finally, restart &lt;em&gt;CruiseControl&lt;/em&gt; and your build server should be ready to go!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; sudo /etc/init.d/cruisecontrol restart
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;Using &lt;em&gt;phpUnderControl&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;You should now be able to view &lt;em&gt;phpUnderControl&lt;/em&gt; at &lt;a href="http://localhost:8080/cruisecontrol/" class="external" rel="nofollow" target="_blank"&gt;http://localhost:8080/cruisecontrol/&lt;/a&gt; :&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2011-05-13-continuous-integration-for-php-with-php-under-control/Main_Screen.png" /&gt;&lt;/figure&gt;
&lt;p&gt;If you add other projects in &lt;em&gt;/opt/cruisecontrol/config.xml&lt;/em&gt; , they will show up on this screen as well. Click the green tick button to force a build, or click the project name to view the build results for that project.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;CruiseControl&lt;/em&gt; will check subversion for updates every minute or so and perform a build automatically if it finds any, so you shouldn&amp;#8217;t need to force a build too often. If you entered your email details in &lt;em&gt;config.xml&lt;/em&gt; , you should also get an email if the build fails for any reason.&lt;/p&gt;
&lt;h3&gt;Null pointer exceptions viewing the &lt;em&gt;metrics&lt;/em&gt; page&lt;/h3&gt;
&lt;p&gt;With more recent versions of &lt;em&gt;phpUnderControl&lt;/em&gt; , I&amp;#8217;ve been getting a &lt;em&gt;java.lang.NullPointerException&lt;/em&gt; whenever i try and access the &lt;em&gt;metrics&lt;/em&gt; page :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NullPointerException&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sourceforge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cruisecontrol&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PieChartData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;produceDataset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PieChartData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;laures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cewolf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;taglib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DataContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDataset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DataContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;laures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cewolf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;taglib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SimpleChartDefinition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDataset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SimpleChartDefinition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;laures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cewolf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;taglib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SimpleChartDefinition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;produceChart&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SimpleChartDefinition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;laures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cewolf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;taglib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AbstractChartDefinition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getChart&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbstractChartDefinition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;laures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cewolf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;taglib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ChartImageDefinition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ensureRendered&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ChartImageDefinition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;131&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;laures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cewolf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;taglib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ChartImageDefinition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ChartImageDefinition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;125&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;laures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cewolf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SerializableChartImage&lt;/span&gt;&lt;span class="o"&gt;.(&lt;/span&gt;&lt;span class="n"&gt;SerializableChartImage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;laures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cewolf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SessionStorage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;storeChartImage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SessionStorage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;57&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;laures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cewolf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SessionStorage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;storeChartImage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SessionStorage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;laures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cewolf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;taglib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ChartImgTag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doStartTag&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ChartImgTag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;74&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;main_jsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;_jspx_meth_cewolf_img_0&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;main_jsp&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1781&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;main_jsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;_jspService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;main_jsp&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;695&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jasper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HttpJspBase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpJspBase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;93&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;javax&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;servlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HttpServlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpServlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;820&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jasper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;servlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JspServletWrapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JspServletWrapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;373&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jasper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;servlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JspServlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;serviceJspFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JspServlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;470&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jasper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;servlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JspServlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JspServlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;364&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;javax&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;servlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HttpServlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpServlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;820&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;servlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ServletHolder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ServletHolder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;487&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;servlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ServletHandler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ServletHandler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;362&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;security&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SecurityHandler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SecurityHandler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;216&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;servlet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SessionHandler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SessionHandler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;181&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ContextHandler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ContextHandler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;729&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;webapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;WebAppContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WebAppContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;405&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ContextHandlerCollection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ContextHandlerCollection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;206&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HandlerCollection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HandlerCollection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;114&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HandlerWrapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HandlerWrapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;152&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;324&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HttpConnection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handleRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpConnection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;505&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HttpConnection&lt;/span&gt;&lt;span class="n"&gt;$RequestHandler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;headerComplete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpConnection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;829&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HttpParser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parseNext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpParser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;513&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HttpParser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parseAvailable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpParser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;211&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jetty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HttpConnection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpConnection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;380&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SelectChannelEndPoint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SelectChannelEndPoint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;395&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mortbay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;QueuedThreadPool&lt;/span&gt;&lt;span class="n"&gt;$PoolThread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QueuedThreadPool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;488&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;It took me hours to get to the bottom of this because while it &lt;strong&gt;looks&lt;/strong&gt; like a java problem, the actual problem is in &lt;span class="caps"&gt;PHP&lt;/span&gt;. The &lt;em&gt;ClassComplexityInput.php&lt;/em&gt; class (used for generating the complexity graph) has an undefined constant or something in it (I forget the exact cause), which causes the graph not to be rendered, which in turn causes &lt;em&gt;CruiseControl&lt;/em&gt; to fall over when it tries to render the &lt;em&gt;metrics&lt;/em&gt; page.&lt;/p&gt;
&lt;p&gt;The quick-and-dirty solution to this is simply to move the file somewhere else :)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /usr/share/php/phpUnderControl/Graph/Input/
&amp;gt; sudo mv ClassComplexityInput.php ClassComplexityInput.php.bak
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You lose the code dependency graph by doing this, but until I have some time to dig a bit deeper and put a patch together it&amp;#8217;s good enough for me.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/KA0RGK5OhUk" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2011/05/13/continuous-integration-for-php-with-php-under-control</feedburner:origLink></entry>
 
 <entry>
   <title>Weekend Project - Time Out In NZ</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/y2to13GgyVM/time-out-in-nz" />
   <updated>2011-05-04T00:00:00+12:00</updated>
   <id>http://recursive-design.com/blog/2011/05/04/time-out-in-nz</id>
   <content type="html">&lt;time datetime="2011-05-04T00:00:00+12:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;MAY&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;04&lt;/span&gt; &lt;span class="year"&gt;2011&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2011/05/04/time-out-in-nz"&gt;Weekend Project &amp;#8211; Time Out In NZ&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/announcement/"&gt;announcement&lt;/a&gt;, &lt;a href="/blog/category/programming/"&gt;programming&lt;/a&gt;, &lt;a href="/blog/category/rails/"&gt;rails&lt;/a&gt;, and &lt;a href="/blog/category/ruby/"&gt;ruby&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;ve been flat out with a couple of contracting projects recently &amp;#8211; apologies for the four-month blogging hiatus!&lt;/p&gt;
&lt;p&gt;One of these projects (albeit a quickie) was a weekend spent making a rails site for a couple of New Zealand organizations to help the victims of the Japanese quakes and tsunami relocate themselves and/or their children to New Zealand temporarily.&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2011-05-04-time-out-in-nz/Time_Out_In_NZ.png" /&gt;&lt;/figure&gt;
&lt;p&gt;There&amp;#8217;s &lt;a href="http://timeoutinnz.org.nz/en/supporters" class="external" rel="nofollow" target="_blank"&gt;quite a few&lt;/a&gt; big names backing it (both in New Zealand and Japan), and when we were approached about doing the site it seemed like the perfect opportunity to give something back to the people of Japan, who&amp;#8217;ve been kind enough to give me visas and keep us employed for the past seven years :)&lt;/p&gt;
&lt;p&gt;It was built on top of &lt;a href="http://railskitchensink.com" class="external" rel="nofollow" target="_blank"&gt;Rails Kitchen Sink&lt;/a&gt; (shameless plug) and took most of a weekend to get the main functionality in, with a few more evenings of tweaking as requirements solidified a little.&lt;/p&gt;
&lt;p&gt;The good folks at &lt;a href="http://www.heroku.com" class="external" rel="nofollow" target="_blank"&gt;Heroku&lt;/a&gt; were kind enough to provide 6 months free hosting (with extra dynos on top of the free plan), so the whole initiative has only cost a few hours of my time, plus a few hours for Toshi at &lt;a href="http://www.second-drip.com" class="external" rel="nofollow" target="_blank"&gt;Second Drip&lt;/a&gt; who was kind enough to do the Japanese translation.&lt;/p&gt;
&lt;p&gt;If any of you are in New Zealand, feel free to &lt;a href="http://timeoutinnz.org.nz/en/accommodation/download-form" class="external" rel="nofollow" target="_blank"&gt;sign up&lt;/a&gt; and help out!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/y2to13GgyVM" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2011/05/04/time-out-in-nz</feedburner:origLink></entry>
 
 <entry>
   <title>Simple video remixes using The Echo Nest API</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/75l5GYWTvt8/simple-video-remixes-using-the-echo-nest-api" />
   <updated>2011-01-05T00:00:00+13:00</updated>
   <id>http://recursive-design.com/blog/2011/01/05/simple-video-remixes-using-the-echo-nest-api</id>
   <content type="html">&lt;time datetime="2011-01-05T00:00:00+13:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;JAN&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;05&lt;/span&gt; &lt;span class="year"&gt;2011&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2011/01/05/simple-video-remixes-using-the-echo-nest-api"&gt;Simple video remixes using The Echo Nest &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/api/"&gt;api&lt;/a&gt;, &lt;a href="/blog/category/echonest/"&gt;echonest&lt;/a&gt;, &lt;a href="/blog/category/music/"&gt;music&lt;/a&gt;, and &lt;a href="/blog/category/programming/"&gt;programming&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;Here&amp;#8217;s a couple of remix videos I did earlier in the year using &lt;a href="http://developer.echonest.com/" class="external" rel="nofollow" target="_blank"&gt;The Echo Nest &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been meaning to post these for a while, but finally decided to get off my ass and put them up since the folks at Echo Nest were kind enough to &lt;a href="/blog/2011/01/05/a-christmas-present-from-the-echo-nest"&gt;send me a T-shirt&lt;/a&gt; :&lt;/p&gt;
&lt;p&gt;&lt;iframe class="framed" src="http://player.vimeo.com/video/12043016" width="600" height="450" frameborder="0"&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt;(&lt;a href="http://www.youtube.com/watch?v=PHU-AJTn0I8" class="external" rel="nofollow" target="_blank"&gt;source video one&lt;/a&gt;)&lt;br /&gt;
(&lt;a href="http://www.youtube.com/watch?v=ET6ud7GiMFg" class="external" rel="nofollow" target="_blank"&gt;source video two&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;iframe class="framed" src="http://player.vimeo.com/video/12042971" width="600" height="450" frameborder="0"&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt;(&lt;a href="http://www.youtube.com/watch?v=oKF-meCkEXE" class="external" rel="nofollow" target="_blank"&gt;source video one&lt;/a&gt;)&lt;br /&gt;
(&lt;a href="http://www.youtube.com/watch?v=s1I73BerjUY" class="external" rel="nofollow" target="_blank"&gt;source video two&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s pretty straightforward to create these.&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;a href="http://developer.echonest.com/account/register" class="external" rel="nofollow" target="_blank"&gt;Create an account&lt;/a&gt; over at The Echo Nest and grab an &lt;span class="caps"&gt;API&lt;/span&gt; key.&lt;/li&gt;
	&lt;li&gt;Download a couple of videos off of Youtube (or elsewhere)&lt;/li&gt;
	&lt;li&gt;Grab the &lt;a href="http://code.google.com/p/echo-nest-remix/source/browse/trunk/examples/videx/vafromb.py" class="external" rel="nofollow" target="_blank"&gt;vafromb.py&lt;/a&gt; example script that comes bundled with the Echo Nest developer sources.&lt;/li&gt;
	&lt;li&gt;Add a couple of lines near the top of the script (before the &lt;em&gt;from echonest&lt;/em&gt; imports) with your &lt;span class="caps"&gt;API&lt;/span&gt; key :&lt;br /&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pyechonest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ECHO_NEST_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;lt;YOUR_API_KEY_HERE&amp;gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
	&lt;li&gt;Run the script on your input files : &lt;br /&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;vafromb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;inputfilenameA&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;inputfilenameB&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;outputfilename&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Mix&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;em&gt;Mix&lt;/em&gt; parameter is a number between 0 and 1 that determines the relative mix of the resynthesized song and the original input A. i.e. a mix value of 0.9 yields an output that is mostly the resynthesized version.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A &lt;em&gt;Mix&lt;/em&gt; of zero will contain only the original song, whereas a &lt;em&gt;Mix&lt;/em&gt; of 1 will contain %100 resynthesized sound.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &amp;#8216;env&amp;#8217; flag applies the volume envelopes of the segments of A to those from B.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This flag is optional, and is kind of hard to explain if you don&amp;#8217;t know what an &lt;em&gt;envelope&lt;/em&gt; is &amp;#8211; try it out and you&amp;#8217;ll figure it out pretty quickly.&lt;/p&gt;
&lt;p&gt;The hardest part is finding two videos that will mix well together &amp;#8211; I&amp;#8217;ve found that using one with a fairly sparse, strong rhythm track for &lt;em&gt;inputfilenameA&lt;/em&gt; works quite well, with a more melodic track in &lt;em&gt;inputfilenameB&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;These examples barely scrape the surface of what you can do with The Echo Nest &lt;span class="caps"&gt;API&lt;/span&gt; &amp;#8211; I highly recommend playing around with it yourself if you&amp;#8217;re interested in music and computers.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/75l5GYWTvt8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2011/01/05/simple-video-remixes-using-the-echo-nest-api</feedburner:origLink></entry>
 
 <entry>
   <title>A Christmas present from The Echo Nest</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/vKoKERuqfEY/a-christmas-present-from-the-echo-nest" />
   <updated>2011-01-05T00:00:00+13:00</updated>
   <id>http://recursive-design.com/blog/2011/01/05/a-christmas-present-from-the-echo-nest</id>
   <content type="html">&lt;time datetime="2011-01-05T00:00:00+13:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;JAN&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;05&lt;/span&gt; &lt;span class="year"&gt;2011&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2011/01/05/a-christmas-present-from-the-echo-nest"&gt;A Christmas present from The Echo Nest&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/api/"&gt;api&lt;/a&gt;, &lt;a href="/blog/category/echonest/"&gt;echonest&lt;/a&gt;, &lt;a href="/blog/category/music/"&gt;music&lt;/a&gt;, and &lt;a href="/blog/category/programming/"&gt;programming&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;A couple of weeks before Christmas I got a mail from &lt;a href="http://the.echonest.com/" class="external" rel="nofollow" target="_blank"&gt;The Echo Nest&lt;/a&gt; &lt;a href="http://developer.echonest.com/" class="external" rel="nofollow" target="_blank"&gt;developer team&lt;/a&gt; promising a free T-shirt for filling out a survey :&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2011-01-05-a-christmas-present-from-the-echo-nest/Survey_Email.png" /&gt;&lt;/figure&gt;
&lt;p&gt;I didn&amp;#8217;t expect that they&amp;#8217;d send a shirt all the way to Australia (plus I thought I&amp;#8217;d probably missed the cutoff), but they provide an amazing service so I thought I&amp;#8217;d fill out the survey anyway.&lt;/p&gt;
&lt;p&gt;A couple of weeks later, lo and behold, they came through with the goods!&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2011-01-05-a-christmas-present-from-the-echo-nest/T_Shirt.jpg" /&gt;&lt;/figure&gt;
&lt;p&gt;If you have any interest whatsoever in music programming, I can&amp;#8217;t recommend their &lt;span class="caps"&gt;API&lt;/span&gt; enough &amp;#8211; they are doing some really incredible work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt; : I&amp;#8217;ve put up a &lt;a href="/blog/2011/01/05/simple-video-remixes-using-the-echo-nest-api/"&gt;couple of remixed videos&lt;/a&gt;, in case you&amp;#8217;re wondering what kind of stuff the &lt;span class="caps"&gt;API&lt;/span&gt; allows you to do.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/vKoKERuqfEY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2011/01/05/a-christmas-present-from-the-echo-nest</feedburner:origLink></entry>
 
 <entry>
   <title>Face detection with OS X and python</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/-_oiowBKpDk/face-detection-with-osx-and-python" />
   <updated>2010-12-14T00:00:00+13:00</updated>
   <id>http://recursive-design.com/blog/2010/12/14/face-detection-with-osx-and-python</id>
   <content type="html">&lt;time datetime="2010-12-14T00:00:00+13:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;DEC&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;14&lt;/span&gt; &lt;span class="year"&gt;2010&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2010/12/14/face-detection-with-osx-and-python"&gt;Face detection with OS X and python&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/opencv/"&gt;opencv&lt;/a&gt;, &lt;a href="/blog/category/osx/"&gt;osx&lt;/a&gt;, &lt;a href="/blog/category/programming/"&gt;programming&lt;/a&gt;, and &lt;a href="/blog/category/python/"&gt;python&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;ve been messing about with &lt;a href="http://en.wikipedia.org/wiki/Face_detection" class="external" rel="nofollow" target="_blank"&gt;face detection&lt;/a&gt; for a while, and was surprised how easy it is to get basic detection working out-of-the-box with open-source libraries.&lt;/p&gt;
&lt;p&gt;Today we&amp;#8217;ll look at a simple way to get started with face detection on &lt;span class="caps"&gt;OSX&lt;/span&gt; using &lt;a href="http://www.python.org/" class="external" rel="nofollow" target="_blank"&gt;python&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2010-12-14-face-detection-with-osx-and-python/Example_1.png" /&gt;&lt;figcaption&gt;http://www.flickr.com/photos/rogue3w/2877522084/&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;We&amp;#8217;re going to be using the &lt;a href="http://opencv.willowgarage.com/wiki/" class="external" rel="nofollow" target="_blank"&gt;OpenCV&lt;/a&gt; computer vision library, originally developed by &lt;a href="http://www.intel.com/" class="external" rel="nofollow" target="_blank"&gt;Intel&lt;/a&gt; but subsequently released under the &lt;a href="http://en.wikipedia.org/wiki/BSD_license" class="external" rel="nofollow" target="_blank"&gt;&lt;span class="caps"&gt;BSD&lt;/span&gt; license&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re going to use &lt;a href="https://github.com/mxcl/homebrew" class="external" rel="nofollow" target="_blank"&gt;Homebrew&lt;/a&gt; to install everything. I&amp;#8217;ve also had success installing OpenCV from &lt;a href="http://www.macports.org/" class="external" rel="nofollow" target="_blank"&gt;MacPorts&lt;/a&gt;, as well as compiling it from source, but Homebrew seems to be the easiest and cleanest option these days.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; brew install opencv
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This ran for about 5 minutes trying to install &lt;em&gt;cmake&lt;/em&gt;, at which point I ran into an error :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;ld: symbol&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; not found
collect2: ld returned 1 &lt;span class="nb"&gt;exit &lt;/span&gt;status
make&lt;span class="o"&gt;[&lt;/span&gt;2&lt;span class="o"&gt;]&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;bin/ccmake&lt;span class="o"&gt;]&lt;/span&gt; Error 1
make&lt;span class="o"&gt;[&lt;/span&gt;1&lt;span class="o"&gt;]&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;Source/CMakeFiles/ccmake.dir/all&lt;span class="o"&gt;]&lt;/span&gt; Error 2
make: *** &lt;span class="o"&gt;[&lt;/span&gt;all&lt;span class="o"&gt;]&lt;/span&gt; Error 2
Exit status: 2
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;There was a note in the homebrew error message pointing to &lt;a href="https://github.com/mxcl/homebrew/issues/issue/2773" class="external" rel="nofollow" target="_blank"&gt;this GitHub issue&lt;/a&gt; (I wish more package managers did this!) which had a few comments suggesting that updating Homebrew and reinstalling &lt;em&gt;cmake&lt;/em&gt; would fix the problem :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; brew update
&amp;gt; brew install -v cmake
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;With this update done, installing opencv proceeded without problems :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; brew install opencv
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You probably also need to update your &lt;em&gt;PYTHON_PATH&lt;/em&gt; (thanks &lt;a href="/blog/2010/12/14/face-detection-with-osx-and-python/#comment-111571736"&gt;Duncan&lt;/a&gt; for pointing this out) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/usr/local/lib/python2.6/site-packages/:$PYTHONPATH&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You can add the export command to your &lt;em&gt;~/.profile&lt;/em&gt; file if you want to avoid having to do this in the future.&lt;/p&gt;
&lt;p&gt;The Homebrew install should come with python bindings built-in &amp;#8211; to make sure everything is working, start the python interpreter and type &lt;em&gt;import cv&lt;/em&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; python
Python 2.7 &lt;span class="o"&gt;(&lt;/span&gt;r27:82500, Sep 10 2010, 08:44:08&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;span class="o"&gt;[&lt;/span&gt;GCC 4.2.1 &lt;span class="o"&gt;(&lt;/span&gt;Apple Inc. build 5664&lt;span class="o"&gt;)]&lt;/span&gt; on darwin
Type &lt;span class="s2"&gt;&amp;quot;help&amp;quot;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;quot;copyright&amp;quot;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;quot;credits&amp;quot;&lt;/span&gt; or &lt;span class="s2"&gt;&amp;quot;license&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;more information.
&amp;gt;&amp;gt;&amp;gt; import cv
&amp;gt;&amp;gt;&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you don&amp;#8217;t get any errors, you&amp;#8217;re good to go!&lt;/p&gt;
&lt;p&gt;Next, we need a simple python script to do the actual face detection. Luckily, the &lt;a href="http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.2/" class="external" rel="nofollow" target="_blank"&gt;OpenCV source&lt;/a&gt; comes with a bunch of examples &amp;#8211; here&amp;#8217;s their &lt;em&gt;facedetect.py&lt;/em&gt; example :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;&lt;span class="c"&gt;#!/usr/bin/python&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;This program is demonstration for face and object detection using haar-like features.&lt;/span&gt;
&lt;span class="sd"&gt;The program finds faces in a camera image or video stream and displays a red box around them.&lt;/span&gt;

&lt;span class="sd"&gt;Original C implementation by:  ?&lt;/span&gt;
&lt;span class="sd"&gt;Python implementation by: Roman Stanchak, James Bowman&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;cv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;optparse&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OptionParser&lt;/span&gt;

&lt;span class="c"&gt;# Parameters for haar detection&lt;/span&gt;
&lt;span class="c"&gt;# From the API:&lt;/span&gt;
&lt;span class="c"&gt;# The default parameters (scale_factor=2, min_neighbors=3, flags=0) are tuned &lt;/span&gt;
&lt;span class="c"&gt;# for accurate yet slow object detection. For a faster operation on real video &lt;/span&gt;
&lt;span class="c"&gt;# images the settings are: &lt;/span&gt;
&lt;span class="c"&gt;# scale_factor=1.2, min_neighbors=2, flags=CV_HAAR_DO_CANNY_PRUNING, &lt;/span&gt;
&lt;span class="c"&gt;# min_size=&amp;lt;minimum possible face size&lt;/span&gt;

&lt;span class="n"&gt;min_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;image_scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;haar_scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt;
&lt;span class="n"&gt;min_neighbors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;haar_flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;detect_and_draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cascade&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c"&gt;# allocate temporary images&lt;/span&gt;
    &lt;span class="n"&gt;gray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateImage&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;small_img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateImage&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;image_scale&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
			       &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Round&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;image_scale&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;# convert color input image to grayscale&lt;/span&gt;
    &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CvtColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CV_BGR2GRAY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;# scale input image for faster processing&lt;/span&gt;
    &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;small_img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CV_INTER_LINEAR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EqualizeHist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;small_img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;small_img&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cascade&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetTickCount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;faces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HaarDetectObjects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;small_img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cascade&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateMemStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                     &lt;span class="n"&gt;haar_scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_neighbors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;haar_flags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetTickCount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;detection time = &lt;/span&gt;&lt;span class="si"&gt;%g&lt;/span&gt;&lt;span class="s"&gt;ms&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetTickFrequency&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;1000.&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;faces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;faces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c"&gt;# the input to cv.HaarDetectObjects was resized, so scale the &lt;/span&gt;
                &lt;span class="c"&gt;# bounding box of each face and convert it to two CvPoints&lt;/span&gt;
                &lt;span class="n"&gt;pt1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;image_scale&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;image_scale&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="n"&gt;pt2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;image_scale&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;image_scale&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pt1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pt2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RGB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShowImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;result&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OptionParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;usage: %prog [options] [filename|camera_index]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-c&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;--cascade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;store&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cascade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;str&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Haar cascade file, default &lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;efault&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/usr/local/Cellar/opencv/2.2/share/opencv/haarcascades/haarcascade_frontalface_default.xml&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;cascade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cascade&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print_help&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;input_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;input_name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isdigit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;capture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateCameraCapture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;capture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NamedWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;result&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;frame_copy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;frame_copy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;frame_copy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateImage&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                            &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IPL_DEPTH_8U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nChannels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IPL_ORIGIN_TL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame_copy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame_copy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            
            &lt;span class="n"&gt;detect_and_draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame_copy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cascade&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;detect_and_draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cascade&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DestroyWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;result&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;One minor change I made was updating the path to &lt;em&gt;haarcascade_frontalface_default.xml&lt;/em&gt; on line 117 &amp;#8211; I&amp;#8217;ve hard-coded in the path to the file installed by Homebrew in the example above for simplicity.&lt;/p&gt;
&lt;p&gt;Save the script above as &lt;em&gt;facedetect.py&lt;/em&gt;, grab a sample image to test it on, and you should be able to run it with regular mac python :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; python facedetect.py example.jpg
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The command above will launch a python window containing the image, with red boxes surrounding detected faces.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the result of running the script on some random creative-commons photos &lt;a href="http://www.flickr.com/search/?q=family&amp;l=deriv&amp;ct=0&amp;mt=photos&amp;adv=1" class="external" rel="nofollow" target="_blank"&gt;tagged with &amp;#8216;family&amp;#8217;&lt;/a&gt; on Flickr :&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2010-12-14-face-detection-with-osx-and-python/Example_2.png" /&gt;&lt;figcaption&gt;http://www.flickr.com/photos/stuckincustoms/2002931359/&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2010-12-14-face-detection-with-osx-and-python/Example_3.png" /&gt;&lt;figcaption&gt;http://www.flickr.com/photos/mareen/752734261/&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2010-12-14-face-detection-with-osx-and-python/Example_4.png" /&gt;&lt;figcaption&gt;http://www.flickr.com/photos/thomashawk/513666576/&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2010-12-14-face-detection-with-osx-and-python/Example_5.png" /&gt;&lt;figcaption&gt;http://www.flickr.com/photos/soldiersmediacenter/4308562775/&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2010-12-14-face-detection-with-osx-and-python/Example_6.png" /&gt;&lt;figcaption&gt;http://www.flickr.com/photos/freeparking/478631087/&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2010-12-14-face-detection-with-osx-and-python/Example_7.png" /&gt;&lt;figcaption&gt;http://www.flickr.com/photos/18854914@N04/2075741899/&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;As you can see, the results are mixed. Full-frontal faces work best (because we&amp;#8217;re using &lt;em&gt;haarcascade_frontalface_default.xml&lt;/em&gt; to do the detection), as do medium-resolution images. I&amp;#8217;ve found that processing very high-res images can result in a lot of false positives, since the image has so much detail.&lt;/p&gt;
&lt;p&gt;The example above can also process real-time video from the camera on your Mac &amp;#8211; instead of using a filename as an argument, input the camera number you wish to use (zero for most Macs) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&amp;gt; python facedetect.py 0
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you feel like digging in a little deeper, there&amp;#8217;s various other training data sets in &lt;em&gt;/usr/local/Cellar/opencv/2.2/share/opencv/haarcascades/&lt;/em&gt; for detecting other shapes (such as full bodies, eyes, noses etc), which open up some cool possibilities.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/-_oiowBKpDk" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2010/12/14/face-detection-with-osx-and-python</feedburner:origLink></entry>
 
 <entry>
   <title>Jekyll plugins for categories, projects and sitemaps</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/Ve0OSYIeSu0/jekyll-plugins-for-categories-projects-and-sitemaps" />
   <updated>2010-12-08T00:00:00+13:00</updated>
   <id>http://recursive-design.com/blog/2010/12/08/jekyll-plugins-for-categories-projects-and-sitemaps</id>
   <content type="html">&lt;time datetime="2010-12-08T00:00:00+13:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;DEC&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;08&lt;/span&gt; &lt;span class="year"&gt;2010&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2010/12/08/jekyll-plugins-for-categories-projects-and-sitemaps"&gt;Jekyll plugins for categories, projects and sitemaps&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/jekyll/"&gt;jekyll&lt;/a&gt;, &lt;a href="/blog/category/plugin/"&gt;plugin&lt;/a&gt;, &lt;a href="/blog/category/programming/"&gt;programming&lt;/a&gt;, &lt;a href="/blog/category/ruby/"&gt;ruby&lt;/a&gt;, and &lt;a href="/blog/category/web/"&gt;web&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;ve finally gotten around to cleaning up and releasing the source for a couple of the Jekyll plugins used to build this site.&lt;/p&gt;
&lt;p&gt;You can find them all on the &lt;a href="/projects/jekyll-plugins/"&gt;Jekyll Plugins&lt;/a&gt; project page, or &lt;a href="https://github.com/recurser/jekyll-plugins" class="external" rel="nofollow" target="_blank"&gt;browse the source&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As always, if you come across any problems please &lt;a href="https://github.com/recurser/jekyll-plugins/issues" class="external" rel="nofollow" target="_blank"&gt;create a ticket&lt;/a&gt; and we’ll try to get it fixed as soon as possible.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;h2&gt;Project page generator&lt;/h2&gt;
&lt;p&gt;A generator that creates project pages for Jekyll sites from git repositories.&lt;/p&gt;
&lt;p&gt;This was inspired by the project pages on GitHub, which use the project &lt;em&gt;&lt;span class="caps"&gt;README&lt;/span&gt;&lt;/em&gt; file as the index page. It takes git repositories, and automatically builds project pages for them using the &lt;em&gt;&lt;span class="caps"&gt;README&lt;/span&gt;&lt;/em&gt; file, along with downloadable zipped copies of the projects themselves (for example, all the project pages linked to from our &lt;a href="http://recursive-design.com/projects/"&gt;project page&lt;/a&gt; were auto-generated with this).&lt;/p&gt;
&lt;p&gt;The goal is to automate the construction of online project pages, keep them in sync with &lt;em&gt;&lt;span class="caps"&gt;README&lt;/span&gt;&lt;/em&gt; documentation, and provide an up-to-date zip archive for download.&lt;/p&gt;
&lt;h2&gt;Category page generator&lt;/h2&gt;
&lt;p&gt;A generator that creates category pages for Jekyll sites (for example our &lt;a href="http://recursive-design.com/blog/category/plugin/"&gt;plugin category&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I found one or two category page generators floating around on &lt;a href="http://pastebin.com/" class="external" rel="nofollow" target="_blank"&gt;pastebin&lt;/a&gt; etc, but nothing that really achieved what I was after, so I ended up putting this script together.&lt;/p&gt;
&lt;h2&gt;sitemap.xml generator&lt;/h2&gt;
&lt;p&gt;A fairly simple generator that creates a sitemap.xml page for jekyll sites, suitable for submission to google etc.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/Ve0OSYIeSu0" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2010/12/08/jekyll-plugins-for-categories-projects-and-sitemaps</feedburner:origLink></entry>
 
 <entry>
   <title>jQuery SimpleColor plugin hits version 1.0</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/bRPOAI-KZYA/jquery-simple-color-plugin-hits-version-1-0" />
   <updated>2010-12-07T00:00:00+13:00</updated>
   <id>http://recursive-design.com/blog/2010/12/07/jquery-simple-color-plugin-hits-version-1-0</id>
   <content type="html">&lt;time datetime="2010-12-07T00:00:00+13:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;DEC&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;07&lt;/span&gt; &lt;span class="year"&gt;2010&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2010/12/07/jquery-simple-color-plugin-hits-version-1-0"&gt;jQuery SimpleColor plugin hits version 1.0&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/announcement/"&gt;announcement&lt;/a&gt;, &lt;a href="/blog/category/javascript/"&gt;javascript&lt;/a&gt;, &lt;a href="/blog/category/jquery/"&gt;jquery&lt;/a&gt;, &lt;a href="/blog/category/plugin/"&gt;plugin&lt;/a&gt;, &lt;a href="/blog/category/programming/"&gt;programming&lt;/a&gt;, and &lt;a href="/blog/category/web/"&gt;web&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;A couple of weeks ago &lt;a href="http://recursive-design.com/projects/jquery-simple-color/#comment-99406963"&gt;Huga commented&lt;/a&gt; on the SimpleColor plugin with a nice suggestion &amp;#8211; adding the selected color as text inside the color selection button. I finally got around to implementing this last night, and added a couple of extra options to support this :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&lt;span class="nx"&gt;displayColorCode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="nx"&gt;Display&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eg&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;333333&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="nx"&gt;inside&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; 
                    &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
                     &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="nx"&gt;colorCodeAlign&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="nx"&gt;alignment&lt;/span&gt; &lt;span class="nx"&gt;used&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="nx"&gt;inside&lt;/span&gt;
                    &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Only&lt;/span&gt; &lt;span class="nx"&gt;used&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;displayColorCode&amp;#39;&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
                     &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;center&amp;#39;&lt;/span&gt;

&lt;span class="nx"&gt;colorCodeColor&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="nx"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="nx"&gt;inside&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Only&lt;/span&gt;
                    &lt;span class="nx"&gt;used&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;displayColorCode&amp;#39;&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
                     &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;#FFF&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The finished result looks something like this :&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2010-12-07-jquery-simple-color-plugin-hits-version-1-0/SimpleColor_Picker_With_Text.png" /&gt;&lt;/figure&gt;
&lt;p&gt;Since there&amp;#8217;s been no bug reports for a while and the plugin does basically what I need, I also took the opportunity to upgrade it from version &lt;em&gt;0.9.0&lt;/em&gt; to &lt;em&gt;1.0.0&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;As always, if you come across any problems please &lt;a href="https://github.com/recurser/jquery-simple-color/issues" class="external" rel="nofollow" target="_blank"&gt;create a ticket&lt;/a&gt; and we’ll try to get it fixed as soon as possible.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/bRPOAI-KZYA" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2010/12/07/jquery-simple-color-plugin-hits-version-1-0</feedburner:origLink></entry>
 
 <entry>
   <title>CompSci 101 - Big-O notation</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/KSV5scWIuE8/comp-sci-101-big-o-notation" />
   <updated>2010-12-07T00:00:00+13:00</updated>
   <id>http://recursive-design.com/blog/2010/12/07/comp-sci-101-big-o-notation</id>
   <content type="html">&lt;h1&gt;CompSci 101 &amp;#8211; Big-O notation&lt;/h1&gt;
&lt;p&gt;I recently had a couple of Google interviews in Tokyo, and while preparing for them I ended up with a huge list of things I wanted to brush up on before the interview.&lt;/p&gt;
&lt;p&gt;It turns out I didn&amp;#8217;t get the job (next time!), but I thought I might be able to learn something anyway by working through the list and blogging about the main areas that companies like Google expect you to know.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve grabbed the domain &lt;a href="http://computerscience101.org" class="external" rel="nofollow" target="_blank"&gt;computerscience101.org&lt;/a&gt; (which currently redirects back here), and when I&amp;#8217;ve collected enough posts I plan to throw everything up there as a kind of chapter-by-chapter interview-primer in the hope that it might help someone else out.&lt;/p&gt;
&lt;p&gt;Without further ado, first on the list is Big-O notation:&lt;/p&gt;
&lt;h2&gt;So what is Big-O notation anyway?&lt;/h2&gt;
&lt;p&gt;Big-O measures how well an operation will &amp;#8220;scale&amp;#8221; when you increase the amount of &amp;#8220;things&amp;#8221; it operates on.&lt;/p&gt;
&lt;p&gt;Big-O can be used to describe how fast an algorithm will run, or it can describe other behaviour such as how much memory an algorithm will use. For the purposes of this article, we&amp;#8217;re only going to focus on Big-O as it relates to &lt;em&gt;runtime&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For example, deciding whether a number &lt;em&gt;n&lt;/em&gt; is even or odd will take the same time no matter how big &lt;em&gt;n&lt;/em&gt; is. On the other hand, to find an item in an unsorted list of &lt;em&gt;n&lt;/em&gt; items, you have to look at each item individually &amp;#8211; the time taken will increase as the size of the list increases.&lt;/p&gt;
&lt;h2&gt;Common complexity cases&lt;/h2&gt;
&lt;p&gt;Let&amp;#8217;s have a look at a few different cases, and what they mean in real-world terms:&lt;/p&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;th&gt;Big-O     &lt;/th&gt;
		&lt;th&gt;Operations for 10 &amp;#8220;things&amp;#8221; &lt;/th&gt;
		&lt;th&gt;Operations for 100 &amp;#8220;things&amp;#8221; &lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; O(1)        &lt;/td&gt;
		&lt;td&gt;   1                         &lt;/td&gt;
		&lt;td&gt;     1 &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; O(log n)    &lt;/td&gt;
		&lt;td&gt;   3                         &lt;/td&gt;
		&lt;td&gt;     7 &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; O(n)        &lt;/td&gt;
		&lt;td&gt;  10                         &lt;/td&gt;
		&lt;td&gt;   100 &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; O(n log n)  &lt;/td&gt;
		&lt;td&gt;  30                         &lt;/td&gt;
		&lt;td&gt;   700 &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; O(n^2)      &lt;/td&gt;
		&lt;td&gt; 100                         &lt;/td&gt;
		&lt;td&gt; 10000 &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; O(2^n)      &lt;/td&gt;
		&lt;td&gt; 1024                        &lt;/td&gt;
		&lt;td&gt; 2^100 &amp;#8211; a lot! &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; O(n!)       &lt;/td&gt;
		&lt;td&gt; 3628800                     &lt;/td&gt;
		&lt;td&gt; 100! &amp;#8211; also a lot! &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h3&gt;O(1)&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;O(1) means that no matter how large the input is, &lt;strong&gt;the time taken doesn&amp;#8217;t change&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;O(1) operations run in &lt;em&gt;constant time&lt;/em&gt;. Some examples of O(1) operations are :&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Determining if a number is even or odd.&lt;/li&gt;
	&lt;li&gt;Using a constant-size lookup table or hash table.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following function will take the same time to execute, no matter how big &lt;em&gt;array&lt;/em&gt; is :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_first_element_null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;O(log n)&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Any algorithm which &lt;strong&gt;cuts the problem in half&lt;/strong&gt; each time is O(log n).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;O(log n) operations run in &lt;em&gt;logarithmic time&lt;/em&gt; &amp;#8211; the operation will take longer as the input size increases, but once the input gets fairly large it won&amp;#8217;t change enough to worry about. If you double &lt;em&gt;n&lt;/em&gt;, you have to spend an extra amount of time &lt;em&gt;t&lt;/em&gt; to complete the task. If &lt;em&gt;n&lt;/em&gt; doubles again, &lt;em&gt;t&lt;/em&gt; won&amp;#8217;t double, but will increase by a constant amount.&lt;/p&gt;
&lt;p&gt;An example of an O(log n) operation is finding an item in a sorted list with a &lt;a href="http://en.wikipedia.org/wiki/Self-balancing_binary_search_tree" class="external" rel="nofollow" target="_blank"&gt;balanced search tree&lt;/a&gt; or a &lt;a href="http://en.wikipedia.org/wiki/Binary_search_algorithm" class="external" rel="nofollow" target="_blank"&gt;binary search&lt;/a&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="c1"&gt;# if high and low overlap, nothing was found.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt;
  &lt;span class="c1"&gt;# Determine the middle element.&lt;/span&gt;
  &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# Split the result in half and search again recursively until we succeed.&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="c1"&gt;# Found!&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;O(n)&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;O(n) means that for every element, you are doing a constant number of operations, such as comparing each element to a known value.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;O(n) operations run in &lt;em&gt;linear time&lt;/em&gt; &amp;#8211; the larger the input, the longer it takes, in an even tradeoff. Every time you double &lt;em&gt;n&lt;/em&gt;, the operation will take twice as long.&lt;/p&gt;
&lt;p&gt;An example of an O(n) operation is finding an item in an unsorted list :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;contains_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;O(n log n)&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;O(n log n) means that you&amp;#8217;re performing an &lt;strong&gt;O(log n) operation for each item&lt;/strong&gt; in your input. Most (efficient) sort algorithms are an example of this.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;O(n log n) operations run in &lt;em&gt;loglinear time&lt;/em&gt; &amp;#8211; increasing the input size hurts, but may still be manageable. Every time you double &lt;em&gt;n&lt;/em&gt;, you spend twice as much time plus a little more.&lt;/p&gt;
&lt;p&gt;Examples of O(n log n) operations are &lt;a href="http://en.wikipedia.org/wiki/Quicksort" class="external" rel="nofollow" target="_blank"&gt;quicksort&lt;/a&gt; (in the average and best case), &lt;a href="http://en.wikipedia.org/wiki/Heapsort" class="external" rel="nofollow" target="_blank"&gt;heapsort&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Mergesort" class="external" rel="nofollow" target="_blank"&gt;merge sort&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mergesort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="n"&gt;left&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mergesort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;mergesort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
 
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
  &lt;span class="k"&gt;until&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty?&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty?&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;
      &lt;span class="n"&gt;sorted&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shift&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;sorted&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shift&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;sorted&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;O(n^2)&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;O(n^2) means that &lt;strong&gt;for every element, you do something with every other element&lt;/strong&gt;, such as comparing them.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;O(n^2) operations run in &lt;em&gt;quadratic time&lt;/em&gt; &amp;#8211; the operation is only really practical up to a certain input size. Every time &lt;em&gt;n&lt;/em&gt; doubles, the operation takes four times as long.&lt;/p&gt;
&lt;p&gt;Examples of O(n^2) operations are &lt;a href="http://en.wikipedia.org/wiki/Quicksort" class="external" rel="nofollow" target="_blank"&gt;quicksort&lt;/a&gt; (in the worst case) and &lt;a href="http://en.wikipedia.org/wiki/Bubble_Sort" class="external" rel="nofollow" target="_blank"&gt;bubble sort&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The following function is an example of an O(n^2) operation, where every element in an array is compared to every other element :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;contains_duplicates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
        &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# Found a match!&lt;/span&gt;
            &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;O(2^n)&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;O(2^n means that &lt;strong&gt;the time taken will double with each additional element&lt;/strong&gt; in the input data set.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;O(2^n) operations run in &lt;em&gt;exponential time&lt;/em&gt; &amp;#8211; the operation is impractical for any reasonably large input size &lt;em&gt;n&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;An example of an O(2^n) operation is &lt;a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem" class="external" rel="nofollow" target="_blank"&gt;the travelling salesman problem&lt;/a&gt; (using &lt;a href="http://en.wikipedia.org/wiki/Dynamic_programming" class="external" rel="nofollow" target="_blank"&gt;dynamic programming&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;O(n!)&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;O(n!) involves doing something for &lt;strong&gt;all possible permutations&lt;/strong&gt; of the n elements.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;O(n!) operations run in &lt;em&gt;factorial time&lt;/em&gt; &amp;#8211; the operation is impractical for any reasonably large input size &lt;em&gt;n&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;An example of an O(n!) operation is &lt;a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem" class="external" rel="nofollow" target="_blank"&gt;the travelling salesman problem&lt;/a&gt; using brute force, where every combination of paths will be examined.&lt;/p&gt;
&lt;h2&gt;Big-O Visualized&lt;/h2&gt;
&lt;p&gt;The graph below&lt;sup class="footnote" id="fnr1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; maps number of operations (on the X-axis) to time taken (on the Y-axis). It&amp;#8217;s pretty clear that an O(2^n) algorithm is going to cause problems quickly as the input size increases!&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2010-12-07-comp-sci-101-big-o-notation/Time_Complexity.png" /&gt;&lt;/figure&gt;
&lt;h2&gt;Amortized analysis&lt;/h2&gt;
&lt;p&gt;Some operations are said to run in &lt;em&gt;amortized time&lt;/em&gt; :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you do an operation say a million times, you don&amp;#8217;t really care about the worst-case or the best-case of that operation &amp;#8211; what you care about is how much time is taken in total when you repeat the operation a million times.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;So it doesn&amp;#8217;t matter if the operation is very slow once in a while, as long as &amp;#8220;once in a while&amp;#8221; is rare enough for the slowness to be diluted away. Essentially amortised time means &amp;#8220;average time taken per operation, if you do many operations&amp;#8221;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Let&amp;#8217;s take [an] example of a dynamic array, to which you repeatedly add new items. Normally adding an item takes constant time (that is, O(1)). But each time the array is full, you allocate twice as much space, copy your data into the new region, and free the old space. Assuming allocates and frees run in constant time, this enlargement process takes O(n) time where n is the current size of the array.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;So each time you enlarge, you take about twice as much time as the last enlarge. But you&amp;#8217;ve also waited twice as long before doing it! The cost of each enlargement can thus be &amp;#8220;spread out&amp;#8221; among the insertions. This means that in the long term, the total time taken for adding m items to the array is O(m), and so the amortised time (i.e. time per insertion) is O(1). &lt;sup class="footnote" id="fnr2"&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Exercises&lt;/h2&gt;
&lt;p&gt;Decide the Big-O complexity of the following examples :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bubble_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zero?&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; 
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;palindrome?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;stack&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
  &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_char&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 
    &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty?&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sum_of_divisors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="n"&gt;i&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_prime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;word_occurrence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="n"&gt;array&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;phrase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;downcase&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;downcase&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://rob-bell.net/2009/06/a-beginners-guide-to-big-o-notation/" class="external" rel="nofollow" target="_blank"&gt;A Beginners’ Guide to Big O Notation&lt;/a&gt; (rob-bell.net)&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Amortized_analysis" class="external" rel="nofollow" target="_blank"&gt;Amortized analysis&lt;/a&gt; (en.wikipedia.org)&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/107165/big-o-for-eight-year-olds/107189#107189" class="external" rel="nofollow" target="_blank"&gt;Big-O for Eight Year Olds?&lt;/a&gt; (stackoverflow.com)&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Big_O_notation" class="external" rel="nofollow" target="_blank"&gt;Big O notation&lt;/a&gt; (en.wikipedia.org)&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/200384/constant-amortized-time/" class="external" rel="nofollow" target="_blank"&gt;Constant Amortized Time&lt;/a&gt; (stackoverflow.com)&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://en.wikibooks.org/wiki/Algorithm_implementation/Sorting/Merge_sort#Ruby" class="external" rel="nofollow" target="_blank"&gt;Merge sort&lt;/a&gt; (en.wikipedia.org)&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Time_complexity#Table_of_common_time_complexities" class="external" rel="nofollow" target="_blank"&gt;Table of common time complexities&lt;/a&gt; (en.wikipedia.org)&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://therecyclebin.files.wordpress.com/2008/05/time-complexity.png" class="external" rel="nofollow" target="_blank"&gt;Time complexity graph&lt;/a&gt; (therecyclebin.wordpress.com)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;p class="footnote" id="fn1"&gt;&lt;a href="#fnr1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; Improved graph kindly provided by &lt;a href="http://twitter.com/Xorlev"&gt;Xorlev&lt;/a&gt;. The original graph was from &lt;a href="http://therecyclebin.files.wordpress.com/2008/05/time-complexity.png" class="external" rel="nofollow" target="_blank"&gt;The Recycle Bin&lt;/a&gt;&lt;/p&gt;
&lt;p class="footnote" id="fn2"&gt;&lt;a href="#fnr2"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; Quote from Stack Overflow user &lt;a href="http://stackoverflow.com/questions/200384/constant-amortized-time/249695#249695" class="external" rel="nofollow" target="_blank"&gt;Artelius&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/KSV5scWIuE8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2010/12/07/comp-sci-101-big-o-notation</feedburner:origLink></entry>
 
 <entry>
   <title>A weekend project - fromthecache.com</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/3gklGj4eVdw/a-weekend-project-from-the-cache" />
   <updated>2010-11-03T00:00:00+13:00</updated>
   <id>http://recursive-design.com/blog/2010/11/03/a-weekend-project-from-the-cache</id>
   <content type="html">&lt;time datetime="2010-11-03T00:00:00+13:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;NOV&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;03&lt;/span&gt; &lt;span class="year"&gt;2010&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2010/11/03/a-weekend-project-from-the-cache"&gt;A weekend project &amp;#8211; fromthecache.com&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/announcement/"&gt;announcement&lt;/a&gt;, &lt;a href="/blog/category/company/"&gt;company&lt;/a&gt;, &lt;a href="/blog/category/html5/"&gt;html5&lt;/a&gt;, &lt;a href="/blog/category/programming/"&gt;programming&lt;/a&gt;, &lt;a href="/blog/category/rails/"&gt;rails&lt;/a&gt;, &lt;a href="/blog/category/ruby/"&gt;ruby&lt;/a&gt;, &lt;a href="/blog/category/sass/"&gt;sass&lt;/a&gt;, and &lt;a href="/blog/category/web/"&gt;web&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;I was playing around on the weekend screen-scraping and analyzing word-frequencies for various sites (don&amp;#8217;t ask), and was getting some slow responses (and accidentally got my IP blocked from one site when I hit them a few too many times).&lt;/p&gt;
&lt;p&gt;Eventually I hit upon the idea of hitting &lt;a href="http://webcache.googleusercontent.com/search?q=cache:recursive-design.com" class="external" rel="nofollow" target="_blank"&gt;Google Cache&lt;/a&gt; for each &lt;span class="caps"&gt;URL&lt;/span&gt; (the pages I was scraping had sequential &lt;em&gt;?id=xxx&lt;/em&gt; URLs so it was easy to automate), with the aim of speeding things up a bit and taking some load off the target sites.&lt;/p&gt;
&lt;p&gt;With this in mind, I spent a few hours Saturday and Sunday developing &lt;a href="/projects/from-the-cache/"&gt;fromthecache.com&lt;/a&gt; &amp;#8211; it&amp;#8217;s built on rails, and designed to provide transparent access to the Google cache, while fetching the original page as a fallback if necessary.&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2010-11-03-a-weekend-project-from-the-cache/Screenshot.png" /&gt;&lt;/figure&gt;
&lt;p&gt;It occurred to me halfway through that it&amp;#8217;s also useful for providing mirror links if a site gets &lt;a href="http://en.wikipedia.org/wiki/Slashdot_effect" class="external" rel="nofollow" target="_blank"&gt;slash-dotted&lt;/a&gt; &amp;#8211; just put &lt;em&gt;fromthecache.com/&lt;/em&gt; in front of the &lt;span class="caps"&gt;URL&lt;/span&gt; and you have an instant cache link.&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s a fairly good chance that the server&amp;#8217;s IP will get blocked from Google for looking like a bot, but I&amp;#8217;m hoping requests out of &lt;a href="http://heroku.com/" class="external" rel="nofollow" target="_blank"&gt;Heroku&lt;/a&gt; might come from a few different IPs and mix things up a bit.&lt;/p&gt;
&lt;p&gt;You can view the demo at &lt;a href="http://fromthecache.com/" class="external" rel="nofollow" target="_blank"&gt;fromthecache.com&lt;/a&gt;, &lt;a href="https://github.com/recurser/from-the-cache" class="external" rel="nofollow" target="_blank"&gt;browse the source&lt;/a&gt;, or&lt;br /&gt;
download it from &lt;a href="/projects/from-the-cache/"&gt;the project page&lt;/a&gt; and try it out for yourself.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/3gklGj4eVdw" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2010/11/03/a-weekend-project-from-the-cache</feedburner:origLink></entry>
 
 <entry>
   <title>Introducing Rails Kitchen Sink</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/eiFuDM8SGGM/introducing-rails-kitchen-sink" />
   <updated>2010-10-21T00:00:00+13:00</updated>
   <id>http://recursive-design.com/blog/2010/10/21/introducing-rails-kitchen-sink</id>
   <content type="html">&lt;time datetime="2010-10-21T00:00:00+13:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;OCT&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;21&lt;/span&gt; &lt;span class="year"&gt;2010&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2010/10/21/introducing-rails-kitchen-sink"&gt;Introducing Rails Kitchen Sink&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/announcement/"&gt;announcement&lt;/a&gt;, &lt;a href="/blog/category/company/"&gt;company&lt;/a&gt;, &lt;a href="/blog/category/html5/"&gt;html5&lt;/a&gt;, &lt;a href="/blog/category/programming/"&gt;programming&lt;/a&gt;, &lt;a href="/blog/category/rails/"&gt;rails&lt;/a&gt;, &lt;a href="/blog/category/ruby/"&gt;ruby&lt;/a&gt;, &lt;a href="/blog/category/sass/"&gt;sass&lt;/a&gt;, and &lt;a href="/blog/category/web/"&gt;web&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;m happy to announce the release of &lt;a href="/projects/rails-kitchen-sink/"&gt;Rails Kitchen Sink&lt;/a&gt;, our rails-project-starter, which we will be building all future Rails apps off of.&lt;/p&gt;
&lt;figure&gt;&lt;img src="http://recursive-design.com/images/posts/2010-10-21-introducing-rails-kitchen-sink/Screenshot.png" /&gt;&lt;/figure&gt;
&lt;p&gt;It includes everything we commonly need when starting a new project, such as registration, login, password reset, authorization, &lt;span class="caps"&gt;HAML&lt;/span&gt;, &lt;span class="caps"&gt;SASS&lt;/span&gt;, CoffeeSript etc.&lt;/p&gt;
&lt;p&gt;You can view the demo at &lt;a href="http://railskitchensink.com/"&gt;http://railskitchensink.com/&lt;/a&gt;, or download it from &lt;a href="/projects/rails-kitchen-sink/"&gt;the project page&lt;/a&gt; and try it out for yourself.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m considering including support for a couple of recurring-billing companies, but not sure if the interest is there &amp;#8211; please let us know if you would find this useful. It would probably involve writing a separate gem to abstract out the details and provide a common billing interface.&lt;/p&gt;
&lt;p&gt;As always, contributions (particularly translations) are much appreciated!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/eiFuDM8SGGM" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2010/10/21/introducing-rails-kitchen-sink</feedburner:origLink></entry>
 
 <entry>
   <title>Static blogging the Jekyll way</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/eOBe9SLEQEE/static-blogging-the-jekyll-way" />
   <updated>2010-10-12T00:00:00+13:00</updated>
   <id>http://recursive-design.com/blog/2010/10/12/static-blogging-the-jekyll-way</id>
   <content type="html">&lt;time datetime="2010-10-12T00:00:00+13:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;OCT&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;12&lt;/span&gt; &lt;span class="year"&gt;2010&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2010/10/12/static-blogging-the-jekyll-way"&gt;Static blogging the Jekyll way&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/company/"&gt;company&lt;/a&gt;, &lt;a href="/blog/category/html5/"&gt;html5&lt;/a&gt;, &lt;a href="/blog/category/jekyll/"&gt;jekyll&lt;/a&gt;, &lt;a href="/blog/category/programming/"&gt;programming&lt;/a&gt;, &lt;a href="/blog/category/ruby/"&gt;ruby&lt;/a&gt;, &lt;a href="/blog/category/sass/"&gt;sass&lt;/a&gt;, and &lt;a href="/blog/category/web/"&gt;web&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;In building the new site, I decided to take the opportunity to try out something new. I&amp;#8217;ve been using &lt;a href="http://wordpress.org/" class="external" rel="nofollow" target="_blank"&gt;WordPress&lt;/a&gt; to power my blog for about 5 years, and while it has served me well, I wanted to try out something different. The main criteria for choosing a new blogging platform were :&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;It should serve true static pages, with no need for server-side processing.&lt;/li&gt;
	&lt;li&gt;It should be easy to store the entire site in &lt;a href="http://git-scm.com/" class="external" rel="nofollow" target="_blank"&gt;Git&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;It should support the concept of &lt;em&gt;layouts&lt;/em&gt; &amp;#8211; I wanted to have a single &amp;#8216;template&amp;#8217; file that blog posts could easily inherit from.&lt;/li&gt;
	&lt;li&gt;It should support &lt;a href="http://daringfireball.net/projects/markdown/" class="external" rel="nofollow" target="_blank"&gt;MarkDown&lt;/a&gt; or &lt;a href="http://www.textism.com/tools/textile/" class="external" rel="nofollow" target="_blank"&gt;Textile&lt;/a&gt; for formatting posts, since I want to keep away from posting raw &lt;span class="caps"&gt;HTML&lt;/span&gt; as much as possible.&lt;/li&gt;
	&lt;li&gt;It should support comments.&lt;/li&gt;
	&lt;li&gt;I should be able to deploy updates to the site with a single command.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By patching together a few different open-source technologies, I&amp;#8217;ve been able to achieve the above and more.&lt;/p&gt;
&lt;h2&gt;Jekyll&lt;/h2&gt;
&lt;p&gt;After trying out several different static site generators, I settled on &lt;a href="http://jekyllrb.com/" class="external" rel="nofollow" target="_blank"&gt;Jekyll&lt;/a&gt;. In its own words :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Jekyll is a simple, blog aware, static site generator. It takes a template directory (representing the raw form of a website), runs it through Textile or Markdown and Liquid converters, and spits out a complete, static website suitable for serving with Apache or your favorite web server.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Jekyll has a healthy community built around it, and has a plugin system, which I figured would allow me to work around any shortcomings I came across. The fact that Jekyll is used to power &lt;a href="http://pages.github.com/" class="external" rel="nofollow" target="_blank"&gt;GitHub Pages&lt;/a&gt; also helped sway my decision, since I know it isn’t going to go away anytime soon.&lt;/p&gt;
&lt;p&gt;I won&amp;#8217;t go into how to get your first Jekyll site going here, but the &lt;a href="http://github.com/mojombo/jekyll/wiki" class="external" rel="nofollow" target="_blank"&gt;documentation on GitHub&lt;/a&gt; is excellent, and there&amp;#8217;s a nice &lt;a href="http://github.com/mojombo/jekyll/wiki/Usage" class="external" rel="nofollow" target="_blank"&gt;getting started guide&lt;/a&gt; to help you jump straight in.&lt;/p&gt;
&lt;h2&gt;Custom Jekyll Plugins&lt;/h2&gt;
&lt;p&gt;I ended up writing several custom Jekyll plugins to provide things that aren&amp;#8217;t included by default :&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;A short generator to create a google-compatible &lt;span class="caps"&gt;XML&lt;/span&gt; &lt;a href="http://recursive-design.com/sitemap.xml"&gt;sitemap&lt;/a&gt; automatically.&lt;/li&gt;
	&lt;li&gt;A generator to create category pages automatically (for example the &lt;a href="/blog/category/ruby/"&gt;Ruby&lt;/a&gt; category).&lt;/li&gt;
	&lt;li&gt;A more in-depth generator that takes git repositories, and automatically builds project pages for them using the &lt;em&gt;&lt;span class="caps"&gt;README&lt;/span&gt;&lt;/em&gt; file, along with downloadable zipped copies of the projects themselves (for example, the &lt;a href="/projects/jquery-simple-color/"&gt;jquery-simple-color plugin&lt;/a&gt; page). I only have a couple of these projects up at this point, but have quite a few queued up to release when time permits, so I wanted the process to be automated as much as possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href="http://github.com/mojombo/jekyll/wiki/Plugins" class="external" rel="nofollow" target="_blank"&gt;plugin documentation&lt;/a&gt; is a little sparse, but there are a couple of examples to get you going. I&amp;#8217;ll be releasing the source of my own custom generators over the next couple of weeks, so &lt;a href="/feed/"&gt;stay tuned to &lt;span class="caps"&gt;RSS&lt;/span&gt;&lt;/a&gt; if you want more information.&lt;/p&gt;
&lt;h2&gt;HTML5 Boilerplate&lt;/h2&gt;
&lt;p&gt;Since this is the first site I&amp;#8217;ve built with HTML5, I decided to use &lt;a href="http://html5boilerplate.com/" class="external" rel="nofollow" target="_blank"&gt;HTML5 Boilerplate&lt;/a&gt; as a starting-point, which bills itself as &lt;em&gt;the professional badass&amp;#8217;s base &lt;span class="caps"&gt;HTML&lt;/span&gt;/&lt;span class="caps"&gt;CSS&lt;/span&gt;/JS template for a fast, robust and future-proof site&lt;/em&gt; .&lt;/p&gt;
&lt;p&gt;Overall it works very nicely, although things still look a bit wacky on Internet Explorer (my fault, not BoilerPlate&amp;#8217;s). We&amp;#8217;re serving the site with &lt;a href="http://nginx.org/" class="external" rel="nofollow" target="_blank"&gt;Nginx&lt;/a&gt;, so we miss out on some of the Apache &lt;em&gt;.htaccess&lt;/em&gt; goodness that comes with &lt;span class="caps"&gt;HTML&lt;/span&gt; Boilerplate, but overall it&amp;#8217;s nice and easy to dive in and get started with.&lt;/p&gt;
&lt;p&gt;One minor niggle is that the meta tag for triggering &lt;a href="http://code.google.com/chrome/chromeframe/" class="external" rel="nofollow" target="_blank"&gt;Google Chrome Frame&lt;/a&gt; in &lt;em&gt;IE&lt;/em&gt; doesn’t validate, which doesn’t really affect anything one way or the other, but it&amp;#8217;s always nice to get the green tick from &lt;a href="http://validator.w3.org/check/" class="external" rel="nofollow" target="_blank"&gt;validator.w3.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Boilerplate was a cinch to get running with Jekyll &amp;#8211; just a matter of dropping the &lt;span class="caps"&gt;CSS&lt;/span&gt; and JavaScript files in the right places, and editing the main layout.&lt;/p&gt;
&lt;h2&gt;Compass/Sass&lt;/h2&gt;
&lt;p&gt;After using &lt;a href="http://compass-style.org/" class="external" rel="nofollow" target="_blank"&gt;Compass&lt;/a&gt; and &lt;a href="http://sass-lang.com/" class="external" rel="nofollow" target="_blank"&gt;Sass&lt;/a&gt; on a couple of projects in the past I was determined to use them again this time.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Compass is a stylesheet authoring framework that makes your stylesheets and markup easier to build and maintain. With compass, you write your stylesheets in Sass instead of &lt;span class="caps"&gt;CSS&lt;/span&gt;. Using the power of Sass Mixins and the Compass community, you can apply battle-tested styles from frameworks like Blueprint to your stylesheets instead of your markup.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Compass/Sass combo is a huge time-saver when building &lt;span class="caps"&gt;CSS&lt;/span&gt;-heavy sites, and even on a reasonably minimal site like this it helps keep things nicely organized, readable and maintainable. Compass was relatively easy to get running with Jekyll &amp;#8211; &lt;a href="http://bmaland.com/2009/05/08/using-compass-with-jekyll.html" class="external" rel="nofollow" target="_blank"&gt;Bjørn Arild Mæland&lt;/a&gt; has a few tips that helped here.&lt;/p&gt;
&lt;p&gt;The fact that Compass was designed to work with ruby/rails was an added bonus here, since it allowed me to handle all common Jekyll and Compass tasks in the same Rakefile.&lt;/p&gt;
&lt;h2&gt;Pygments&lt;/h2&gt;
&lt;p&gt;Jekyll uses &lt;a href="http://pygments.org/" class="external" rel="nofollow" target="_blank"&gt;Pygments&lt;/a&gt; to do code syntax highlighting. Again I was pleasantly surprised how easy this was to integrate, since it&amp;#8217;s written in Python rather than Ruby. Installation on Leopard is as simple as :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sudo easy_install Pygments
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Once it is installed, you need to generate the &lt;span class="caps"&gt;CSS&lt;/span&gt; required for highlighting :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pygmentize -S default -f html &amp;gt; _sass/3rd_party/pygments/default.scss
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This generates the default color scheme, and drops it into a folder inside &lt;em&gt;_sass&lt;/em&gt; (you may want to organize your &lt;span class="caps"&gt;SASS&lt;/span&gt; files differently). Once you have the &lt;span class="caps"&gt;CSS&lt;/span&gt; installed, you can highlight code in your posts by wrapping it in &lt;em&gt;highlight&lt;/em&gt; tags :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;highlight&lt;/span&gt; &lt;span class="n"&gt;ruby&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;goes&lt;/span&gt; &lt;span class="n"&gt;here&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;endhighlight&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Pygments &lt;a href="http://pygments.org/languages/" class="external" rel="nofollow" target="_blank"&gt;supports a bunch of languages&lt;/a&gt;, and it doesn’t look terribly difficult to add your own if the need arises.&lt;/p&gt;
&lt;h2&gt;Rake&lt;/h2&gt;
&lt;p&gt;Being a huge fan of automation, I used &lt;a href="http://rake.rubyforge.org/" class="external" rel="nofollow" target="_blank"&gt;Rake&lt;/a&gt; to script some of the common tasks involved with running the site. These shortcuts handle tasks like compiling the &lt;span class="caps"&gt;CSS&lt;/span&gt;, compiling the &lt;span class="caps"&gt;HTML&lt;/span&gt;, cleaning all build products, generating pygments &lt;span class="caps"&gt;CSS&lt;/span&gt;, and deploying the site.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:jekyll&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Delete generated _site files&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:clean&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rm -fR _site&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Run the jekyll dev server&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:server&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;jekyll --server --auto&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Clean temporary files and run the server&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:compile&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;compass:clean&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;compass:compile&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;jekyll&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:deploy&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Deploy to production&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:prod&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dev:off&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cap deploy&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:compass&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;  

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Delete temporary compass files&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:clean&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rm -fR css/*&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Run the compass watch script&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:watch&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;compass watch&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Compile sass scripts&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:compile&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:clean&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;compass compile&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:pygments&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;  

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Delete pygments CSS files&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:clean&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rm -f _sass/3rd_party/pygments/*.scss&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Generate pygments CSS&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:compile&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:clean&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;mkdir -p _sass/3rd_party/pygments&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;pygmentize -S default -f html &amp;gt; _sass/3rd_party/pygments/default.scss&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:dev&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Un-publish old posts to speed up development&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:on&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;jekyll:clean&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;find . -name &amp;quot;*.textile&amp;quot; -exec sed -i &amp;quot;&amp;quot; &amp;quot;s|^published: true|published: false|g&amp;quot; {} \;&amp;#39;&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;find . -name &amp;quot;*.yml&amp;quot; -exec sed -i &amp;quot;&amp;quot; &amp;quot;s|^published: true|published: false|g&amp;quot; {} \;&amp;#39;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Re-publish old posts for deployment&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:off&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;jekyll:clean&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;find . -name &amp;quot;*.textile&amp;quot; -exec sed -i &amp;quot;&amp;quot; &amp;quot;s|^published: false|published: true|g&amp;quot; {} \;&amp;#39;&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;find . -name &amp;quot;*.yml&amp;quot; -exec sed -i &amp;quot;&amp;quot; &amp;quot;s|^published: false|published: true|g&amp;quot; {} \;&amp;#39;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2&gt;Capistrano&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;ve used &lt;a href="http://github.com/capistrano/capistrano/wiki/Documentation-v2.x" class="external" rel="nofollow" target="_blank"&gt;Capistrano&lt;/a&gt; on several projects in the past, and was very keen to use it again.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Capistrano is an open source tool for running scripts on multiple servers; its main use is deploying web applications. It automates the process of making a new version of an application available on one or more web servers, including supporting tasks such as changing databases.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Again, &lt;em&gt;Capistrano&lt;/em&gt; was very easy to get going with &lt;em&gt;Jekyll&lt;/em&gt;. I had to write a simple &lt;em&gt;deploy.rb&lt;/em&gt; script to push the site to production :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;capistrano/ext/multistage&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:stages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sx"&gt;%w(production)&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:default_stage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;production&amp;quot;&lt;/span&gt;

&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;recursive-design&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.com&amp;quot;&lt;/span&gt;

&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;config/passwords.yml&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;abort&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Couldn&amp;#39;t find config/passwords.yml&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:passwords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;YAML&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:deploy_via&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:copy&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:repository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;_site&amp;quot;&lt;/span&gt; 
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:scm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:none&lt;/span&gt; 
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:copy_compression&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:gzip&lt;/span&gt;

&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:use_sudo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:deploy&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;DESC&lt;/span&gt;
&lt;span class="sh"&gt;  A macro-task that updates the code and fixes the symlink.&lt;/span&gt;
&lt;span class="no"&gt;  DESC&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;compile&lt;/span&gt;
      &lt;span class="n"&gt;update_code&lt;/span&gt;
      &lt;span class="n"&gt;symlink&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:update_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:except&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:no_release&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;on_rollback&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rm -rf &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;release_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;; true&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deploy!&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Compile the site and CSS. &amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:compile&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rake dev:off&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rake jekyll:compile&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
    
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&amp;#8230; and a supporting &lt;em&gt;production.rb&lt;/em&gt; file :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:web&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:primary&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;

&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;passwords&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;production&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:deploy_to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/var/www/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&amp;#8230; as well as a &lt;em&gt;passwords.yml&lt;/em&gt; containing login information for the production server.&lt;/p&gt;
&lt;p&gt;Once Capsitrano and Rake are set up, deployment is as simple as doing a&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rake deploy:prod
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This cleans out all the old build products, rebuilds the site and associated &lt;span class="caps"&gt;CSS&lt;/span&gt;, grabs all my projects from Git, builds pages for them and adds a link to the latest zipped-up version, and pushes everything to the production server.&lt;/p&gt;
&lt;h2&gt;Disqus&lt;/h2&gt;
&lt;p&gt;Since &lt;em&gt;Jekyll&lt;/em&gt; only generates static &lt;span class="caps"&gt;HTML&lt;/span&gt;, there is no support for comments. Luckily &lt;a href="http://disqus.com/" class="external" rel="nofollow" target="_blank"&gt;Disqus&lt;/a&gt; offers a great (free!) service to provide comments to your site via embedded JavaScript.&lt;/p&gt;
&lt;p&gt;My only gripe with the service is that it has proved impossible to import all the comments from the old WordPress site into Disqus &amp;#8211; I&amp;#8217;ve tried their WordPress plugin, a direct upload of the &lt;span class="caps"&gt;XML&lt;/span&gt; exported by WordPress, as well as a site crawl, and nothing seems to have worked. I haven&amp;#8217;t gotten around to contacting them about this yet, so possibly there&amp;#8217;s a simple way to do it that I&amp;#8217;m missing. For new content though, &lt;em&gt;Disqus&lt;/em&gt; works great.&lt;/p&gt;
&lt;h2&gt;Feedburner&lt;/h2&gt;
&lt;p&gt;Once again I&amp;#8217;m using &lt;a href="http://feedburner.google.com/" class="external" rel="nofollow" target="_blank"&gt;FeedBurner&lt;/a&gt; to serve the &lt;em&gt;&lt;span class="caps"&gt;RSS&lt;/span&gt;&lt;/em&gt; feed &amp;#8211; it gives some nice stats, and looks a little better than a plain feed. Again, this was fairly straightforward to get running with Jekyll &amp;#8211; I &lt;a href="/blog/2010/09/14/integrating-jekyll-with-feedburner/"&gt;posted a how-to&lt;/a&gt; several weeks ago laying out how to get it all going.&lt;/p&gt;
&lt;h2&gt;So what&amp;#8217;s the verdict?&lt;/h2&gt;
&lt;p&gt;With services like &lt;em&gt;Disqus&lt;/em&gt; appearing, pure-static sites are now a viable option for blogging. I love being able to write in a regular text editor instead of the WordPress &lt;span class="caps"&gt;WYSIWYG&lt;/span&gt; editor, and love the safety-net that keeping everything in &lt;em&gt;Git&lt;/em&gt; provides. Jekyll is extremely light-weight and pluggable &amp;#8211; I don&amp;#8217;t think getting Compass and Pygments going with WordPress would have been quite as straightforward.&lt;/p&gt;
&lt;p&gt;Re-building the site (and researching the various options beforehand) really drove home to me how many great, open-source projects there are these days &amp;#8211; the fact that I could just plug in all these disparate pieces to build a site in a weekend was a pleasant surprise.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/eOBe9SLEQEE" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2010/10/12/static-blogging-the-jekyll-way</feedburner:origLink></entry>
 
 <entry>
   <title>HABTM before_filter in rails models</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/6jypHFVmi90/habtm-before-filter-in-rails-models" />
   <updated>2010-10-03T00:00:00+13:00</updated>
   <id>http://recursive-design.com/blog/2010/10/03/habtm-before-filter-in-rails-models</id>
   <content type="html">&lt;time datetime="2010-10-03T00:00:00+13:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;OCT&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;03&lt;/span&gt; &lt;span class="year"&gt;2010&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2010/10/03/habtm-before-filter-in-rails-models"&gt;&lt;span class="caps"&gt;HABTM&lt;/span&gt; before_filter in rails models&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/database/"&gt;database&lt;/a&gt;, &lt;a href="/blog/category/habtm/"&gt;habtm&lt;/a&gt;, &lt;a href="/blog/category/quickie/"&gt;quickie&lt;/a&gt;, &lt;a href="/blog/category/rails/"&gt;rails&lt;/a&gt;, and &lt;a href="/blog/category/ruby/"&gt;ruby&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;ve been playing about with &lt;a href="http://github.com/plataformatec/devise" class="external" rel="nofollow" target="_blank"&gt;Devise&lt;/a&gt; and &lt;a href="http://github.com/ryanb/cancan" class="external" rel="nofollow" target="_blank"&gt;CanCan&lt;/a&gt; for rails authentication and authorization recently &amp;#8211; this great &lt;a href="http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/" class="external" rel="nofollow" target="_blank"&gt;pair&lt;/a&gt; of &lt;a href="http://www.tonyamoyal.com/2010/09/29/rails-authentication-with-devise-and-cancan-part-2-restful-resources-for-administrators//" class="external" rel="nofollow" target="_blank"&gt;posts&lt;/a&gt; from &lt;a href="http://www.tonyamoyal.com/" class="external" rel="nofollow" target="_blank"&gt;Tony Amoyal&lt;/a&gt; have helped a great deal.&lt;/p&gt;
&lt;p&gt;I have a &lt;em&gt;User&lt;/em&gt; model and a &lt;em&gt;Role&lt;/em&gt; model, and wanted to automatically add the &lt;em&gt;:user&lt;/em&gt; role to each user whenever roles are assigned. The roles were set in the controller as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;
  &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:role_ids&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&amp;#8230; so I wanted to automatically add the &lt;em&gt;:user&lt;/em&gt; role when &lt;em&gt;@user.role_ids&lt;/em&gt; was set. Initially I tried adding a &amp;#8216;before_filter&amp;#8217; to the &lt;em&gt;User&lt;/em&gt; model:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  
  &lt;span class="n"&gt;has_and_belongs_to_many&lt;/span&gt; &lt;span class="ss"&gt;:roles&lt;/span&gt;
  
  &lt;span class="n"&gt;before_filter&lt;/span&gt; &lt;span class="ss"&gt;:add_default_roles&lt;/span&gt;
  
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_default_roles&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:role_ids&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Role&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Obviously this didn’t work &amp;#8211; setting the &lt;em&gt;habtm&lt;/em&gt; field in this case happens &lt;em&gt;after&lt;/em&gt; the model is saved (as you can see in the 2 lines from the controller above).&lt;/p&gt;
&lt;p&gt;Next I tried to over-ride the &lt;em&gt;roles&lt;/em&gt; setter in the model :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  
  &lt;span class="n"&gt;has_and_belongs_to_many&lt;/span&gt; &lt;span class="ss"&gt;:roles&lt;/span&gt;
  
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;role_ids&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_role_ids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_role_ids&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Role&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_role_ids&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The obvious (in hindsight) problem with this is that it is recursive &amp;#8211; setting &lt;em&gt;self.role_ids&lt;/em&gt; from inside the setter calls itself again, and results in a &lt;em&gt;stack level too deep&lt;/em&gt; error. This recursive call can be fixed by changing the line&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_role_ids&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:role_ids&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_role_ids&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;or even&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;write_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:role_ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_role_ids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This fixes the recursion problem, but still doesn&amp;#8217;t add the default role properly, due to some complexities with the way &lt;em&gt;habtm&lt;/em&gt; is implemented.&lt;/p&gt;
&lt;p&gt;After a lot of digging around I came up with a solution that works using &lt;em&gt;alias_method_chain&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  
  &lt;span class="n"&gt;has_and_belongs_to_many&lt;/span&gt; &lt;span class="ss"&gt;:roles&lt;/span&gt;
  
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  
  &lt;span class="c1"&gt;# Make sure all users have at least the :user role.&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;role_ids_with_add_user_role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_role_ids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_role_ids&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Role&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:role_ids&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_role_ids&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role_ids_without_add_user_role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_role_ids&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt; 
  &lt;span class="n"&gt;alias_method_chain&lt;/span&gt; &lt;span class="ss"&gt;:role_ids&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:add_user_role&lt;/span&gt;  
  
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;After some testing this seems to do exactly what we need &amp;#8211; when &lt;em&gt;@user.role_ids&lt;/em&gt; is set, the &lt;em&gt;role_ids_with_add_user_role&lt;/em&gt; function is called, and adds the &lt;em&gt;:user&lt;/em&gt; role to the list of role ids before saving.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/6jypHFVmi90" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2010/10/03/habtm-before-filter-in-rails-models</feedburner:origLink></entry>
 
 <entry>
   <title>Excluding fields from rails json and xml output</title>
   <link href="http://feedproxy.google.com/~r/recursive-design/feed/~3/B9YEKhg1nXg/excluding-fields-from-rails-json-and-xml-output" />
   <updated>2010-10-03T00:00:00+13:00</updated>
   <id>http://recursive-design.com/blog/2010/10/03/excluding-fields-from-rails-json-and-xml-output</id>
   <content type="html">&lt;time datetime="2010-10-03T00:00:00+13:00"&gt;&lt;span class="month"&gt;&lt;span class="caps"&gt;OCT&lt;/span&gt;&lt;/span&gt; &lt;span class="day"&gt;03&lt;/span&gt; &lt;span class="year"&gt;2010&lt;/span&gt; &lt;/time&gt;
&lt;h2&gt;&lt;a href="/blog/2010/10/03/excluding-fields-from-rails-json-and-xml-output"&gt;Excluding fields from rails json and xml output&lt;/a&gt;&lt;/h2&gt;
&lt;div class="categories"&gt;
Filed under &lt;a href="/blog/category/json/"&gt;json&lt;/a&gt;, &lt;a href="/blog/category/quickie/"&gt;quickie&lt;/a&gt;, &lt;a href="/blog/category/rails/"&gt;rails&lt;/a&gt;, &lt;a href="/blog/category/rest/"&gt;rest&lt;/a&gt;, &lt;a href="/blog/category/ruby/"&gt;ruby&lt;/a&gt;, and &lt;a href="/blog/category/xml/"&gt;xml&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;Rails has a very handy &amp;#8216;respond_to&amp;#8217; feature to render your pages in different formats :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:json&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xml&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:xml&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;      
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;However, by default it outputs every field in the model, which exposes some data (&lt;em&gt;encrypted-password&lt;/em&gt; and &lt;em&gt;password-salt&lt;/em&gt;) that I&amp;#8217;d rather keep to myself :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="xml"&gt;&lt;span class="nt"&gt;&amp;lt;user&amp;gt;&lt;/span&gt; 
  &lt;span class="nt"&gt;&amp;lt;encrypted-password&amp;gt;&lt;/span&gt;$2a$10$a2K.PXEXpgpWH6MMLD/AFe84mjB4u3ZNf4MYTPten42LkPpjd.wZm&lt;span class="nt"&gt;&amp;lt;/encrypted-password&amp;gt;&lt;/span&gt; 
  &lt;span class="nt"&gt;&amp;lt;created-at&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;datetime&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;2010-10-02T00:12:43Z&lt;span class="nt"&gt;&amp;lt;/created-at&amp;gt;&lt;/span&gt; 
  &lt;span class="nt"&gt;&amp;lt;updated-at&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;datetime&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;2010-10-03T03:28:27Z&lt;span class="nt"&gt;&amp;lt;/updated-at&amp;gt;&lt;/span&gt;  
  &lt;span class="nt"&gt;&amp;lt;id&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;integer&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;12&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt; 
  &lt;span class="nt"&gt;&amp;lt;password-salt&amp;gt;&lt;/span&gt;$2a$10$a2K.PXEXpgpWH6MMLD/AFe&lt;span class="nt"&gt;&amp;lt;/password-salt&amp;gt;&lt;/span&gt; 
  &lt;span class="nt"&gt;&amp;lt;email&amp;gt;&lt;/span&gt;mail@recursive-design.com&lt;span class="nt"&gt;&amp;lt;/email&amp;gt;&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;/user&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Luckily, you can disable specific fields using the &lt;em&gt;except&lt;/em&gt; option :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:json&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:except&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:encrypted_password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password_salt&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xml&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:xml&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:except&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:encrypted_password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password_salt&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;      
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&amp;#8230; which removes the offending fields from output :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="xml"&gt;&lt;span class="nt"&gt;&amp;lt;user&amp;gt;&lt;/span&gt; 
  &lt;span class="nt"&gt;&amp;lt;created-at&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;datetime&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;2010-10-02T00:12:43Z&lt;span class="nt"&gt;&amp;lt;/created-at&amp;gt;&lt;/span&gt; 
  &lt;span class="nt"&gt;&amp;lt;updated-at&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;datetime&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;2010-10-03T03:28:27Z&lt;span class="nt"&gt;&amp;lt;/updated-at&amp;gt;&lt;/span&gt;  
  &lt;span class="nt"&gt;&amp;lt;id&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;integer&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;12&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt; 
  &lt;span class="nt"&gt;&amp;lt;email&amp;gt;&lt;/span&gt;dave@recurser.com&lt;span class="nt"&gt;&amp;lt;/email&amp;gt;&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;/user&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you find yourself doing this in a lot of different places, it may be easier to filter these options at the model level, by over-riding the &amp;#8216;to_json&amp;#8217; and &amp;#8216;to_xml&amp;#8217; methods :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
   
   &lt;span class="c1"&gt;# Exclude password info from xml output.&lt;/span&gt;
   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_xml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
     &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:except&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:encrypted_password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password_salt&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
     &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
   
   &lt;span class="c1"&gt;# Exclude password info from json output.&lt;/span&gt;
   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
     &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:except&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:encrypted_password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password_salt&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
     &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/recursive-design/feed/~4/B9YEKhg1nXg" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://recursive-design.com/blog/2010/10/03/excluding-fields-from-rails-json-and-xml-output</feedburner:origLink></entry>
 
 
</feed>

