<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Brandon Harris Web Development</title>
  <link rel="alternate" type="text/html" href="http://brandon-harris.com" />
  <link rel="self" type="application/atom+xml" href="http://brandon-harris.com/posts.atom" />
  <id>http://brandon-harris.com/posts.atom</id>
  <updated>2011-12-11T23:21:44Z</updated>
  <subtitle>The tidbits, musings, tips and thoughts of brandon harris as he journeys through his web development profession.  Mostly focused on Ruby on Rails.</subtitle>

    
  <entry>
    <title>We are the Privileged 150k</title>
    <link rel='alternate' type='text/html' href='/general/2011/12/11/We-are-the-privileged-150k.html' />
    <id>tag:brandon-harris.com:/general/2011/12/11/We-are-the-privileged-150k</id>
    <updated>2011-12-11T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>The majority of the world dreams to make more than 100k a year. Yet, in the tech community, we refuse to train those dreamers. Instead we pine after "rockstars" and "ninjas".</p>
<p>I am happy to see the global tech community pay attention to our burgeoning tech community in Austin. The truth is, Austin has been part of the tech community as long as Silicon Valley has existed. I recently had lunch with a startup founder who eloquently pulled me through the trenches of his trek to his current successes. These include building one of the worlds first online credit card processing websites. Back then, they had to connect to FileMaker Pro as their database - oh the Humanity!</p>
<p>We have a <a href="http://www.rssweather.com/climate/Texas/Austin%20City/">great climate</a>, a vibrant young population, kick ass night life, <a href="http://www.aclfestival.com/">an awesome music festival</a>, <a href="http://sxsw.com/">a party with a conference</a> and great food. It really comes as no surprise that young ambitious entreprenuers would put Austin on the very short list of "cool" places to live.</p>
<p>For a while, the tech community has discussed a glut in talent required at new startups in Austin as well as Silicon Valley. Mostly, I am pointing to <a href="http://news.ycombinator.com/item?id=3341412">recent</a> <a href="http://news.ycombinator.com/item?id=3339236">discussions</a> on Hacker News.</p>
<p>It seems that the local newspaper has <a href="http://www.statesman.com/business/technology/austin-battles-shortage-in-high-end-software-engineering-2024970.html?viewAsSinglePage=true">published a misleading article</a> about the current situation as it applies to employers and their insatiable desire for top talent. According to the article, recruiters flew out to California and attempted to sway Silicon Valley development talent into a relocation to central texas. Oh, and money. A lot of money.</p>
<p>I am calling bullshit. There is no one in the development community telling stories of being offered 150k or anywhere near that number. This is a lame article meant to inspire the next generation of students to dive into the currently lucrative world of software engineering. Everyday it seems like we read about developers who cant write fizz-buzz in an interview and suddenly by magic surprise, the businesses are complaining about a lack of talent? I call it a lack of employee investment. If companies and startups spent their time finding sharp people and shaping them into what they are looking for, I submit that as a world society we would be in a better situation. However, it appears that middle to large startups on a "funded" and "limited" budget would rather spend money on a non-fortuitious business trip in an attempt to persuade a bunch of freeloading developers into moving to a place they have no interest in relocating to. I have an idea. How about training the people that you have right at home? Why not invest in the local community and increase your own technical capital instead of poaching?</p>
<p>We have a vibrant and healthy community. If you asked me, I could name a dozen top notch developers who are more than capable of making a businessmans dreams come true, and they are not demanding 150k a year. To put this into perspective, ONE of <a href="http://austinonrails.org">our local Ruby on Rails monthly meetups</a> exceeds 70 people regularly. People are hungry to learn, and I bet everyone of those 70 could pass fizz-buzz - some with a little training.</p>
<p>In fact I find it far more common to run into a talented individual who is more in tune with performing social good than incurring self benefit. As a person who prescribes to capitalism, I find this rather interesting. Instead of demanding compensation, these people want a better way of life and they want to solve problems that would inevitably make the world a better place.</p>
<p>How's that food for thought? A skill that could land a 150k job, yet the fruits of their labor are given away for free and for the greater good. We [as developers] understand the privilege that we possess in a modern technical society. We understand that we can demand so much more. Most of us don't. We give our code away for free, we want to work from home, and we want to work in an environment that nurtures our good nature.</p>
<p>TL;DR; Who cares about the compensation amount when you are doing it wrong! Train your local pool and build your community. You invested in your company, now invest in the people and community around it!</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>The majority of the world dreams to make more than 100k a year. Yet, in the tech community, we refuse to train those dreamers. Instead we pine after "rockstars" and "ninjas".</p>
<p>I am happy to see the global tech community pay attention to our burgeoning tech community in Austin. The truth is, Austin has been part of the tech community as long as Silicon Valley has existed. I recently had lunch with a startup founder who eloquently pulled me through the trenches of his trek to his current successes. These include building one of the worlds first online credit card processing websites. Back then, they had to connect to FileMaker Pro as their database - oh the Humanity!</p>
<p>We have a <a href="http://www.rssweather.com/climate/Texas/Austin%20City/">great climate</a>, a vibrant young population, kick ass night life, <a href="http://www.aclfestival.com/">an awesome music festival</a>, <a href="http://sxsw.com/">a party with a conference</a> and great food. It really comes as no surprise that young ambitious entreprenuers would put Austin on the very short list of "cool" places to live.</p>
<p>For a while, the tech community has discussed a glut in talent required at new startups in Austin as well as Silicon Valley. Mostly, I am pointing to <a href="http://news.ycombinator.com/item?id=3341412">recent</a> <a href="http://news.ycombinator.com/item?id=3339236">discussions</a> on Hacker News.</p>
<p>It seems that the local newspaper has <a href="http://www.statesman.com/business/technology/austin-battles-shortage-in-high-end-software-engineering-2024970.html?viewAsSinglePage=true">published a misleading article</a> about the current situation as it applies to employers and their insatiable desire for top talent. According to the article, recruiters flew out to California and attempted to sway Silicon Valley development talent into a relocation to central texas. Oh, and money. A lot of money.</p>
<p>I am calling bullshit. There is no one in the development community telling stories of being offered 150k or anywhere near that number. This is a lame article meant to inspire the next generation of students to dive into the currently lucrative world of software engineering. Everyday it seems like we read about developers who cant write fizz-buzz in an interview and suddenly by magic surprise, the businesses are complaining about a lack of talent? I call it a lack of employee investment. If companies and startups spent their time finding sharp people and shaping them into what they are looking for, I submit that as a world society we would be in a better situation. However, it appears that middle to large startups on a "funded" and "limited" budget would rather spend money on a non-fortuitious business trip in an attempt to persuade a bunch of freeloading developers into moving to a place they have no interest in relocating to. I have an idea. How about training the people that you have right at home? Why not invest in the local community and increase your own technical capital instead of poaching?</p>
<p>We have a vibrant and healthy community. If you asked me, I could name a dozen top notch developers who are more than capable of making a businessmans dreams come true, and they are not demanding 150k a year. To put this into perspective, ONE of <a href="http://austinonrails.org">our local Ruby on Rails monthly meetups</a> exceeds 70 people regularly. People are hungry to learn, and I bet everyone of those 70 could pass fizz-buzz - some with a little training.</p>
<p>In fact I find it far more common to run into a talented individual who is more in tune with performing social good than incurring self benefit. As a person who prescribes to capitalism, I find this rather interesting. Instead of demanding compensation, these people want a better way of life and they want to solve problems that would inevitably make the world a better place.</p>
<p>How's that food for thought? A skill that could land a 150k job, yet the fruits of their labor are given away for free and for the greater good. We [as developers] understand the privilege that we possess in a modern technical society. We understand that we can demand so much more. Most of us don't. We give our code away for free, we want to work from home, and we want to work in an environment that nurtures our good nature.</p>
<p>TL;DR; Who cares about the compensation amount when you are doing it wrong! Train your local pool and build your community. You invested in your company, now invest in the people and community around it!</p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>Thank You for Visiting</title>
    <link rel='alternate' type='text/html' href='/general/2011/11/30/thank-you-for-visiting.html' />
    <id>tag:brandon-harris.com:/general/2011/11/30/thank-you-for-visiting</id>
    <updated>2011-11-30T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>Im assuming that as of the writing of this, you arrived here in search of <a href="http://www.gaijin.com/">Brandon Harris the wikipedia programmer</a>.</p>
<p>If you happen to be interested in some of the topics that I occasionally post here, please feel free to subscribe or follow me on twitter.</p>
<p>Brandon did an <a href="http://www.reddit.com/r/IAmA/comments/mr4pf/i_am_wikipedia_programmer_brandon_harris_ama/">AMA on Reddit</a></p>
<p>If you are looking to donate to wikipedia (please do!) <a href="https://donate.wikimedia.org/wiki/Special:FundraiserLandingPage?&template=Lp-layout-default&appeal-template=Appeal-template-default&appeal=Appeal-Brandon&form-template=Form-template-default&form-countryspecific=Form-countryspecific-control&utm_medium=sitenotice&utm_source=socialmedia&utm_campaign=C11_socialmedia_reddit">this is the link that you are looking for</a></p>
<p>Thanks for visiting!</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>Im assuming that as of the writing of this, you arrived here in search of <a href="http://www.gaijin.com/">Brandon Harris the wikipedia programmer</a>.</p>
<p>If you happen to be interested in some of the topics that I occasionally post here, please feel free to subscribe or follow me on twitter.</p>
<p>Brandon did an <a href="http://www.reddit.com/r/IAmA/comments/mr4pf/i_am_wikipedia_programmer_brandon_harris_ama/">AMA on Reddit</a></p>
<p>If you are looking to donate to wikipedia (please do!) <a href="https://donate.wikimedia.org/wiki/Special:FundraiserLandingPage?&template=Lp-layout-default&appeal-template=Appeal-template-default&appeal=Appeal-Brandon&form-template=Form-template-default&form-countryspecific=Form-countryspecific-control&utm_medium=sitenotice&utm_source=socialmedia&utm_campaign=C11_socialmedia_reddit">this is the link that you are looking for</a></p>
<p>Thanks for visiting!</p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>Rails Simple Page Caching</title>
    <link rel='alternate' type='text/html' href='/rails/2011/04/12/rails-simple-page-caching.html' />
    <id>tag:brandon-harris.com:/rails/2011/04/12/rails-simple-page-caching</id>
    <updated>2011-04-12T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>Memcache is great, and Redis is even better. But you are still bound to a database, and running services. We are so caught up in making everything dynamic, that I think we don't often realize that we are still serving up mostly static html. The good news is that Rails has static html caching built in, and I rarely notice anyone talking about it.</p>
<p><strong>The scenario:</strong> You want to input your page content via an administrative interface, but this data rarely changes. Another way to look at it, the content only changes if you or someone who administers the site has a need to change it. Rails page caching is your friend.</p>

<p>Let's say you have this code:</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno"> 1</span> <span class="c1"># application.rb</span>
<span class="lineno"> 2</span> <span class="n">config</span><span class="o">.</span><span class="n">action_controller</span><span class="o">.</span><span class="n">page_cache_directory</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="o">::</span><span class="no">Rails</span><span class="o">.</span><span class="n">root</span><span class="si">}</span><span class="s2">/public/cache&quot;</span>
<span class="lineno"> 3</span> 
<span class="lineno"> 4</span> <span class="c1"># routes.rb</span>
<span class="lineno"> 5</span> <span class="n">match</span> <span class="s1">&#39;/:url&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;pages#show&#39;</span>
<span class="lineno"> 6</span> 
<span class="lineno"> 7</span> <span class="c1"># Simple page class page.rb</span>
<span class="lineno"> 8</span> <span class="k">class</span> <span class="nc">Page</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
<span class="lineno"> 9</span> <span class="k">end</span>
<span class="lineno">10</span> 
<span class="lineno">11</span> <span class="c1">#simple pages controller pages_controller.rb</span>
<span class="lineno">12</span> <span class="k">class</span> <span class="nc">PagesController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
<span class="lineno">13</span>   <span class="n">caches_page</span> <span class="ss">:show</span><span class="p">,</span> <span class="ss">:cache_path</span> <span class="o">=&gt;</span> <span class="nb">lambda</span> <span class="p">{</span><span class="o">|</span><span class="n">controller</span><span class="o">|</span> <span class="n">controller</span><span class="o">.</span><span class="n">params</span><span class="p">}</span>
<span class="lineno">14</span> 
<span class="lineno">15</span>   <span class="k">def</span> <span class="nf">show</span>
<span class="lineno">16</span>     <span class="vi">@page</span> <span class="o">=</span> <span class="no">Page</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="ss">:url</span> <span class="o">=&gt;</span> <span class="n">params</span><span class="o">[</span><span class="ss">:url</span><span class="o">]</span><span class="p">)</span><span class="o">.</span><span class="n">first</span>
<span class="lineno">17</span>     <span class="n">render</span> <span class="ss">:file</span> <span class="o">=&gt;</span> <span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="o">::</span><span class="no">Rails</span><span class="o">.</span><span class="n">root</span><span class="p">,</span><span class="s2">&quot;public&quot;</span><span class="p">,</span><span class="s2">&quot;404.html&quot;</span><span class="p">)</span> <span class="k">if</span> <span class="vi">@page</span><span class="o">.</span><span class="n">nil?</span>
<span class="lineno">18</span>   <span class="k">end</span>
<span class="lineno">19</span> 
<span class="lineno">20</span> <span class="k">end</span>
</code></pre>
</div>


<p>Now, let's skip ahead real quick and write up a quick show template for this dynamic page.</p>

<div class="highlight"><pre><code class="haml"><span class="lineno">1</span>   <span class="cp">-# show.html.haml</span>
<span class="lineno">2</span>   <span class="nt">%h2</span><span class="p">=</span> <span class="vi">@page</span><span class="o">.</span><span class="n">title</span>
<span class="lineno">3</span>   <span class="p">=</span> <span class="vi">@page</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">html_safe</span>
</code></pre>
</div>


<p>The good stuff occurs in the pages_controller.rb file.  Line #13 states: "Cache pages for the show action, use the params for the file name". This is a little lazy on my part, since the params should only contain the :url, this will work. If there are more complex params, you will need to modify that singleton. Since we set the page_cache_directory to a cache folder in public, we can expect to see our generated files appearing in there.</p>
<p>The best part about this setup is that it works, and no plugins are needed. You will need to modify your webserver to look in the cache directory first, then proceed to the rails application.</p>

<p>What if you make changes? Wont you see the generated version instead of the updated version? In this case, yes. You will need to write a cache sweeper, a very trivial task. Here's a version of one that I found, but it may not be what you want. I am not making use of ActionController::Caching::Sweeping, because I have more global cache sweeping needs</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno"> 1</span> <span class="c1"># config/application.rb</span>
<span class="lineno"> 2</span> <span class="n">config</span><span class="o">.</span><span class="n">active_record</span><span class="o">.</span><span class="n">observers</span> <span class="o">=</span> <span class="ss">:cache_sweeper</span>
<span class="lineno"> 3</span> 
<span class="lineno"> 4</span> <span class="c1"># app/models/cache_sweeper.rb</span>
<span class="lineno"> 5</span> <span class="k">class</span> <span class="nc">CacheSweeper</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Observer</span>
<span class="lineno"> 6</span>   <span class="c1"># Add any other models that Page may depend on here</span>
<span class="lineno"> 7</span>   <span class="n">observe</span> <span class="no">Page</span>
<span class="lineno"> 8</span> 
<span class="lineno"> 9</span>   <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">sweep_cache!</span>
<span class="lineno">10</span>     <span class="no">Dir</span><span class="o">.</span><span class="n">glob</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">#{</span><span class="no">ActionController</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">page_cache_directory</span><span class="si">}</span><span class="s2">/**/*.html&quot;</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">f</span><span class="o">|</span>
<span class="lineno">11</span>       <span class="no">File</span><span class="o">.</span><span class="n">delete</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="lineno">12</span>     <span class="k">end</span>
<span class="lineno">13</span>   <span class="k">end</span>
<span class="lineno">14</span> 
<span class="lineno">15</span>   <span class="k">def</span> <span class="nf">after_save</span><span class="p">(</span><span class="o">*</span><span class="n">_</span><span class="p">)</span>
<span class="lineno">16</span>     <span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">sweep_cache!</span>
<span class="lineno">17</span>   <span class="k">end</span>
<span class="lineno">18</span> 
<span class="lineno">19</span>   <span class="k">def</span> <span class="nf">after_destroy</span><span class="p">(</span><span class="o">*</span><span class="n">_</span><span class="p">)</span>
<span class="lineno">20</span>     <span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">sweep_cache!</span>
<span class="lineno">21</span>   <span class="k">end</span>
<span class="lineno">22</span> 
<span class="lineno">23</span> <span class="k">end</span>
</code></pre>
</div>


<p>This good because it errors in favor of regenerating files when any change is made. This is bad if you are extremely worried about performance and don't like it when any of your users touches your database to regenerate a "dynamic" page.</p>
<p>If you are really concerned about page performance on mostly static sites, check out jekyll, this blog runs on it. Generate your pages once and never worry again. However, if you have requirements where people need to edit a page from your web app, rails caching is your free friend.</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>Memcache is great, and Redis is even better. But you are still bound to a database, and running services. We are so caught up in making everything dynamic, that I think we don't often realize that we are still serving up mostly static html. The good news is that Rails has static html caching built in, and I rarely notice anyone talking about it.</p>
<p><strong>The scenario:</strong> You want to input your page content via an administrative interface, but this data rarely changes. Another way to look at it, the content only changes if you or someone who administers the site has a need to change it. Rails page caching is your friend.</p>

<p>Let's say you have this code:</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno"> 1</span> <span class="c1"># application.rb</span>
<span class="lineno"> 2</span> <span class="n">config</span><span class="o">.</span><span class="n">action_controller</span><span class="o">.</span><span class="n">page_cache_directory</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="o">::</span><span class="no">Rails</span><span class="o">.</span><span class="n">root</span><span class="si">}</span><span class="s2">/public/cache&quot;</span>
<span class="lineno"> 3</span> 
<span class="lineno"> 4</span> <span class="c1"># routes.rb</span>
<span class="lineno"> 5</span> <span class="n">match</span> <span class="s1">&#39;/:url&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;pages#show&#39;</span>
<span class="lineno"> 6</span> 
<span class="lineno"> 7</span> <span class="c1"># Simple page class page.rb</span>
<span class="lineno"> 8</span> <span class="k">class</span> <span class="nc">Page</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
<span class="lineno"> 9</span> <span class="k">end</span>
<span class="lineno">10</span> 
<span class="lineno">11</span> <span class="c1">#simple pages controller pages_controller.rb</span>
<span class="lineno">12</span> <span class="k">class</span> <span class="nc">PagesController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
<span class="lineno">13</span>   <span class="n">caches_page</span> <span class="ss">:show</span><span class="p">,</span> <span class="ss">:cache_path</span> <span class="o">=&gt;</span> <span class="nb">lambda</span> <span class="p">{</span><span class="o">|</span><span class="n">controller</span><span class="o">|</span> <span class="n">controller</span><span class="o">.</span><span class="n">params</span><span class="p">}</span>
<span class="lineno">14</span> 
<span class="lineno">15</span>   <span class="k">def</span> <span class="nf">show</span>
<span class="lineno">16</span>     <span class="vi">@page</span> <span class="o">=</span> <span class="no">Page</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="ss">:url</span> <span class="o">=&gt;</span> <span class="n">params</span><span class="o">[</span><span class="ss">:url</span><span class="o">]</span><span class="p">)</span><span class="o">.</span><span class="n">first</span>
<span class="lineno">17</span>     <span class="n">render</span> <span class="ss">:file</span> <span class="o">=&gt;</span> <span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="o">::</span><span class="no">Rails</span><span class="o">.</span><span class="n">root</span><span class="p">,</span><span class="s2">&quot;public&quot;</span><span class="p">,</span><span class="s2">&quot;404.html&quot;</span><span class="p">)</span> <span class="k">if</span> <span class="vi">@page</span><span class="o">.</span><span class="n">nil?</span>
<span class="lineno">18</span>   <span class="k">end</span>
<span class="lineno">19</span> 
<span class="lineno">20</span> <span class="k">end</span>
</code></pre>
</div>


<p>Now, let's skip ahead real quick and write up a quick show template for this dynamic page.</p>

<div class="highlight"><pre><code class="haml"><span class="lineno">1</span>   <span class="cp">-# show.html.haml</span>
<span class="lineno">2</span>   <span class="nt">%h2</span><span class="p">=</span> <span class="vi">@page</span><span class="o">.</span><span class="n">title</span>
<span class="lineno">3</span>   <span class="p">=</span> <span class="vi">@page</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">html_safe</span>
</code></pre>
</div>


<p>The good stuff occurs in the pages_controller.rb file.  Line #13 states: "Cache pages for the show action, use the params for the file name". This is a little lazy on my part, since the params should only contain the :url, this will work. If there are more complex params, you will need to modify that singleton. Since we set the page_cache_directory to a cache folder in public, we can expect to see our generated files appearing in there.</p>
<p>The best part about this setup is that it works, and no plugins are needed. You will need to modify your webserver to look in the cache directory first, then proceed to the rails application.</p>

<p>What if you make changes? Wont you see the generated version instead of the updated version? In this case, yes. You will need to write a cache sweeper, a very trivial task. Here's a version of one that I found, but it may not be what you want. I am not making use of ActionController::Caching::Sweeping, because I have more global cache sweeping needs</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno"> 1</span> <span class="c1"># config/application.rb</span>
<span class="lineno"> 2</span> <span class="n">config</span><span class="o">.</span><span class="n">active_record</span><span class="o">.</span><span class="n">observers</span> <span class="o">=</span> <span class="ss">:cache_sweeper</span>
<span class="lineno"> 3</span> 
<span class="lineno"> 4</span> <span class="c1"># app/models/cache_sweeper.rb</span>
<span class="lineno"> 5</span> <span class="k">class</span> <span class="nc">CacheSweeper</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Observer</span>
<span class="lineno"> 6</span>   <span class="c1"># Add any other models that Page may depend on here</span>
<span class="lineno"> 7</span>   <span class="n">observe</span> <span class="no">Page</span>
<span class="lineno"> 8</span> 
<span class="lineno"> 9</span>   <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">sweep_cache!</span>
<span class="lineno">10</span>     <span class="no">Dir</span><span class="o">.</span><span class="n">glob</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">#{</span><span class="no">ActionController</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">page_cache_directory</span><span class="si">}</span><span class="s2">/**/*.html&quot;</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">f</span><span class="o">|</span>
<span class="lineno">11</span>       <span class="no">File</span><span class="o">.</span><span class="n">delete</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="lineno">12</span>     <span class="k">end</span>
<span class="lineno">13</span>   <span class="k">end</span>
<span class="lineno">14</span> 
<span class="lineno">15</span>   <span class="k">def</span> <span class="nf">after_save</span><span class="p">(</span><span class="o">*</span><span class="n">_</span><span class="p">)</span>
<span class="lineno">16</span>     <span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">sweep_cache!</span>
<span class="lineno">17</span>   <span class="k">end</span>
<span class="lineno">18</span> 
<span class="lineno">19</span>   <span class="k">def</span> <span class="nf">after_destroy</span><span class="p">(</span><span class="o">*</span><span class="n">_</span><span class="p">)</span>
<span class="lineno">20</span>     <span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">sweep_cache!</span>
<span class="lineno">21</span>   <span class="k">end</span>
<span class="lineno">22</span> 
<span class="lineno">23</span> <span class="k">end</span>
</code></pre>
</div>


<p>This good because it errors in favor of regenerating files when any change is made. This is bad if you are extremely worried about performance and don't like it when any of your users touches your database to regenerate a "dynamic" page.</p>
<p>If you are really concerned about page performance on mostly static sites, check out jekyll, this blog runs on it. Generate your pages once and never worry again. However, if you have requirements where people need to edit a page from your web app, rails caching is your free friend.</p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>JSON Templates in Rails</title>
    <link rel='alternate' type='text/html' href='/rails/2011/03/29/json-templates-in-rails.html' />
    <id>tag:brandon-harris.com:/rails/2011/03/29/json-templates-in-rails</id>
    <updated>2011-03-29T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>Sometimes, you just don't want to do call the "to_json" message on an object. It could be that the object has a lot of attributes, the json needs are very simple, or you simply don't like the default structure.</p>
<p>Fortunately, there is a very easy solution: JSON templates. This is built in, and you might have not even known it.</p>
<p>In my case, I wanted to plot a bunch of people and their locations on a map. I had the following model:</p>
<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="k">class</span> <span class="nc">Person</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
<span class="lineno">2</span>   <span class="c1"># ...</span>
<span class="lineno">3</span> 
<span class="lineno">4</span>   <span class="k">def</span> <span class="nf">geo_location</span>
<span class="lineno">5</span>     <span class="o">[</span><span class="n">latitude</span><span class="p">,</span><span class="n">longitude</span><span class="o">].</span><span class="n">compact</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="p">)</span>
<span class="lineno">6</span>   <span class="k">end</span>
<span class="lineno">7</span> 
<span class="lineno">8</span>   <span class="c1"># ...</span>
<span class="lineno">9</span> <span class="k">end</span>
</code></pre>
</div>


<p>I have the following controller:</p>
<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="k">class</span> <span class="nc">PeopleController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
<span class="lineno">2</span>   <span class="n">respond_to</span> <span class="ss">:html</span><span class="p">,</span> <span class="ss">:json</span>
<span class="lineno">3</span> 
<span class="lineno">4</span>   <span class="k">def</span> <span class="nf">index</span>
<span class="lineno">5</span>    <span class="vi">@people</span> <span class="o">=</span> <span class="no">Person</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="ss">:all</span><span class="p">)</span>
<span class="lineno">6</span>    <span class="n">respond_with</span><span class="p">(</span><span class="vi">@people</span><span class="p">)</span>
<span class="lineno">7</span>   <span class="k">end</span>
<span class="lineno">8</span>   <span class="c1"># ...</span>
<span class="lineno">9</span> <span class="k">end</span>
</code></pre>
</div>


<p>Now, create index.json.erb.  I tried doing this with haml, but I really didn't like the way I had to handle the necessary whitespace.  Your call if you want to use it.</p>

<div class="highlight"><pre><code class="erb"><span class="lineno">1</span> <span class="x">[</span>
<span class="lineno">2</span> <span class="cp">&lt;%-</span> <span class="vi">@people</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="nb">p</span><span class="o">|</span> <span class="cp">%&gt;</span><span class="x"></span>
<span class="lineno">3</span> <span class="x">  {</span>
<span class="lineno">4</span> <span class="x">    &quot;id&quot;: &quot;</span><span class="cp">&lt;%=</span><span class="nb">p</span><span class="o">.</span><span class="n">id</span> <span class="cp">%&gt;</span><span class="x">&quot;,</span>
<span class="lineno">5</span> <span class="x">    &quot;location&quot;: &quot;</span><span class="cp">&lt;%=</span> <span class="nb">p</span><span class="o">.</span><span class="n">location</span> <span class="cp">%&gt;</span><span class="x">&quot;</span>
<span class="lineno">6</span> <span class="x">  },</span>
<span class="lineno">7</span> <span class="cp">&lt;%</span> <span class="k">end</span> <span class="cp">%&gt;</span><span class="x"></span>
<span class="lineno">8</span> <span class="x">{}]</span>
</code></pre>
</div>


<p> There is a wart, the trailing {}.  I didn't want to include any logic, as it would slow down this rather large dataset.  The whole reason I am doing it this way is for speed.  I have no need to display all the attribute data from the "people" table, I just need to plot a heat map. Suggestions are welcome, the side effect is that the last point that is attempted to be plotted, is ignored.</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>Sometimes, you just don't want to do call the "to_json" message on an object. It could be that the object has a lot of attributes, the json needs are very simple, or you simply don't like the default structure.</p>
<p>Fortunately, there is a very easy solution: JSON templates. This is built in, and you might have not even known it.</p>
<p>In my case, I wanted to plot a bunch of people and their locations on a map. I had the following model:</p>
<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="k">class</span> <span class="nc">Person</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
<span class="lineno">2</span>   <span class="c1"># ...</span>
<span class="lineno">3</span> 
<span class="lineno">4</span>   <span class="k">def</span> <span class="nf">geo_location</span>
<span class="lineno">5</span>     <span class="o">[</span><span class="n">latitude</span><span class="p">,</span><span class="n">longitude</span><span class="o">].</span><span class="n">compact</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="p">)</span>
<span class="lineno">6</span>   <span class="k">end</span>
<span class="lineno">7</span> 
<span class="lineno">8</span>   <span class="c1"># ...</span>
<span class="lineno">9</span> <span class="k">end</span>
</code></pre>
</div>


<p>I have the following controller:</p>
<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="k">class</span> <span class="nc">PeopleController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
<span class="lineno">2</span>   <span class="n">respond_to</span> <span class="ss">:html</span><span class="p">,</span> <span class="ss">:json</span>
<span class="lineno">3</span> 
<span class="lineno">4</span>   <span class="k">def</span> <span class="nf">index</span>
<span class="lineno">5</span>    <span class="vi">@people</span> <span class="o">=</span> <span class="no">Person</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="ss">:all</span><span class="p">)</span>
<span class="lineno">6</span>    <span class="n">respond_with</span><span class="p">(</span><span class="vi">@people</span><span class="p">)</span>
<span class="lineno">7</span>   <span class="k">end</span>
<span class="lineno">8</span>   <span class="c1"># ...</span>
<span class="lineno">9</span> <span class="k">end</span>
</code></pre>
</div>


<p>Now, create index.json.erb.  I tried doing this with haml, but I really didn't like the way I had to handle the necessary whitespace.  Your call if you want to use it.</p>

<div class="highlight"><pre><code class="erb"><span class="lineno">1</span> <span class="x">[</span>
<span class="lineno">2</span> <span class="cp">&lt;%-</span> <span class="vi">@people</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="nb">p</span><span class="o">|</span> <span class="cp">%&gt;</span><span class="x"></span>
<span class="lineno">3</span> <span class="x">  {</span>
<span class="lineno">4</span> <span class="x">    &quot;id&quot;: &quot;</span><span class="cp">&lt;%=</span><span class="nb">p</span><span class="o">.</span><span class="n">id</span> <span class="cp">%&gt;</span><span class="x">&quot;,</span>
<span class="lineno">5</span> <span class="x">    &quot;location&quot;: &quot;</span><span class="cp">&lt;%=</span> <span class="nb">p</span><span class="o">.</span><span class="n">location</span> <span class="cp">%&gt;</span><span class="x">&quot;</span>
<span class="lineno">6</span> <span class="x">  },</span>
<span class="lineno">7</span> <span class="cp">&lt;%</span> <span class="k">end</span> <span class="cp">%&gt;</span><span class="x"></span>
<span class="lineno">8</span> <span class="x">{}]</span>
</code></pre>
</div>


<p> There is a wart, the trailing {}.  I didn't want to include any logic, as it would slow down this rather large dataset.  The whole reason I am doing it this way is for speed.  I have no need to display all the attribute data from the "people" table, I just need to plot a heat map. Suggestions are welcome, the side effect is that the last point that is attempted to be plotted, is ignored.</p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>Matrox DualHead2Go, TripleHead2Go on Ubuntu, with ATI/AMD</title>
    <link rel='alternate' type='text/html' href='/ubuntu/dualhead2go/triplehead2go/2011/02/01/matrox-dualhead2go-triplehead2go-on-ubuntu-with-ati-amd.html' />
    <id>tag:brandon-harris.com:/ubuntu/dualhead2go/triplehead2go/2011/02/01/matrox-dualhead2go-triplehead2go-on-ubuntu-with-ati-amd</id>
    <updated>2011-02-01T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>I recently purchased a <a href="http://www.matrox.com/graphics/en/products/gxm/dh2go/">matrox dualhead2go digital edition</a> off of ebay on a whim.  I did this because I wanted to make use of some extra monitors sitting around the office. I have also come to the realization that I have grown up as a developer and I have enough confidence to look anyone straight in the eye and say &#8211; &#8220;Yes, I need 3 monitors&#8221;.</p>
<p>My current setup is a Dell <span class="caps">XPS</span> 1640 running Ubuntu 10.04, with a Radeon 3670 graphics card. Yeah, enter the wonderful world of linux graphics drivers.</p>
<p>My first attempt was to simply, plug it in and see what would happen, resulted in a mild success.  I was able to have my laptop lcd set at a resolution of 1920&#215;1080 and the two 1680&#215;1050 monitors would only go up to 2560&#215;1024.  It looked warped, but it gave me a taste of what was possible.</p>
<p>After much configuring with <a href="https://wiki.ubuntu.com/X/Config/Resolution">xrandr &#8212;addmode, et. al ad nauseum</a>, I came to the conclusion that the matrox just wouldn&#8217;t support a higher resolution than 2560&#215;1024, even though the site claims that it will.  Some searching prompted me to discover that you need to configure the device to support your desired resolutions using the matrox powerdesk tool.  Windows and Mac users can rejoice, this exists for you both.  Linux users, go get on that old Windows test box that you use for IE testing and configure this mutha.</p>
<p>Armed with the following resolutions 3360&#215;1050, 3840&#215;1080, I set to work on my dream display.</p>
<p>I hit another snag. I could crank the resolution on my laptop, or the two 22&quot; monitors, but setting both to 11 caused really odd horizontal sync issues on my laptop.  The text would be fuzzy and move from side to side.  Clearly this wasn&#8217;t going to work using just Xrandr, and the Gnome Display tool.</p>
<p>This brings up another one of my errors.  DO <span class="caps">NOT</span> <span class="caps">USE</span> <span class="caps">THE</span> <span class="caps">GNOME</span> <span class="caps">DISPLAY</span> <span class="caps">TOOL</span> after using the <span class="caps">AMD</span>/<span class="caps">ATI</span> Catalyst Control panel.  The Gnome tool will nuke your xorg.conf file, and leave you scratching your head.  Once you go <span class="caps">FGLRX</span>, forget that the Gnome display tool even exists, and trust yourself to learn the <span class="caps">AMD</span>/<span class="caps">ATI</span> Catalyst Control Panel as well as the aticonfig command line tool.  If you are a complete badass and can handcraft your own xorg.conf file and modelines (why are you reading this?) skip ahead to the modeline cheats below.</p>
<p>I had clearly stepped into a limitation of the linux fglrx display driver, or so I thought.  At one point, I had inadvertently nuked my xorg.conf file, so fglrx was no longer being loaded. (See cautionary statement above) I went through the relatively simple process of <a href="https://wiki.ubuntu.com/X/Troubleshooting/FglrxInteferesWithRadeonDriver">removing all traces of fglrx from my system</a>. I reinstalled the proprietary drivers (because I also require dropshadows, and transparency, that&#8217;s how I roll) and set back to work.</p>
<p>Now the magic steps to make your mutliple display work:</p>
<p>1 Make sure you have the necessary modes available.<br />
2 Add the modelines that you require to the display that you want them added to.<br />
3 Set your resolution in the <span class="caps">ATI</span>/<span class="caps">AMD</span> Catalyst Control Panel</p>
<p>To see 1:</p>

<div class="highlight"><pre><code class="console"><span class="go">xrandr</span>
</code></pre>
</div>


<p>Will display all the modes available for you devices.</p>
<p>I am going to cheat and give you the &#8220;magic&#8221; modelines needed by the Matrox DualHead2Go, TripleHead2Go:</p>

<div class="highlight"><pre><code class="console"><span class="go">DualHead:</span>
<span class="go">2x 1680x1050:  ModeLine &quot;3360x1050&quot; 238.00 3360 3424 3488 3680 1050 1053 1061 1080 +HSync +VSync</span>
<span class="go">2x 1600x1200:  ModeLine &quot;3200x1200&quot; 281.40 3200 3264 3456 3752 1200 1201 1206 1250 +HSync +VSync</span>
<span class="go">2x 1920x1080:  ModeLine &quot;3840x1080&quot; 277.00 3840 3904 3968 4160 1080 1083 1092 1111 +HSync +VSync</span>
<span class="go">2x 1920x1200:  ModeLine &quot;3840x1200&quot; 308.00 3840 3904 3968 4160 1200 1203 1213 1235 +HSync +VSync</span>

<span class="go">TripleHead:</span>
<span class="go">3x 1280x1024:  ModeLine &quot;3840x1024&quot; 254.31 3840 3856 3872 3976 1024 1025 1032 1066 +HSync +VSync</span>
<span class="go">3x 1360x768:   ModeLine &quot;4080x768&quot;  200.38 4080 4104 4136 4200  768  771  779  795 +HSync +VSync</span>
<span class="go">3x 1440x900:   ModeLine &quot;4320x900&quot;  320.10 4320 4400 4688 5712  900  903  915  934 +HSync +VSync</span>
<span class="go">3x 1680x1050:  ModeLine &quot;5040x1050&quot; 326.66 5040 5104 5168 5376 1050 1053 1057 1066 +HSync +VSync</span>
</code></pre>
</div>


<p>To add one of these to your display:</p>

<div class="highlight"><pre><code class="console"><span class="go">xrandr --newmode &lt;Mode``Line&gt;</span>
<span class="go">xrandr --addmode DEVICE &quot;AAAAxBBBB&quot; </span>
</code></pre>
</div>


<p>Where <span class="caps">DEVICE</span> is the device name for your display, probably CRT1, DFP1, <span class="caps">LVDS</span>, etc. and the &#8220;AAAAxBBBB&#8221; is the name of the modeline that you copied from above.  So in my case:</p>

<div class="highlight"><pre><code class="console"><span class="go">xrandr --newmode &quot;3360x1050&quot; 238.00 3360 3424 3488 3680 1050 1053 1061 1080 +HSync +VSync</span>
<span class="go">xrandr --addmode CRT1 &quot;3360x1050&quot;</span>
</code></pre>
</div>


<p>Then I popped open the <span class="caps">AMD</span>/<span class="caps">ATI</span> Catalyst Control Panel &#8211; Voila! that resolution showed up.  I set all my monitors to their desired resolution and it worked.</p>
<p>To make you changes permanent add the xrandr commands to you .xprofile.  I move around between monitors at home and at work, so I don&#8217;t make this too automatic.  If you made it this far, you can probably google your way into a more automated setup.  Will upload a pic tomorrow of the working setup.</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>I recently purchased a <a href="http://www.matrox.com/graphics/en/products/gxm/dh2go/">matrox dualhead2go digital edition</a> off of ebay on a whim.  I did this because I wanted to make use of some extra monitors sitting around the office. I have also come to the realization that I have grown up as a developer and I have enough confidence to look anyone straight in the eye and say &#8211; &#8220;Yes, I need 3 monitors&#8221;.</p>
<p>My current setup is a Dell <span class="caps">XPS</span> 1640 running Ubuntu 10.04, with a Radeon 3670 graphics card. Yeah, enter the wonderful world of linux graphics drivers.</p>
<p>My first attempt was to simply, plug it in and see what would happen, resulted in a mild success.  I was able to have my laptop lcd set at a resolution of 1920&#215;1080 and the two 1680&#215;1050 monitors would only go up to 2560&#215;1024.  It looked warped, but it gave me a taste of what was possible.</p>
<p>After much configuring with <a href="https://wiki.ubuntu.com/X/Config/Resolution">xrandr &#8212;addmode, et. al ad nauseum</a>, I came to the conclusion that the matrox just wouldn&#8217;t support a higher resolution than 2560&#215;1024, even though the site claims that it will.  Some searching prompted me to discover that you need to configure the device to support your desired resolutions using the matrox powerdesk tool.  Windows and Mac users can rejoice, this exists for you both.  Linux users, go get on that old Windows test box that you use for IE testing and configure this mutha.</p>
<p>Armed with the following resolutions 3360&#215;1050, 3840&#215;1080, I set to work on my dream display.</p>
<p>I hit another snag. I could crank the resolution on my laptop, or the two 22&quot; monitors, but setting both to 11 caused really odd horizontal sync issues on my laptop.  The text would be fuzzy and move from side to side.  Clearly this wasn&#8217;t going to work using just Xrandr, and the Gnome Display tool.</p>
<p>This brings up another one of my errors.  DO <span class="caps">NOT</span> <span class="caps">USE</span> <span class="caps">THE</span> <span class="caps">GNOME</span> <span class="caps">DISPLAY</span> <span class="caps">TOOL</span> after using the <span class="caps">AMD</span>/<span class="caps">ATI</span> Catalyst Control panel.  The Gnome tool will nuke your xorg.conf file, and leave you scratching your head.  Once you go <span class="caps">FGLRX</span>, forget that the Gnome display tool even exists, and trust yourself to learn the <span class="caps">AMD</span>/<span class="caps">ATI</span> Catalyst Control Panel as well as the aticonfig command line tool.  If you are a complete badass and can handcraft your own xorg.conf file and modelines (why are you reading this?) skip ahead to the modeline cheats below.</p>
<p>I had clearly stepped into a limitation of the linux fglrx display driver, or so I thought.  At one point, I had inadvertently nuked my xorg.conf file, so fglrx was no longer being loaded. (See cautionary statement above) I went through the relatively simple process of <a href="https://wiki.ubuntu.com/X/Troubleshooting/FglrxInteferesWithRadeonDriver">removing all traces of fglrx from my system</a>. I reinstalled the proprietary drivers (because I also require dropshadows, and transparency, that&#8217;s how I roll) and set back to work.</p>
<p>Now the magic steps to make your mutliple display work:</p>
<p>1 Make sure you have the necessary modes available.<br />
2 Add the modelines that you require to the display that you want them added to.<br />
3 Set your resolution in the <span class="caps">ATI</span>/<span class="caps">AMD</span> Catalyst Control Panel</p>
<p>To see 1:</p>

<div class="highlight"><pre><code class="console"><span class="go">xrandr</span>
</code></pre>
</div>


<p>Will display all the modes available for you devices.</p>
<p>I am going to cheat and give you the &#8220;magic&#8221; modelines needed by the Matrox DualHead2Go, TripleHead2Go:</p>

<div class="highlight"><pre><code class="console"><span class="go">DualHead:</span>
<span class="go">2x 1680x1050:  ModeLine &quot;3360x1050&quot; 238.00 3360 3424 3488 3680 1050 1053 1061 1080 +HSync +VSync</span>
<span class="go">2x 1600x1200:  ModeLine &quot;3200x1200&quot; 281.40 3200 3264 3456 3752 1200 1201 1206 1250 +HSync +VSync</span>
<span class="go">2x 1920x1080:  ModeLine &quot;3840x1080&quot; 277.00 3840 3904 3968 4160 1080 1083 1092 1111 +HSync +VSync</span>
<span class="go">2x 1920x1200:  ModeLine &quot;3840x1200&quot; 308.00 3840 3904 3968 4160 1200 1203 1213 1235 +HSync +VSync</span>

<span class="go">TripleHead:</span>
<span class="go">3x 1280x1024:  ModeLine &quot;3840x1024&quot; 254.31 3840 3856 3872 3976 1024 1025 1032 1066 +HSync +VSync</span>
<span class="go">3x 1360x768:   ModeLine &quot;4080x768&quot;  200.38 4080 4104 4136 4200  768  771  779  795 +HSync +VSync</span>
<span class="go">3x 1440x900:   ModeLine &quot;4320x900&quot;  320.10 4320 4400 4688 5712  900  903  915  934 +HSync +VSync</span>
<span class="go">3x 1680x1050:  ModeLine &quot;5040x1050&quot; 326.66 5040 5104 5168 5376 1050 1053 1057 1066 +HSync +VSync</span>
</code></pre>
</div>


<p>To add one of these to your display:</p>

<div class="highlight"><pre><code class="console"><span class="go">xrandr --newmode &lt;Mode``Line&gt;</span>
<span class="go">xrandr --addmode DEVICE &quot;AAAAxBBBB&quot; </span>
</code></pre>
</div>


<p>Where <span class="caps">DEVICE</span> is the device name for your display, probably CRT1, DFP1, <span class="caps">LVDS</span>, etc. and the &#8220;AAAAxBBBB&#8221; is the name of the modeline that you copied from above.  So in my case:</p>

<div class="highlight"><pre><code class="console"><span class="go">xrandr --newmode &quot;3360x1050&quot; 238.00 3360 3424 3488 3680 1050 1053 1061 1080 +HSync +VSync</span>
<span class="go">xrandr --addmode CRT1 &quot;3360x1050&quot;</span>
</code></pre>
</div>


<p>Then I popped open the <span class="caps">AMD</span>/<span class="caps">ATI</span> Catalyst Control Panel &#8211; Voila! that resolution showed up.  I set all my monitors to their desired resolution and it worked.</p>
<p>To make you changes permanent add the xrandr commands to you .xprofile.  I move around between monitors at home and at work, so I don&#8217;t make this too automatic.  If you made it this far, you can probably google your way into a more automated setup.  Will upload a pic tomorrow of the working setup.</p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>Painless Upgrade to Bundler and Bamboo Stack</title>
    <link rel='alternate' type='text/html' href='/heroku/rails/2010/11/06/painless-upgrade-to-bundler-and-bamboo-stack.html' />
    <id>tag:brandon-harris.com:/heroku/rails/2010/11/06/painless-upgrade-to-bundler-and-bamboo-stack</id>
    <updated>2010-11-06T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>I just upgraded this site to use bundler and the heroku Bamboo stack.</p>
<p>The steps were:</p>
<p>1. Remove the .gems file, and create a Gemfile.<br />
2. <a href="http://gembundler.com/rails23.html">Patch the Rails 2.3 installation for bundler</a><br />
3. Run heroku command:</p>

<div class="highlight"><pre><code class="console"><span class="go">heroku stack:migrate bamboo-ree-1.8.7</span>
</code></pre>
</div>


<p>4.Run command:</p>

<div class="highlight"><pre><code class="console"><span class="go">bundle install</span>
</code></pre>
</div>


<p>5. Commit all changes to git, and push to heroku.</p>
<p>I am really impressed with the ease at which this was done.  Heroku continues to impress, and Bundler is the best thing to happen to Ruby since Rails.</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>I just upgraded this site to use bundler and the heroku Bamboo stack.</p>
<p>The steps were:</p>
<p>1. Remove the .gems file, and create a Gemfile.<br />
2. <a href="http://gembundler.com/rails23.html">Patch the Rails 2.3 installation for bundler</a><br />
3. Run heroku command:</p>

<div class="highlight"><pre><code class="console"><span class="go">heroku stack:migrate bamboo-ree-1.8.7</span>
</code></pre>
</div>


<p>4.Run command:</p>

<div class="highlight"><pre><code class="console"><span class="go">bundle install</span>
</code></pre>
</div>


<p>5. Commit all changes to git, and push to heroku.</p>
<p>I am really impressed with the ease at which this was done.  Heroku continues to impress, and Bundler is the best thing to happen to Ruby since Rails.</p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>Heroku Gem Gone After Push</title>
    <link rel='alternate' type='text/html' href='/heroku/2010/09/27/heroku-gem-gone-after-push.html' />
    <id>tag:brandon-harris.com:/heroku/2010/09/27/heroku-gem-gone-after-push</id>
    <updated>2010-09-27T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>I recently deployed to heroku and was greeted with the dreaded &#8220;App Crashed&#8221; dialogue.  In this particular case it was for a higher traffic production site, so I was frantic to fix it.<br />
A quick</p>

<div class="highlight"><pre><code class="console"><span class="go">heroku logs</span>
</code></pre>
</div>


<p>showed that the memcache gem was missing.  I scratched my head a little bit and did a quick git log on the .gem file.  It hadn&#8217;t changed in months.  Time was ticking, so I looked up the current version that I needed for the environment and I added it in.  Another git push and I waited.<br />
All the gems were pulled in and the instance started successfully.  In my haste to move on to the next task, I didn&#8217;t follow up too much and just assumed that this was a fluke.</p>
<p>It happened again, this time to a much less important application.  Only it was a different gem.  I took the time a looked through the heroku gem command list look for something like heroku rake gems:refresh or similar.  Nothing!  This seems like a very logical task.  The only way I can think to force a gem refresh is to edit the .gems file and perform a push.</p>
<p>I this case, that is what I did again.  I am not currently running on the bamboo stack, and this looks like it is a new phenomenon.  Has anyone else experience this oddity?  If I find a fix, I will post back here.  Maybe I need to get moving on upgrading to the bamboo stack&#8230;</p>
<p>To be continued.</p>
<p><strong>Update 10/03/2010</strong></p>
<p>I spoke with a local heroku developer and the issue that I experienced along with several others was caused by an error in the slug compiler.  A fix has been released and this issue should be resolved.  If you do experience it, simply touching the .gems file and committing will result in a slug recompile.</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>I recently deployed to heroku and was greeted with the dreaded &#8220;App Crashed&#8221; dialogue.  In this particular case it was for a higher traffic production site, so I was frantic to fix it.<br />
A quick</p>

<div class="highlight"><pre><code class="console"><span class="go">heroku logs</span>
</code></pre>
</div>


<p>showed that the memcache gem was missing.  I scratched my head a little bit and did a quick git log on the .gem file.  It hadn&#8217;t changed in months.  Time was ticking, so I looked up the current version that I needed for the environment and I added it in.  Another git push and I waited.<br />
All the gems were pulled in and the instance started successfully.  In my haste to move on to the next task, I didn&#8217;t follow up too much and just assumed that this was a fluke.</p>
<p>It happened again, this time to a much less important application.  Only it was a different gem.  I took the time a looked through the heroku gem command list look for something like heroku rake gems:refresh or similar.  Nothing!  This seems like a very logical task.  The only way I can think to force a gem refresh is to edit the .gems file and perform a push.</p>
<p>I this case, that is what I did again.  I am not currently running on the bamboo stack, and this looks like it is a new phenomenon.  Has anyone else experience this oddity?  If I find a fix, I will post back here.  Maybe I need to get moving on upgrading to the bamboo stack&#8230;</p>
<p>To be continued.</p>
<p><strong>Update 10/03/2010</strong></p>
<p>I spoke with a local heroku developer and the issue that I experienced along with several others was caused by an error in the slug compiler.  A fix has been released and this issue should be resolved.  If you do experience it, simply touching the .gems file and committing will result in a slug recompile.</p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>Oracle, Rails and Ubuntu 10.04</title>
    <link rel='alternate' type='text/html' href='/rails/oracle/ubuntu/2010/06/14/oracle-rails-and-ubuntu-10-04.html' />
    <id>tag:brandon-harris.com:/rails/oracle/ubuntu/2010/06/14/oracle-rails-and-ubuntu-10-04</id>
    <updated>2010-06-14T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>I recently setup an Ubuntu based server that needed ruby to talk to oracle and mysql.  If you are a rails developer, you should be familiar with mysql, but what about Oracle? It isn&#8217;t quite as straightforward as you might assume, but it is within the grasp of mere mortals. Please keep in mind that due to changing version numbers, all version numbers are replaced with *.  It is up to the reader to properly translate the following commands.  Don&#8217;t simply copy and paste.  I am making the assumption that you are installing on Ubuntu 10.04 (Lucid Lynx) and you are using the 64-bit version.</p>
<p>First Go to:<br />
<a href="http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/linuxx86_64.html">http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/linuxx86_64.html</a></p>
<p>Select the latest versions of:</p>

<div class="highlight"><pre><code class="console"><span class="go">oracle-instantclient*-basiclite-*.rpm</span>
<span class="go">oracle-instantclient*-sqlplus-*.rpm</span>
<span class="go">instantclient-sdk-*.zip</span>
</code></pre>
</div>


<p>Replace the * above with the appropriate latest version number.</p>
<p>Now you will need to install the alien package management tool.  It converts .rpm to .deb and works amazingly well most of the time.</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo apt0get install alien</span>
</code></pre>
</div>


<p>Now run the alien command on the rpms you downloaded from oracle:</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo alien oracle-instantclient*-basiclite-*.rpm</span>
<span class="go">sudo alien oracle-instantclient*-sqlplus-*.rpm</span>
</code></pre>
</div>


<p>This will produce .deb files in your current directory. To install the freshly minted pacakges run:</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo dpkg -i oracle-instantclient-*.deb</span>
</code></pre>
</div>


<p>Now unzip the sdk contents, you need to extract the header files for everything to work later.</p>

<div class="highlight"><pre><code class="console"><span class="go">unzip instantclient-sdk-*</span>
<span class="go">cd instantclient-sdk-*/include/</span>
<span class="go">cp *.h /usr/include/oracle/&lt;version&gt;/client64/lib</span>
</code></pre>
</div>


<p>If you are going to be using the tnsnames.ora file to specify your connections, you will need to set the TNS_ADMIN environment variable.  In Debian based distros, you will want to edit /etc/environment.  Editing this file ensures that environment variables are set for all users.</p>
<p>Add the following environment variables to your /etc/environment file.</p>

<div class="highlight"><pre><code class="console"><span class="go">LD_LIBRARY_PATH=/usr/lib/oracle/&lt;version&gt;/client64/lib</span>
<span class="go">TNS_ADMIN=&quot;your path to your tnsnames.ora file&quot;</span>
</code></pre>
</div>


<p>You are all set for interacting with oracle from your Ubuntu server. To test just run:</p>

<div class="highlight"><pre><code class="console"><span class="go">sqlplus64</span>
</code></pre>
</div>


<p>If you would like to enable your rails app to use oracle as well you have a few more steps.</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo gem install ruby-oci8</span>
</code></pre>
</div>


<p>If that fails, you may need to specify to LD_LIBRARY_PATH:</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo gem install LD_LIBRARY_PATH=$LD_LIBRARY_PATH ruby-oci8</span>
</code></pre>
</div>


<p>Pay close attention to errors if you receive them, they are actually very clear and coherent. Pay close attention to your environment variables and the inclusion of the header files.</p>
<p>If you have reached this point you can test your oci8 connection:</p>

<div class="highlight"><pre><code class="irb"><span class="lineno">1</span> <span class="go">irb</span>
<span class="lineno">2</span> <span class="go">irb(main):001:0&gt;require &#39;rubygems&#39;</span>
<span class="lineno">3</span> <span class="go">=&gt; true</span>
<span class="lineno">4</span> <span class="go">irb(main):002:0&gt;require &#39;oci8&#39;</span>
<span class="lineno">5</span> <span class="go">=&gt; true</span>
<span class="lineno">6</span> <span class="go">irb(main):003:0&gt;oracle_connection = OCI8.new(user,password,schema)</span>
<span class="lineno">7</span> <span class="go">=&gt; #&lt;OCI8:RTD_ODBC&gt;</span>
<span class="lineno">8</span> <span class="gp">irb(main):004:0&gt; </span><span class="n">oracle</span><span class="o">.</span><span class="n">exec</span><span class="p">(</span><span class="s2">&quot;select 1 from dual&quot;</span><span class="p">)</span>
<span class="lineno">9</span> <span class="go">=&gt; #&lt;OCI8::Cursor:0x7f9ea9a72430&gt;</span>
</code></pre>
</div>


<p>Now if you are planning on using Ruby on Rails with Oracle, you will need to install the activerecord adapter.  I used the <a href="http://github.com/rsim/oracle-enhanced">enhanced adapter</a>, but the choice is yours.</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo gem install activerecord-oracle_enhanced-adapter</span>
</code></pre>
</div>


<p>Now the final part, your database.yml file should look like the following:</p>

<div class="highlight"><pre><code class="yaml"><span class="lineno">1</span> <span class="l-Scalar-Plain">production</span><span class="p-Indicator">:</span> 
<span class="lineno">2</span>   <span class="l-Scalar-Plain">adapter</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">oracle_enhanced</span> 
<span class="lineno">3</span>   <span class="l-Scalar-Plain">database</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">&lt;oracle database&gt;</span>
<span class="lineno">4</span>   <span class="l-Scalar-Plain">username</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">&lt;oracle username&gt;</span>
<span class="lineno">5</span>   <span class="l-Scalar-Plain">password</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">&lt;oracle password&gt;</span>
</code></pre>
</div>


<p>The oracle enhanced adapter has some more config options for your database.yml file, please refer to:<br />
<a href="http://wiki.github.com/rsim/oracle-enhanced/">http://wiki.github.com/rsim/oracle-enhanced/</a></p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>I recently setup an Ubuntu based server that needed ruby to talk to oracle and mysql.  If you are a rails developer, you should be familiar with mysql, but what about Oracle? It isn&#8217;t quite as straightforward as you might assume, but it is within the grasp of mere mortals. Please keep in mind that due to changing version numbers, all version numbers are replaced with *.  It is up to the reader to properly translate the following commands.  Don&#8217;t simply copy and paste.  I am making the assumption that you are installing on Ubuntu 10.04 (Lucid Lynx) and you are using the 64-bit version.</p>
<p>First Go to:<br />
<a href="http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/linuxx86_64.html">http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/linuxx86_64.html</a></p>
<p>Select the latest versions of:</p>

<div class="highlight"><pre><code class="console"><span class="go">oracle-instantclient*-basiclite-*.rpm</span>
<span class="go">oracle-instantclient*-sqlplus-*.rpm</span>
<span class="go">instantclient-sdk-*.zip</span>
</code></pre>
</div>


<p>Replace the * above with the appropriate latest version number.</p>
<p>Now you will need to install the alien package management tool.  It converts .rpm to .deb and works amazingly well most of the time.</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo apt0get install alien</span>
</code></pre>
</div>


<p>Now run the alien command on the rpms you downloaded from oracle:</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo alien oracle-instantclient*-basiclite-*.rpm</span>
<span class="go">sudo alien oracle-instantclient*-sqlplus-*.rpm</span>
</code></pre>
</div>


<p>This will produce .deb files in your current directory. To install the freshly minted pacakges run:</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo dpkg -i oracle-instantclient-*.deb</span>
</code></pre>
</div>


<p>Now unzip the sdk contents, you need to extract the header files for everything to work later.</p>

<div class="highlight"><pre><code class="console"><span class="go">unzip instantclient-sdk-*</span>
<span class="go">cd instantclient-sdk-*/include/</span>
<span class="go">cp *.h /usr/include/oracle/&lt;version&gt;/client64/lib</span>
</code></pre>
</div>


<p>If you are going to be using the tnsnames.ora file to specify your connections, you will need to set the TNS_ADMIN environment variable.  In Debian based distros, you will want to edit /etc/environment.  Editing this file ensures that environment variables are set for all users.</p>
<p>Add the following environment variables to your /etc/environment file.</p>

<div class="highlight"><pre><code class="console"><span class="go">LD_LIBRARY_PATH=/usr/lib/oracle/&lt;version&gt;/client64/lib</span>
<span class="go">TNS_ADMIN=&quot;your path to your tnsnames.ora file&quot;</span>
</code></pre>
</div>


<p>You are all set for interacting with oracle from your Ubuntu server. To test just run:</p>

<div class="highlight"><pre><code class="console"><span class="go">sqlplus64</span>
</code></pre>
</div>


<p>If you would like to enable your rails app to use oracle as well you have a few more steps.</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo gem install ruby-oci8</span>
</code></pre>
</div>


<p>If that fails, you may need to specify to LD_LIBRARY_PATH:</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo gem install LD_LIBRARY_PATH=$LD_LIBRARY_PATH ruby-oci8</span>
</code></pre>
</div>


<p>Pay close attention to errors if you receive them, they are actually very clear and coherent. Pay close attention to your environment variables and the inclusion of the header files.</p>
<p>If you have reached this point you can test your oci8 connection:</p>

<div class="highlight"><pre><code class="irb"><span class="lineno">1</span> <span class="go">irb</span>
<span class="lineno">2</span> <span class="go">irb(main):001:0&gt;require &#39;rubygems&#39;</span>
<span class="lineno">3</span> <span class="go">=&gt; true</span>
<span class="lineno">4</span> <span class="go">irb(main):002:0&gt;require &#39;oci8&#39;</span>
<span class="lineno">5</span> <span class="go">=&gt; true</span>
<span class="lineno">6</span> <span class="go">irb(main):003:0&gt;oracle_connection = OCI8.new(user,password,schema)</span>
<span class="lineno">7</span> <span class="go">=&gt; #&lt;OCI8:RTD_ODBC&gt;</span>
<span class="lineno">8</span> <span class="gp">irb(main):004:0&gt; </span><span class="n">oracle</span><span class="o">.</span><span class="n">exec</span><span class="p">(</span><span class="s2">&quot;select 1 from dual&quot;</span><span class="p">)</span>
<span class="lineno">9</span> <span class="go">=&gt; #&lt;OCI8::Cursor:0x7f9ea9a72430&gt;</span>
</code></pre>
</div>


<p>Now if you are planning on using Ruby on Rails with Oracle, you will need to install the activerecord adapter.  I used the <a href="http://github.com/rsim/oracle-enhanced">enhanced adapter</a>, but the choice is yours.</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo gem install activerecord-oracle_enhanced-adapter</span>
</code></pre>
</div>


<p>Now the final part, your database.yml file should look like the following:</p>

<div class="highlight"><pre><code class="yaml"><span class="lineno">1</span> <span class="l-Scalar-Plain">production</span><span class="p-Indicator">:</span> 
<span class="lineno">2</span>   <span class="l-Scalar-Plain">adapter</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">oracle_enhanced</span> 
<span class="lineno">3</span>   <span class="l-Scalar-Plain">database</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">&lt;oracle database&gt;</span>
<span class="lineno">4</span>   <span class="l-Scalar-Plain">username</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">&lt;oracle username&gt;</span>
<span class="lineno">5</span>   <span class="l-Scalar-Plain">password</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">&lt;oracle password&gt;</span>
</code></pre>
</div>


<p>The oracle enhanced adapter has some more config options for your database.yml file, please refer to:<br />
<a href="http://wiki.github.com/rsim/oracle-enhanced/">http://wiki.github.com/rsim/oracle-enhanced/</a></p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>Simple Sinatra ActiveRecord App with Migrations</title>
    <link rel='alternate' type='text/html' href='/sinatra/2010/03/28/simple-sinatra-activerecord-app-with-migrations.html' />
    <id>tag:brandon-harris.com:/sinatra/2010/03/28/simple-sinatra-activerecord-app-with-migrations</id>
    <updated>2010-03-28T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>I make a lot of stuff using Ruby on Rails, so why bother with Sinatra?  Well, its fast, has a very small footprint, and it&#8217;s fun.</p>
<p>I decided to build a simple posting app as a test for Sinatra. My example doesn&#8217;t do much, but it was fun to learn about all the little parts of Rails that I take for granted everyday. <br />
The first thing I did was start with the hello world example.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="nb">require</span> <span class="s1">&#39;rubygems&#39;</span>
<span class="lineno">2</span> <span class="nb">require</span> <span class="s1">&#39;sinatra&#39;</span>
<span class="lineno">3</span> <span class="n">get</span> <span class="s1">&#39;/&#39;</span> <span class="k">do</span>
<span class="lineno">4</span> <span class="s2">&quot;This is my first Sinatra test.&quot;</span>
<span class="lineno">5</span> <span class="k">end</span>
</code></pre>
</div>


<p>I fired up the server</p>

<div class="highlight"><pre><code class="console"><span class="go">ruby test.rb</span>
</code></pre>
</div>


<p>Cool.</p>
<p>I really like Haml, so I created a file test/views/index.haml</p>

<div class="highlight"><pre><code class="haml"><span class="nt">%h1</span> This is my first Sinatra test.
</code></pre>
</div>


<p>and edited my hello world code:</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="nb">require</span> <span class="s1">&#39;rubygems&#39;</span>
<span class="lineno">2</span> <span class="nb">require</span> <span class="s1">&#39;sinatra&#39;</span>
<span class="lineno">3</span> <span class="nb">require</span> <span class="s1">&#39;haml&#39;</span>
<span class="lineno">4</span> <span class="n">get</span> <span class="s1">&#39;/&#39;</span> <span class="k">do</span>
<span class="lineno">5</span>   <span class="n">haml</span> <span class="ss">:index</span>
<span class="lineno">6</span> <span class="k">end</span>
</code></pre>
</div>


<p>Fired up the server and once again was justified in my simple attempts. Cool, what about databases?  We all know and love ActiveRecord, so lets start there.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno"> 1</span> <span class="nb">require</span> <span class="s1">&#39;rubygems&#39;</span>
<span class="lineno"> 2</span> <span class="nb">require</span> <span class="s1">&#39;sinatra&#39;</span>
<span class="lineno"> 3</span> <span class="nb">require</span> <span class="s1">&#39;haml&#39;</span>
<span class="lineno"> 4</span> <span class="nb">require</span> <span class="s1">&#39;active_record&#39;</span>
<span class="lineno"> 5</span> 
<span class="lineno"> 6</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">establish_connection</span><span class="p">(</span>
<span class="lineno"> 7</span>   <span class="ss">:adapter</span> <span class="o">=&gt;</span> <span class="s1">&#39;sqlite3&#39;</span><span class="p">,</span>
<span class="lineno"> 8</span>   <span class="ss">:dbfile</span> <span class="o">=&gt;</span>  <span class="s1">&#39;db/test.sqlite3.db&#39;</span>
<span class="lineno"> 9</span> <span class="p">)</span>
<span class="lineno">10</span> 
<span class="lineno">11</span> <span class="c1">#Models</span>
<span class="lineno">12</span> <span class="k">class</span> <span class="nc">Post</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
<span class="lineno">13</span> <span class="k">end</span>
<span class="lineno">14</span> 
<span class="lineno">15</span> <span class="n">get</span> <span class="s1">&#39;/&#39;</span> <span class="k">do</span>
<span class="lineno">16</span>  <span class="vi">@posts</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">all</span>
<span class="lineno">17</span>  <span class="n">haml</span> <span class="ss">:index</span>
<span class="lineno">18</span> <span class="k">end</span>
<span class="lineno">19</span> 
<span class="lineno">20</span> <span class="c1">#Posts</span>
<span class="lineno">21</span> <span class="n">get</span> <span class="s1">&#39;/posts&#39;</span> <span class="k">do</span>
<span class="lineno">22</span>   <span class="vi">@posts</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">all</span>
<span class="lineno">23</span>   <span class="n">haml</span> <span class="ss">:&#39;posts/index&#39;</span>
<span class="lineno">24</span> <span class="k">end</span>
<span class="lineno">25</span> 
<span class="lineno">26</span> <span class="n">get</span> <span class="s1">&#39;/posts/new&#39;</span> <span class="k">do</span>
<span class="lineno">27</span>   <span class="vi">@post</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">new</span>
<span class="lineno">28</span>   <span class="n">haml</span> <span class="ss">:&#39;posts/new&#39;</span>
<span class="lineno">29</span> <span class="k">end</span>
<span class="lineno">30</span> 
<span class="lineno">31</span> <span class="n">post</span> <span class="s1">&#39;/posts&#39;</span> <span class="k">do</span>
<span class="lineno">32</span>   <span class="vi">@post</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">params</span><span class="o">[</span><span class="ss">:post</span><span class="o">]</span><span class="p">)</span>
<span class="lineno">33</span>   <span class="k">if</span> <span class="vi">@post</span><span class="o">.</span><span class="n">save</span>
<span class="lineno">34</span>     <span class="n">redirect</span> <span class="s2">&quot;/posts/</span><span class="si">#{</span><span class="vi">@post</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="lineno">35</span>   <span class="k">else</span>
<span class="lineno">36</span>     <span class="s2">&quot;There was a problem saving that...&quot;</span>
<span class="lineno">37</span>   <span class="k">end</span>
<span class="lineno">38</span> <span class="k">end</span>
<span class="lineno">39</span> 
<span class="lineno">40</span> <span class="n">get</span> <span class="s1">&#39;/posts/:id&#39;</span> <span class="k">do</span>
<span class="lineno">41</span>   <span class="vi">@post</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">params</span><span class="o">[</span><span class="ss">:id</span><span class="o">]</span><span class="p">)</span>
<span class="lineno">42</span>   <span class="n">haml</span> <span class="ss">:&#39;posts/show&#39;</span>
<span class="lineno">43</span> <span class="k">end</span>
</code></pre>
</div>


<p>This will work, if you manually create your own database in sqlite. But I really like migrations. So I created a Rakefile.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno"> 1</span> <span class="n">namespace</span> <span class="ss">:db</span> <span class="k">do</span>
<span class="lineno"> 2</span>   <span class="n">task</span> <span class="ss">:environment</span> <span class="k">do</span>
<span class="lineno"> 3</span>     <span class="nb">require</span> <span class="s1">&#39;active_record&#39;</span>
<span class="lineno"> 4</span>     <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">establish_connection</span> <span class="ss">:adapter</span> <span class="o">=&gt;</span> <span class="s1">&#39;sqlite3&#39;</span><span class="p">,</span> <span class="ss">:dbfile</span> <span class="o">=&gt;</span>  <span class="s1">&#39;db/test.sqlite3.db&#39;</span>
<span class="lineno"> 5</span>   <span class="k">end</span>
<span class="lineno"> 6</span> 
<span class="lineno"> 7</span>   <span class="n">desc</span> <span class="s2">&quot;Migrate the database&quot;</span>
<span class="lineno"> 8</span>   <span class="n">task</span><span class="p">(</span><span class="ss">:migrate</span> <span class="o">=&gt;</span> <span class="ss">:environment</span><span class="p">)</span> <span class="k">do</span>
<span class="lineno"> 9</span>     <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="no">Logger</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="no">STDOUT</span><span class="p">)</span>
<span class="lineno">10</span>     <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Migration</span><span class="o">.</span><span class="n">verbose</span> <span class="o">=</span> <span class="kp">true</span>
<span class="lineno">11</span>     <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Migrator</span><span class="o">.</span><span class="n">migrate</span><span class="p">(</span><span class="s2">&quot;db/migrate&quot;</span><span class="p">)</span>
<span class="lineno">12</span>   <span class="k">end</span>
<span class="lineno">13</span> <span class="k">end</span>
</code></pre>
</div>


<p>You have to manually create your migration file in db/migrations, and when you run rake db:migrate this rakefile will work for you.  Of course, you will have to edit this particular one to use a different database other than sqlite.  Perhaps you could create a configuration file using <span class="caps">YAML</span>?</p>
<p>You can see where this is going.  Sinatra is very lightweight, yet it gives you the elements that you are used to in Rails. If you wanted to use something other than ActiveRecord, you can go ahead and do that easily.  Don&#8217;t like Migrations? Don&#8217;t use them.</p>
<p>I&#8217;ll be using it, and keeping it in my toolbelt.  Try it out, it&#8217;s refreshingly simple if you spend your days toiling around in Rails.</p>
<p>I did some minor cleanup on the above code and threw it on my <a href="http://github.com/bbwharris/examples/tree/master/sinatra/test/">github which you can get here</a>.</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>I make a lot of stuff using Ruby on Rails, so why bother with Sinatra?  Well, its fast, has a very small footprint, and it&#8217;s fun.</p>
<p>I decided to build a simple posting app as a test for Sinatra. My example doesn&#8217;t do much, but it was fun to learn about all the little parts of Rails that I take for granted everyday. <br />
The first thing I did was start with the hello world example.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="nb">require</span> <span class="s1">&#39;rubygems&#39;</span>
<span class="lineno">2</span> <span class="nb">require</span> <span class="s1">&#39;sinatra&#39;</span>
<span class="lineno">3</span> <span class="n">get</span> <span class="s1">&#39;/&#39;</span> <span class="k">do</span>
<span class="lineno">4</span> <span class="s2">&quot;This is my first Sinatra test.&quot;</span>
<span class="lineno">5</span> <span class="k">end</span>
</code></pre>
</div>


<p>I fired up the server</p>

<div class="highlight"><pre><code class="console"><span class="go">ruby test.rb</span>
</code></pre>
</div>


<p>Cool.</p>
<p>I really like Haml, so I created a file test/views/index.haml</p>

<div class="highlight"><pre><code class="haml"><span class="nt">%h1</span> This is my first Sinatra test.
</code></pre>
</div>


<p>and edited my hello world code:</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="nb">require</span> <span class="s1">&#39;rubygems&#39;</span>
<span class="lineno">2</span> <span class="nb">require</span> <span class="s1">&#39;sinatra&#39;</span>
<span class="lineno">3</span> <span class="nb">require</span> <span class="s1">&#39;haml&#39;</span>
<span class="lineno">4</span> <span class="n">get</span> <span class="s1">&#39;/&#39;</span> <span class="k">do</span>
<span class="lineno">5</span>   <span class="n">haml</span> <span class="ss">:index</span>
<span class="lineno">6</span> <span class="k">end</span>
</code></pre>
</div>


<p>Fired up the server and once again was justified in my simple attempts. Cool, what about databases?  We all know and love ActiveRecord, so lets start there.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno"> 1</span> <span class="nb">require</span> <span class="s1">&#39;rubygems&#39;</span>
<span class="lineno"> 2</span> <span class="nb">require</span> <span class="s1">&#39;sinatra&#39;</span>
<span class="lineno"> 3</span> <span class="nb">require</span> <span class="s1">&#39;haml&#39;</span>
<span class="lineno"> 4</span> <span class="nb">require</span> <span class="s1">&#39;active_record&#39;</span>
<span class="lineno"> 5</span> 
<span class="lineno"> 6</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">establish_connection</span><span class="p">(</span>
<span class="lineno"> 7</span>   <span class="ss">:adapter</span> <span class="o">=&gt;</span> <span class="s1">&#39;sqlite3&#39;</span><span class="p">,</span>
<span class="lineno"> 8</span>   <span class="ss">:dbfile</span> <span class="o">=&gt;</span>  <span class="s1">&#39;db/test.sqlite3.db&#39;</span>
<span class="lineno"> 9</span> <span class="p">)</span>
<span class="lineno">10</span> 
<span class="lineno">11</span> <span class="c1">#Models</span>
<span class="lineno">12</span> <span class="k">class</span> <span class="nc">Post</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
<span class="lineno">13</span> <span class="k">end</span>
<span class="lineno">14</span> 
<span class="lineno">15</span> <span class="n">get</span> <span class="s1">&#39;/&#39;</span> <span class="k">do</span>
<span class="lineno">16</span>  <span class="vi">@posts</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">all</span>
<span class="lineno">17</span>  <span class="n">haml</span> <span class="ss">:index</span>
<span class="lineno">18</span> <span class="k">end</span>
<span class="lineno">19</span> 
<span class="lineno">20</span> <span class="c1">#Posts</span>
<span class="lineno">21</span> <span class="n">get</span> <span class="s1">&#39;/posts&#39;</span> <span class="k">do</span>
<span class="lineno">22</span>   <span class="vi">@posts</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">all</span>
<span class="lineno">23</span>   <span class="n">haml</span> <span class="ss">:&#39;posts/index&#39;</span>
<span class="lineno">24</span> <span class="k">end</span>
<span class="lineno">25</span> 
<span class="lineno">26</span> <span class="n">get</span> <span class="s1">&#39;/posts/new&#39;</span> <span class="k">do</span>
<span class="lineno">27</span>   <span class="vi">@post</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">new</span>
<span class="lineno">28</span>   <span class="n">haml</span> <span class="ss">:&#39;posts/new&#39;</span>
<span class="lineno">29</span> <span class="k">end</span>
<span class="lineno">30</span> 
<span class="lineno">31</span> <span class="n">post</span> <span class="s1">&#39;/posts&#39;</span> <span class="k">do</span>
<span class="lineno">32</span>   <span class="vi">@post</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">params</span><span class="o">[</span><span class="ss">:post</span><span class="o">]</span><span class="p">)</span>
<span class="lineno">33</span>   <span class="k">if</span> <span class="vi">@post</span><span class="o">.</span><span class="n">save</span>
<span class="lineno">34</span>     <span class="n">redirect</span> <span class="s2">&quot;/posts/</span><span class="si">#{</span><span class="vi">@post</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="lineno">35</span>   <span class="k">else</span>
<span class="lineno">36</span>     <span class="s2">&quot;There was a problem saving that...&quot;</span>
<span class="lineno">37</span>   <span class="k">end</span>
<span class="lineno">38</span> <span class="k">end</span>
<span class="lineno">39</span> 
<span class="lineno">40</span> <span class="n">get</span> <span class="s1">&#39;/posts/:id&#39;</span> <span class="k">do</span>
<span class="lineno">41</span>   <span class="vi">@post</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">params</span><span class="o">[</span><span class="ss">:id</span><span class="o">]</span><span class="p">)</span>
<span class="lineno">42</span>   <span class="n">haml</span> <span class="ss">:&#39;posts/show&#39;</span>
<span class="lineno">43</span> <span class="k">end</span>
</code></pre>
</div>


<p>This will work, if you manually create your own database in sqlite. But I really like migrations. So I created a Rakefile.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno"> 1</span> <span class="n">namespace</span> <span class="ss">:db</span> <span class="k">do</span>
<span class="lineno"> 2</span>   <span class="n">task</span> <span class="ss">:environment</span> <span class="k">do</span>
<span class="lineno"> 3</span>     <span class="nb">require</span> <span class="s1">&#39;active_record&#39;</span>
<span class="lineno"> 4</span>     <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">establish_connection</span> <span class="ss">:adapter</span> <span class="o">=&gt;</span> <span class="s1">&#39;sqlite3&#39;</span><span class="p">,</span> <span class="ss">:dbfile</span> <span class="o">=&gt;</span>  <span class="s1">&#39;db/test.sqlite3.db&#39;</span>
<span class="lineno"> 5</span>   <span class="k">end</span>
<span class="lineno"> 6</span> 
<span class="lineno"> 7</span>   <span class="n">desc</span> <span class="s2">&quot;Migrate the database&quot;</span>
<span class="lineno"> 8</span>   <span class="n">task</span><span class="p">(</span><span class="ss">:migrate</span> <span class="o">=&gt;</span> <span class="ss">:environment</span><span class="p">)</span> <span class="k">do</span>
<span class="lineno"> 9</span>     <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="no">Logger</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="no">STDOUT</span><span class="p">)</span>
<span class="lineno">10</span>     <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Migration</span><span class="o">.</span><span class="n">verbose</span> <span class="o">=</span> <span class="kp">true</span>
<span class="lineno">11</span>     <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Migrator</span><span class="o">.</span><span class="n">migrate</span><span class="p">(</span><span class="s2">&quot;db/migrate&quot;</span><span class="p">)</span>
<span class="lineno">12</span>   <span class="k">end</span>
<span class="lineno">13</span> <span class="k">end</span>
</code></pre>
</div>


<p>You have to manually create your migration file in db/migrations, and when you run rake db:migrate this rakefile will work for you.  Of course, you will have to edit this particular one to use a different database other than sqlite.  Perhaps you could create a configuration file using <span class="caps">YAML</span>?</p>
<p>You can see where this is going.  Sinatra is very lightweight, yet it gives you the elements that you are used to in Rails. If you wanted to use something other than ActiveRecord, you can go ahead and do that easily.  Don&#8217;t like Migrations? Don&#8217;t use them.</p>
<p>I&#8217;ll be using it, and keeping it in my toolbelt.  Try it out, it&#8217;s refreshingly simple if you spend your days toiling around in Rails.</p>
<p>I did some minor cleanup on the above code and threw it on my <a href="http://github.com/bbwharris/examples/tree/master/sinatra/test/">github which you can get here</a>.</p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>Portfolio</title>
    <link rel='alternate' type='text/html' href='/2010/02/16/portfolio.html' />
    <id>tag:brandon-harris.com:/2010/02/16/portfolio</id>
    <updated>2010-02-16T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>I have been dabbling in the freelance world, and have created a simple portfolio listing on this site.  <a href="/portfolios">Take a look</a> if you are interested to see some of the work that I have been doing in my &#8220;free time&#8221;.</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>I have been dabbling in the freelance world, and have created a simple portfolio listing on this site.  <a href="/portfolios">Take a look</a> if you are interested to see some of the work that I have been doing in my &#8220;free time&#8221;.</p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>Active Scaffold with Paperclip</title>
    <link rel='alternate' type='text/html' href='/rails/active scaffold/2009/12/28/active-scaffold-with-paperclip.html' />
    <id>tag:brandon-harris.com:/rails/active scaffold/2009/12/28/active-scaffold-with-paperclip</id>
    <updated>2009-12-28T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>I always recommend <a href="http://activescaffold.com/">Active Scaffold</a> to fellow Rails developers.  There is a learning curve, but it can cut a lot of development time out of your clients custom <span class="caps">CMS</span>.</p>
<p><a href="http://github.com/thoughtbot/paperclip">Paperclip</a> has pretty much dominated the Rails attachment market for the past year.  My company has migrated to it, and there are countless tutorials and testimonials regarding it&#8217;s ease of use.</p>
<p>I am assuming that you are using the latest version of Rails (2.3.5 as of this writing), Active Scaffold, and Paperclip.  First we will install all the necessary components, then we will configure the rails app.</p>
<p>Install Active Scaffold:</p>

<div class="highlight"><pre><code class="console"><span class="go">script/plugin install git://github.com/activescaffold/active_scaffold.git</span>
</code></pre>
</div>


<p>Active Scaffold is big so this takes a while.</p>
<p>Install Paperclip:</p>

<div class="highlight"><pre><code class="console"><span class="go">script/plugin install git://github.com/thoughtbot/paperclip.git</span>
</code></pre>
</div>


<p><em>As of 6/14/2010 this is no longer needed, the bridge has been moved to the core</em><br />
<del>Install the Active Scaffold Paperclip Bridge:</del></p>
<p>Lets create a basic person model:</p>

<div class="highlight"><pre><code class="console"><span class="go">script/generate model Person</span>
</code></pre>
</div>


<p>To create controllers in the admin namespace, I don&#8217;t use the rails controller generator. I don&#8217;t like cluttering up my projects with files I will never use, since I employ Active Scaffold for 99% of my admin interfaces.  This is my personal preference, you may do this anyway that you wish.</p>

<div class="highlight"><pre><code class="console"><span class="go">mkdir app/controllers/admin &amp;&amp; touch app/controllers/admin/people_controller.rb</span>
</code></pre>
</div>


<p>Lets configure the &#8220;Person&#8221; migration for paperclip.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno"> 1</span> <span class="k">class</span> <span class="nc">CreatePeople</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Migration</span>
<span class="lineno"> 2</span>   <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">up</span>
<span class="lineno"> 3</span>     <span class="n">create_table</span> <span class="ss">:people</span> <span class="k">do</span> <span class="o">|</span><span class="n">t</span><span class="o">|</span>
<span class="lineno"> 4</span>       <span class="n">t</span><span class="o">.</span><span class="n">string</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">:avatar_file_name</span><span class="p">,</span> <span class="ss">:avatar_content_type</span>
<span class="lineno"> 5</span>       <span class="n">t</span><span class="o">.</span><span class="n">integer</span> <span class="ss">:avatar_file_size</span>
<span class="lineno"> 6</span>       <span class="n">t</span><span class="o">.</span><span class="n">datetime</span> <span class="ss">:avatar_updated_at</span>
<span class="lineno"> 7</span>       <span class="n">t</span><span class="o">.</span><span class="n">timestamps</span>
<span class="lineno"> 8</span>     <span class="k">end</span>
<span class="lineno"> 9</span>   <span class="k">end</span>
<span class="lineno">10</span> 
<span class="lineno">11</span>   <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">down</span>
<span class="lineno">12</span>     <span class="n">drop_table</span> <span class="ss">:people</span>
<span class="lineno">13</span>   <span class="k">end</span>
<span class="lineno">14</span> <span class="k">end</span>
</code></pre>
</div>


<p>Configure the Person model to accept the paperclip attachment.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="k">class</span> <span class="nc">Person</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
<span class="lineno">2</span>   <span class="n">has_attached_file</span> <span class="ss">:avatar</span><span class="p">,</span> <span class="ss">:styles</span> <span class="o">=&gt;</span> <span class="p">{</span><span class="ss">:thumbnail</span> <span class="o">=&gt;</span> <span class="s2">&quot;75x75#&quot;</span><span class="p">}</span>
<span class="lineno">3</span> <span class="k">end</span>
</code></pre>
</div>


<p>Setup your routing for the admin namespaced &#8220;People&#8221; controller.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="no">ActionController</span><span class="o">::</span><span class="no">Routing</span><span class="o">::</span><span class="no">Routes</span><span class="o">.</span><span class="n">draw</span> <span class="k">do</span> <span class="o">|</span><span class="n">map</span><span class="o">|</span>
<span class="lineno">2</span>   <span class="n">map</span><span class="o">.</span><span class="n">namespace</span> <span class="ss">:admin</span> <span class="k">do</span> <span class="o">|</span><span class="n">admin</span><span class="o">|</span>
<span class="lineno">3</span>     <span class="n">admin</span><span class="o">.</span><span class="n">resources</span> <span class="ss">:people</span><span class="p">,</span> <span class="ss">:active_scaffold</span> <span class="o">=&gt;</span> <span class="kp">true</span>
<span class="lineno">4</span>   <span class="k">end</span>
<span class="lineno">5</span>   <span class="n">map</span><span class="o">.</span><span class="n">connect</span> <span class="s1">&#39;:controller/:action/:id&#39;</span>
<span class="lineno">6</span>   <span class="n">map</span><span class="o">.</span><span class="n">connect</span> <span class="s1">&#39;:controller/:action/:id.:format&#39;</span>
<span class="lineno">7</span> <span class="k">end</span>
</code></pre>
</div>


<p>Create a layout file for admin, I use Haml, and I recommend that you do too.</p>

<div class="highlight"><pre><code class="haml"><span class="lineno">1</span> <span class="nn">!!!STRICT</span>
<span class="lineno">2</span> <span class="nt">%html</span><span class="p">{</span><span class="s1">&#39;xmlns&#39;</span> <span class="o">=&gt;</span> <span class="s2">&quot;http://www.w3.org/1999/xhtml&quot;</span><span class="p">,</span> <span class="ss">:lang</span> <span class="o">=&gt;</span> <span class="s2">&quot;en&quot;</span><span class="p">}</span>
<span class="lineno">3</span>   <span class="nt">%head</span>
<span class="lineno">4</span>     <span class="p">=</span> <span class="n">javascript_include_tag</span> <span class="ss">:defaults</span>
<span class="lineno">5</span>     <span class="p">=</span> <span class="n">active_scaffold_includes</span>
<span class="lineno">6</span>   <span class="nt">%body</span>
<span class="lineno">7</span>     <span class="nf">#content</span>
<span class="lineno">8</span>       <span class="p">=</span> <span class="k">yield</span>
</code></pre>
</div>


<p>Finally, configure your active scaffolded controller.  The key here is to include the attachment model name, in this case &#8220;avatar&#8221;.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno"> 1</span> <span class="k">class</span> <span class="nc">Admin</span><span class="o">::</span><span class="no">PeopleController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
<span class="lineno"> 2</span>   <span class="n">layout</span> <span class="s1">&#39;admin&#39;</span>
<span class="lineno"> 3</span>   <span class="n">active_scaffold</span> <span class="ss">:person</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
<span class="lineno"> 4</span>     <span class="c1">#restrict all columns to these three</span>
<span class="lineno"> 5</span>     <span class="n">config</span><span class="o">.</span><span class="n">columns</span> <span class="o">=</span> <span class="o">[</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:avatar</span><span class="o">]</span>
<span class="lineno"> 6</span> 
<span class="lineno"> 7</span>     <span class="c1">#include multipart for create and update forms</span>
<span class="lineno"> 8</span>     <span class="n">config</span><span class="o">.</span><span class="n">create</span><span class="o">.</span><span class="n">multipart</span> <span class="o">=</span> <span class="kp">true</span>
<span class="lineno"> 9</span>     <span class="n">config</span><span class="o">.</span><span class="n">update</span><span class="o">.</span><span class="n">multipart</span> <span class="o">=</span> <span class="kp">true</span>
<span class="lineno">10</span>   <span class="k">end</span>
<span class="lineno">11</span> <span class="k">end</span>
</code></pre>
</div>


<p>When you are done you can go to &#8220;/admin/people&#8221; and you will be greeted with the familiar active scaffold interface.  Create a new Person and upload the avatar to be used for that Person.  Your result should be similar to this image:<br />

<img src="/images/as_paperclip_done.png" alt="as_paperclip_done.png" width="500px"/></p>

<p>You should download the source for this from my git repo <a href="http://github.com/bbwharris/examples/tree/master/as_paperclip/">here.</a></p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>I always recommend <a href="http://activescaffold.com/">Active Scaffold</a> to fellow Rails developers.  There is a learning curve, but it can cut a lot of development time out of your clients custom <span class="caps">CMS</span>.</p>
<p><a href="http://github.com/thoughtbot/paperclip">Paperclip</a> has pretty much dominated the Rails attachment market for the past year.  My company has migrated to it, and there are countless tutorials and testimonials regarding it&#8217;s ease of use.</p>
<p>I am assuming that you are using the latest version of Rails (2.3.5 as of this writing), Active Scaffold, and Paperclip.  First we will install all the necessary components, then we will configure the rails app.</p>
<p>Install Active Scaffold:</p>

<div class="highlight"><pre><code class="console"><span class="go">script/plugin install git://github.com/activescaffold/active_scaffold.git</span>
</code></pre>
</div>


<p>Active Scaffold is big so this takes a while.</p>
<p>Install Paperclip:</p>

<div class="highlight"><pre><code class="console"><span class="go">script/plugin install git://github.com/thoughtbot/paperclip.git</span>
</code></pre>
</div>


<p><em>As of 6/14/2010 this is no longer needed, the bridge has been moved to the core</em><br />
<del>Install the Active Scaffold Paperclip Bridge:</del></p>
<p>Lets create a basic person model:</p>

<div class="highlight"><pre><code class="console"><span class="go">script/generate model Person</span>
</code></pre>
</div>


<p>To create controllers in the admin namespace, I don&#8217;t use the rails controller generator. I don&#8217;t like cluttering up my projects with files I will never use, since I employ Active Scaffold for 99% of my admin interfaces.  This is my personal preference, you may do this anyway that you wish.</p>

<div class="highlight"><pre><code class="console"><span class="go">mkdir app/controllers/admin &amp;&amp; touch app/controllers/admin/people_controller.rb</span>
</code></pre>
</div>


<p>Lets configure the &#8220;Person&#8221; migration for paperclip.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno"> 1</span> <span class="k">class</span> <span class="nc">CreatePeople</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Migration</span>
<span class="lineno"> 2</span>   <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">up</span>
<span class="lineno"> 3</span>     <span class="n">create_table</span> <span class="ss">:people</span> <span class="k">do</span> <span class="o">|</span><span class="n">t</span><span class="o">|</span>
<span class="lineno"> 4</span>       <span class="n">t</span><span class="o">.</span><span class="n">string</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">:avatar_file_name</span><span class="p">,</span> <span class="ss">:avatar_content_type</span>
<span class="lineno"> 5</span>       <span class="n">t</span><span class="o">.</span><span class="n">integer</span> <span class="ss">:avatar_file_size</span>
<span class="lineno"> 6</span>       <span class="n">t</span><span class="o">.</span><span class="n">datetime</span> <span class="ss">:avatar_updated_at</span>
<span class="lineno"> 7</span>       <span class="n">t</span><span class="o">.</span><span class="n">timestamps</span>
<span class="lineno"> 8</span>     <span class="k">end</span>
<span class="lineno"> 9</span>   <span class="k">end</span>
<span class="lineno">10</span> 
<span class="lineno">11</span>   <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">down</span>
<span class="lineno">12</span>     <span class="n">drop_table</span> <span class="ss">:people</span>
<span class="lineno">13</span>   <span class="k">end</span>
<span class="lineno">14</span> <span class="k">end</span>
</code></pre>
</div>


<p>Configure the Person model to accept the paperclip attachment.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="k">class</span> <span class="nc">Person</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
<span class="lineno">2</span>   <span class="n">has_attached_file</span> <span class="ss">:avatar</span><span class="p">,</span> <span class="ss">:styles</span> <span class="o">=&gt;</span> <span class="p">{</span><span class="ss">:thumbnail</span> <span class="o">=&gt;</span> <span class="s2">&quot;75x75#&quot;</span><span class="p">}</span>
<span class="lineno">3</span> <span class="k">end</span>
</code></pre>
</div>


<p>Setup your routing for the admin namespaced &#8220;People&#8221; controller.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno">1</span> <span class="no">ActionController</span><span class="o">::</span><span class="no">Routing</span><span class="o">::</span><span class="no">Routes</span><span class="o">.</span><span class="n">draw</span> <span class="k">do</span> <span class="o">|</span><span class="n">map</span><span class="o">|</span>
<span class="lineno">2</span>   <span class="n">map</span><span class="o">.</span><span class="n">namespace</span> <span class="ss">:admin</span> <span class="k">do</span> <span class="o">|</span><span class="n">admin</span><span class="o">|</span>
<span class="lineno">3</span>     <span class="n">admin</span><span class="o">.</span><span class="n">resources</span> <span class="ss">:people</span><span class="p">,</span> <span class="ss">:active_scaffold</span> <span class="o">=&gt;</span> <span class="kp">true</span>
<span class="lineno">4</span>   <span class="k">end</span>
<span class="lineno">5</span>   <span class="n">map</span><span class="o">.</span><span class="n">connect</span> <span class="s1">&#39;:controller/:action/:id&#39;</span>
<span class="lineno">6</span>   <span class="n">map</span><span class="o">.</span><span class="n">connect</span> <span class="s1">&#39;:controller/:action/:id.:format&#39;</span>
<span class="lineno">7</span> <span class="k">end</span>
</code></pre>
</div>


<p>Create a layout file for admin, I use Haml, and I recommend that you do too.</p>

<div class="highlight"><pre><code class="haml"><span class="lineno">1</span> <span class="nn">!!!STRICT</span>
<span class="lineno">2</span> <span class="nt">%html</span><span class="p">{</span><span class="s1">&#39;xmlns&#39;</span> <span class="o">=&gt;</span> <span class="s2">&quot;http://www.w3.org/1999/xhtml&quot;</span><span class="p">,</span> <span class="ss">:lang</span> <span class="o">=&gt;</span> <span class="s2">&quot;en&quot;</span><span class="p">}</span>
<span class="lineno">3</span>   <span class="nt">%head</span>
<span class="lineno">4</span>     <span class="p">=</span> <span class="n">javascript_include_tag</span> <span class="ss">:defaults</span>
<span class="lineno">5</span>     <span class="p">=</span> <span class="n">active_scaffold_includes</span>
<span class="lineno">6</span>   <span class="nt">%body</span>
<span class="lineno">7</span>     <span class="nf">#content</span>
<span class="lineno">8</span>       <span class="p">=</span> <span class="k">yield</span>
</code></pre>
</div>


<p>Finally, configure your active scaffolded controller.  The key here is to include the attachment model name, in this case &#8220;avatar&#8221;.</p>

<div class="highlight"><pre><code class="ruby"><span class="lineno"> 1</span> <span class="k">class</span> <span class="nc">Admin</span><span class="o">::</span><span class="no">PeopleController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
<span class="lineno"> 2</span>   <span class="n">layout</span> <span class="s1">&#39;admin&#39;</span>
<span class="lineno"> 3</span>   <span class="n">active_scaffold</span> <span class="ss">:person</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
<span class="lineno"> 4</span>     <span class="c1">#restrict all columns to these three</span>
<span class="lineno"> 5</span>     <span class="n">config</span><span class="o">.</span><span class="n">columns</span> <span class="o">=</span> <span class="o">[</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:avatar</span><span class="o">]</span>
<span class="lineno"> 6</span> 
<span class="lineno"> 7</span>     <span class="c1">#include multipart for create and update forms</span>
<span class="lineno"> 8</span>     <span class="n">config</span><span class="o">.</span><span class="n">create</span><span class="o">.</span><span class="n">multipart</span> <span class="o">=</span> <span class="kp">true</span>
<span class="lineno"> 9</span>     <span class="n">config</span><span class="o">.</span><span class="n">update</span><span class="o">.</span><span class="n">multipart</span> <span class="o">=</span> <span class="kp">true</span>
<span class="lineno">10</span>   <span class="k">end</span>
<span class="lineno">11</span> <span class="k">end</span>
</code></pre>
</div>


<p>When you are done you can go to &#8220;/admin/people&#8221; and you will be greeted with the familiar active scaffold interface.  Create a new Person and upload the avatar to be used for that Person.  Your result should be similar to this image:<br />

<img src="/images/as_paperclip_done.png" alt="as_paperclip_done.png" width="500px"/></p>

<p>You should download the source for this from my git repo <a href="http://github.com/bbwharris/examples/tree/master/as_paperclip/">here.</a></p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>Create Git Patch From Commits</title>
    <link rel='alternate' type='text/html' href='/git/2009/11/19/create-git-patch-from-commits.html' />
    <id>tag:brandon-harris.com:/git/2009/11/19/create-git-patch-from-commits</id>
    <updated>2009-11-19T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>This is another of those excruciatingly easy tasks that isn&#8217;t well documented.</p>

<div class="highlight"><pre><code class="console"><span class="go">git format-patch sha1..sha2</span>
</code></pre>
</div>


<p>Where sha1 is the older commit and sha2 is the newer commit.  This will create patches for each modified file between those commits.</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>This is another of those excruciatingly easy tasks that isn&#8217;t well documented.</p>

<div class="highlight"><pre><code class="console"><span class="go">git format-patch sha1..sha2</span>
</code></pre>
</div>


<p>Where sha1 is the older commit and sha2 is the newer commit.  This will create patches for each modified file between those commits.</p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>Viewing Gem Rdoc</title>
    <link rel='alternate' type='text/html' href='/rails/2009/11/12/viewing-gem-rdoc.html' />
    <id>tag:brandon-harris.com:/rails/2009/11/12/viewing-gem-rdoc</id>
    <updated>2009-11-12T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>This is painfully obvious if you actually read about the tools that you use.  I couldn&#8217;t find anything on my first couple of google searches, so hopefully this can fill in that gap:</p>

<div class="highlight"><pre><code class="console"><span class="go">gem server</span>
</code></pre>
</div>


<p>Your gem server will probably start on port 8808, so go to localhost:8808 and you will see a list of your installed gems.  From here on, you probably know what to do.</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>This is painfully obvious if you actually read about the tools that you use.  I couldn&#8217;t find anything on my first couple of google searches, so hopefully this can fill in that gap:</p>

<div class="highlight"><pre><code class="console"><span class="go">gem server</span>
</code></pre>
</div>


<p>Your gem server will probably start on port 8808, so go to localhost:8808 and you will see a list of your installed gems.  From here on, you probably know what to do.</p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>Dell Studio 15 "White Screen of Death" Karmic Koala Workaround</title>
    <link rel='alternate' type='text/html' href='/karmic/ubuntu/2009/11/01/dell-studio-15-white-screen-of-death-karmic-koala-workaround.html' />
    <id>tag:brandon-harris.com:/karmic/ubuntu/2009/11/01/dell-studio-15-white-screen-of-death-karmic-koala-workaround</id>
    <updated>2009-11-01T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>It&#8217;s a horrible feeling to watch your system die after an upgrade.  You may have experienced this problem before.  Fear not, there is a workaround, and you will be back into your computer in no time.  Just follow these directions, they may appear slightly more advanced than what you might be used to, but this can be fixed.</p>
<p>Add &#8220;nomodeset&#8221; to the boot options in grub. Use vim (or nano, or whatever you like to use) to edit the boot options.  If you are booting from your hard drive on a recent upgrade, you can hit &#8220;Esc&#8221; at the grub boot screen and select the kernel after 2.6.31.</p>
<p>In my case it was 2.6.28-16.  You will be booting into Karmic with an Intrepid Kernel, don&#8217;t be surprised if some stuff doesn&#8217;t work perfectly, you are just doing this to have a way to edit the grub configuration.</p>
<p>Once you get into your system, do the following:</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo vim /boot/grub/menu.lst</span>
</code></pre>
</div>


<p>Change:</p>

<div class="highlight"><pre><code class="console"><span class="go">title           Ubuntu 9.10, kernel 2.6.31-14-generic</span>
<span class="go">uuid            76c6b53b-0181-4ebe-af5e-2abe3db988d7</span>
<span class="go">kernel          /boot/vmlinuz-2.6.31-14-generic root=UUID=76c6b53b-0181-4ebe-af5e-2abe3db988d7 ro xforcevesa quiet splash</span>
<span class="go">initrd          /boot/initrd.img-2.6.31-14-generic</span>
<span class="go">quiet</span>

<span class="go">title           Ubuntu 9.10, kernel 2.6.31-14-generic (recovery mode)</span>
<span class="go">uuid            76c6b53b-0181-4ebe-af5e-2abe3db988d7</span>
<span class="go">kernel          /boot/vmlinuz-2.6.31-14-generic root=UUID=76c6b53b-0181-4ebe-af5e-2abe3db988d7 ro xforcevesa  single</span>
<span class="go">initrd          /boot/initrd.img-2.6.31-14-generic</span>
</code></pre>
</div>


<p>To read like this:</p>

<div class="highlight"><pre><code class="console"><span class="go">title           Ubuntu 9.10, kernel 2.6.31-14-generic</span>
<span class="go">uuid            76c6b53b-0181-4ebe-af5e-2abe3db988d7</span>
<span class="go">kernel          /boot/vmlinuz-2.6.31-14-generic root=UUID=76c6b53b-0181-4ebe-af5e-2abe3db988d7 ro xforcevesa quiet splash nomodeset</span>
<span class="go">initrd          /boot/initrd.img-2.6.31-14-generic</span>
<span class="go">quiet</span>

<span class="go">title           Ubuntu 9.10, kernel 2.6.31-14-generic (recovery mode)</span>
<span class="go">uuid            76c6b53b-0181-4ebe-af5e-2abe3db988d7</span>
<span class="go">kernel          /boot/vmlinuz-2.6.31-14-generic root=UUID=76c6b53b-0181-4ebe-af5e-2abe3db988d7 ro xforcevesa  single nomodeset</span>
<span class="go">initrd          /boot/initrd.img-2.6.31-14-generic</span>
</code></pre>
</div>


<p>Don&#8217;t just copy-paste from this post, simply add &#8220;nomodeset&#8221; to the end of the line that starts with the word &#8220;kernel&#8221;, and only do this for the 2.6.31-14 kernel.</p>
<p>Reboot, and watch as you boot into your new Karmic upgrade.</p>
<p>This bug is being worked on in <a href="https://bugs.launchpad.net/ubuntu/hardy/+source/xserver-xorg-video-intel/+bug/297245">this ticket</a></p>
<p>Keep in mind that any new kernel updates might need this same workaround if you experience the &#8220;White Screen of Death&#8221;.</p>
<p>Blame <span class="caps">AUO</span> for jacking up the <span class="caps">EDID</span> for the panel, blame Dell for picking cheap parts, blame yourself for buying cheap hardware, certainly don&#8217;t blame the hardworking developers who provide you a great OS, they are hard at work fixing these issues.</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>It&#8217;s a horrible feeling to watch your system die after an upgrade.  You may have experienced this problem before.  Fear not, there is a workaround, and you will be back into your computer in no time.  Just follow these directions, they may appear slightly more advanced than what you might be used to, but this can be fixed.</p>
<p>Add &#8220;nomodeset&#8221; to the boot options in grub. Use vim (or nano, or whatever you like to use) to edit the boot options.  If you are booting from your hard drive on a recent upgrade, you can hit &#8220;Esc&#8221; at the grub boot screen and select the kernel after 2.6.31.</p>
<p>In my case it was 2.6.28-16.  You will be booting into Karmic with an Intrepid Kernel, don&#8217;t be surprised if some stuff doesn&#8217;t work perfectly, you are just doing this to have a way to edit the grub configuration.</p>
<p>Once you get into your system, do the following:</p>

<div class="highlight"><pre><code class="console"><span class="go">sudo vim /boot/grub/menu.lst</span>
</code></pre>
</div>


<p>Change:</p>

<div class="highlight"><pre><code class="console"><span class="go">title           Ubuntu 9.10, kernel 2.6.31-14-generic</span>
<span class="go">uuid            76c6b53b-0181-4ebe-af5e-2abe3db988d7</span>
<span class="go">kernel          /boot/vmlinuz-2.6.31-14-generic root=UUID=76c6b53b-0181-4ebe-af5e-2abe3db988d7 ro xforcevesa quiet splash</span>
<span class="go">initrd          /boot/initrd.img-2.6.31-14-generic</span>
<span class="go">quiet</span>

<span class="go">title           Ubuntu 9.10, kernel 2.6.31-14-generic (recovery mode)</span>
<span class="go">uuid            76c6b53b-0181-4ebe-af5e-2abe3db988d7</span>
<span class="go">kernel          /boot/vmlinuz-2.6.31-14-generic root=UUID=76c6b53b-0181-4ebe-af5e-2abe3db988d7 ro xforcevesa  single</span>
<span class="go">initrd          /boot/initrd.img-2.6.31-14-generic</span>
</code></pre>
</div>


<p>To read like this:</p>

<div class="highlight"><pre><code class="console"><span class="go">title           Ubuntu 9.10, kernel 2.6.31-14-generic</span>
<span class="go">uuid            76c6b53b-0181-4ebe-af5e-2abe3db988d7</span>
<span class="go">kernel          /boot/vmlinuz-2.6.31-14-generic root=UUID=76c6b53b-0181-4ebe-af5e-2abe3db988d7 ro xforcevesa quiet splash nomodeset</span>
<span class="go">initrd          /boot/initrd.img-2.6.31-14-generic</span>
<span class="go">quiet</span>

<span class="go">title           Ubuntu 9.10, kernel 2.6.31-14-generic (recovery mode)</span>
<span class="go">uuid            76c6b53b-0181-4ebe-af5e-2abe3db988d7</span>
<span class="go">kernel          /boot/vmlinuz-2.6.31-14-generic root=UUID=76c6b53b-0181-4ebe-af5e-2abe3db988d7 ro xforcevesa  single nomodeset</span>
<span class="go">initrd          /boot/initrd.img-2.6.31-14-generic</span>
</code></pre>
</div>


<p>Don&#8217;t just copy-paste from this post, simply add &#8220;nomodeset&#8221; to the end of the line that starts with the word &#8220;kernel&#8221;, and only do this for the 2.6.31-14 kernel.</p>
<p>Reboot, and watch as you boot into your new Karmic upgrade.</p>
<p>This bug is being worked on in <a href="https://bugs.launchpad.net/ubuntu/hardy/+source/xserver-xorg-video-intel/+bug/297245">this ticket</a></p>
<p>Keep in mind that any new kernel updates might need this same workaround if you experience the &#8220;White Screen of Death&#8221;.</p>
<p>Blame <span class="caps">AUO</span> for jacking up the <span class="caps">EDID</span> for the panel, blame Dell for picking cheap parts, blame yourself for buying cheap hardware, certainly don&#8217;t blame the hardworking developers who provide you a great OS, they are hard at work fixing these issues.</p>
]]>
    </content>
  </entry>
    
  <entry>
    <title>No More Comment Spam</title>
    <link rel='alternate' type='text/html' href='/2009/10/26/no-more-comment-spam.html' />
    <id>tag:brandon-harris.com:/2009/10/26/no-more-comment-spam</id>
    <updated>2009-10-26T00:00:00Z</updated>
    <updated></updated>

    <author>
      <name>Brandon Harris</name>
      <uri>http://brandon-harris.com</uri>
      <email>brandon@brandon-harris.com</email>
    </author>

    <summary><p>I have been receiving a lot of comment spam.  I would say around 30 comments a day. I wanted to try the simplest option possible, so I created a hidden field in the comment form that only a bot would fill out.  This was working under the assumption that bots don&#8217;t read css.  This worked for a little while.</p>
<p>My spam had been reduced to under 10 comments a day, which was still high, but maintainable.  As time went on, it crept back up to 30 or more a day. The next step was <a href="http://recaptcha.com">recaptcha</a>, which was a breeze to set up.</p>
<p>For two days now, my comment spam has totalled a big goose egg. 0.</p>
</summary>
    <content type='html' xml:lang='en' xml:base='http://brandon-harris.com'>
      <![CDATA[<p>I have been receiving a lot of comment spam.  I would say around 30 comments a day. I wanted to try the simplest option possible, so I created a hidden field in the comment form that only a bot would fill out.  This was working under the assumption that bots don&#8217;t read css.  This worked for a little while.</p>
<p>My spam had been reduced to under 10 comments a day, which was still high, but maintainable.  As time went on, it crept back up to 30 or more a day. The next step was <a href="http://recaptcha.com">recaptcha</a>, which was a breeze to set up.</p>
<p>For two days now, my comment spam has totalled a big goose egg. 0.</p>
]]>
    </content>
  </entry>
  
</feed>

