<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>A Real American Hero</title>
	<atom:link href="http://www.erikjacobs.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.erikjacobs.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Thu, 06 May 2010 03:17:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Random thoughts on net neutrality and free markets</title>
		<link>http://www.erikjacobs.com/2010/05/05/random-thoughts-on-net-neutrality-and-free-markets/</link>
		<comments>http://www.erikjacobs.com/2010/05/05/random-thoughts-on-net-neutrality-and-free-markets/#comments</comments>
		<pubDate>Thu, 06 May 2010 03:17:16 +0000</pubDate>
		<dc:creator>Erik Jacobs</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.erikjacobs.com/?p=123</guid>
		<description><![CDATA[Some random thoughts on net neutrality and free markets...]]></description>
			<content:encoded><![CDATA[<p>This is basically a copy of a comment I made on Fred Wilson&#8217;s blog, but I wanted to put it here so that other people (who might possibly pay attention to me) might see it, too.  So here are some random thoughts:</p>
<p>- Wireless technologies (WiFi) have evolved extremely quickly because they are largely &#8220;unregulated&#8221;. No one really owns the spectrum and every company can make a device that can access that spectrum, so they all compete to offer better performance/features/etc. in that space.</p>
<p>- The only organization that can create a monopoly is a government. Even if one company were to buy up everything and become the sole provider of a service, it still is not a monopoly. Either people will substitute something else in place of that service (walking instead of taking the train, even though it takes a long time), or someone will determine that the barrier to entry, no matter how significant, will ultimately provide a competitive alternative to the existing monopoly.</p>
<p>- Cable and telephone companies have &#8220;near&#8221; monopoly over internet access, but it is only because they have already eaten the tremendous costs of infrastructure over time, and happened to be able to retrofit this infrastructure for use as a data transport infrastructure.</p>
<p>- Verizon seems to think that, despite the start-up cost, there is competitive benefit to them setting up a new higher-speed data transport infrastructure, as one example. Companies like Clear have decided that, despite the lack of comparable performance to other options today, there is a competitve to their investing in the infrastructure for their wireless data service infrastructure.</p>
<p>- &#8220;Net Neutrality&#8221; and spectrum auctions will likely serve to neuter the inevitable explosion in over-the-air as an alternative to existing wired data service infrastructures. Instead of net neutrality making the internet and data services better, it will ultimately serve to further reinforce the near monopoly that the cable companies and phone companies already have by eliminating the competitive benefit that the wireless providers can exert over the cable companies by being net neutral. If Comcast were allowed to really really manipulate its network traffic, customers who did not like this would move to services like Clear in favor of a neutral experience as a trade-off to performance. Forcing the net neutrality hand means that this inevitable movement is going to be stifled.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.erikjacobs.com/2010/05/05/random-thoughts-on-net-neutrality-and-free-markets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updating Air on Fedora 12 breaks it&#8230; hell ensues</title>
		<link>http://www.erikjacobs.com/2010/01/12/updating-air-on-fedora-12-breaks-it-hell-ensues/</link>
		<comments>http://www.erikjacobs.com/2010/01/12/updating-air-on-fedora-12-breaks-it-hell-ensues/#comments</comments>
		<pubDate>Tue, 12 Jan 2010 14:43:35 +0000</pubDate>
		<dc:creator>Erik Jacobs</dc:creator>
				<category><![CDATA[Fedora]]></category>

		<guid isPermaLink="false">http://www.erikjacobs.com/?p=120</guid>
		<description><![CDATA[After getting messages about updating Adobe Air for a while, I finally decided to bite the bullet and do it. Big mistake.]]></description>
			<content:encoded><![CDATA[<p>After getting messages about updating Adobe Air for a while, I finally decided to bite the bullet and do it.</p>
<p>Big mistake.</p>
<p>Crazy hell ensued, in that nothing from <a title="Adobe Air" href="http://www.adobe.com/products/air/" target="_blank">Air</a> would work any more after that, and all I got was cryptic core dumps. I tried to uninstall Air and <a title="Tweetdeck - an Air Twitter client" href="http://www.tweetdeck.com" target="_blank">Tweetdeck</a>, and failed at that for a while, too, until I figured out the following:</p>
<ol>
<li>Air and Air applications like Tweetdeck actually end up as RPMs.  You can (should) remove them using rpm -e as the root user or with sudo.  (found via <a title="Adobe Air Linux stuff" href="http://blogs.adobe.com/air/2008/12/tips_on_resolving_application.html" target="_blank">Adobe&#8217;s page</a>, sort of)</li>
<li>I found the rpms by grepping: rpm -qa | grep ado &#8212; or &#8212; rpm -qa | grep weet</li>
<li>You may have to remove or move your <a title="Adobe Air Forums" href="http://forums.adobe.com/message/2380277#2380277" target="_blank">certificates folder</a> in /etc/opt</li>
</ol>
<p>So, if you decide to update Adobe Air on your Fedora 12 box and suddenly everything seems borked, you might just want to uninstall everything and install from scratch.  I just did this and it worked well, and I&#8217;m up and running with the latest Tweetdeck for Linux.</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 64px; width: 1px; height: 1px;">http://www.adobe.com/products/air/</div>
]]></content:encoded>
			<wfw:commentRss>http://www.erikjacobs.com/2010/01/12/updating-air-on-fedora-12-breaks-it-hell-ensues/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Manipulating links with HTML select and jQuery</title>
		<link>http://www.erikjacobs.com/2010/01/04/manipulating-links-with-html-select-and-jquery/</link>
		<comments>http://www.erikjacobs.com/2010/01/04/manipulating-links-with-html-select-and-jquery/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 00:27:41 +0000</pubDate>
		<dc:creator>Erik Jacobs</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.erikjacobs.com/?p=114</guid>
		<description><![CDATA[As with most web projects, there's always some little new glitch that pops up. We've been building and massaging our own analytics back end for Riding Resource for some time now, and the change of year from 2009 to 2010 brought some new quirks that had to be dealt with.]]></description>
			<content:encoded><![CDATA[<p>As with most web projects, there&#8217;s always some little new glitch that pops up. We&#8217;ve been building and massaging our own analytics back end for <a title="Riding Resource - A Stable Place to Search" href="http://www.ridingresource.com" target="_blank">Riding Resource</a> for some time now, and the change of year from 2009 to 2010 brought some new quirks that had to be dealt with.</p>
<p>While there were some minor issues related to year/day calculations creating invalid dates, the bigger issue that (I think) was solved rather elegantly was choosing, via a select tag, which year&#8217;s analytics report to generate. <a title="jQuery" href="http://jQuery.com" target="_blank">jQuery</a> came to the rescue, with what turned out to be a far more simple solution than I originally had envisioned.</p>
<p>Select tags are not exactly the most complicated things in the world. But when you don&#8217;t have a form to go with them, it&#8217;s hard sometimes to figure out how to make them be useful. Instead of having a link for every year&#8217;s report, I figured a nice little drop-down would be an elegant way to choose. But this is where the difficulty was. I wanted a single text link to the report, but I wanted to change what that link actually&#8230; linked to&#8230; based on the selection in the box.</p>
<p>Here&#8217;s some of the original HTML that was generated by the app:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;">  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;union-county-veterinary-clinic-target&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/analytics/show2/union-county-veterinary-clinic.pdf&quot;</span>&gt;</span>PDF<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">select</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;union-county-veterinary-clinic-select&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;date[year]&quot;</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">option</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;2009&quot;</span>&gt;</span>2009<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">option</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">option</span> <span style="color: #000066;">selected</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;selected&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;2010&quot;</span>&gt;</span>2010<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">option</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">select</span>&gt;</span></pre></div></div>

<p>Here is where jQuery came to the rescue, and some generous fellow with the handle of &#8220;kit10&#8243; on the #jquery channel on IRC on <a title="Freenode IRC network" href="http://freenode.net/" target="_blank">Freenode</a>. kit10 suggested that I add a &#8220;rel&#8221; attribute to the select element, and give that &#8220;rel&#8221; attribute the value of the id of the PDF link. In this way, jQuery could look at the select element, and, when it changed, update the link. After a few machinations, here&#8217;s what popped out:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">  $<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      <span style="color: #006600; font-style: italic;">// courtesy of kit10 on #jquery on freenode</span>
      $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;select[id$='-select']&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">change</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> target <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#'</span><span style="color: #339933;">+</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'rel'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// set the target to be the value of the rel of the selector</span>
        <span style="color: #003366; font-weight: bold;">var</span> regex <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/year=\d\d\d\d/</span>
        target.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'href'</span><span style="color: #339933;">,</span>target.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'href'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span>regex<span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;year=&quot;</span><span style="color: #339933;">+</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>To read this code in a sense of plain english:<br />
Whenever a select element that contains &#8216;-select&#8217; in the ID changes<br />
Create a variable called target, and assign it the value of the rel attribute of the select element<br />
Replace the href attribute of the target with the new year by using the regex of /year=\d\d\d\d/ (to match year=2009, year=2010, etc)</p>
<p>That was really all there is to it. The new HTML ended up looking like as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;">  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;1000-acres-ranch-target&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/analytics/show2/1000-acres-ranch.pdf?year=2009&quot;</span>&gt;</span>PDF<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">select</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;1000-acres-ranch-select&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;date[year]&quot;</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">option</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;2009&quot;</span>&gt;</span>2009<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">option</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">option</span> <span style="color: #000066;">selected</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;selected&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;2010&quot;</span>&gt;</span>2010<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">option</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">select</span>&gt;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.erikjacobs.com/2010/01/04/manipulating-links-with-html-select-and-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twitter integration and parsing links with Ruby on Rails</title>
		<link>http://www.erikjacobs.com/2009/10/29/twitter-integration-and-parsing-links-with-ruby-on-rails/</link>
		<comments>http://www.erikjacobs.com/2009/10/29/twitter-integration-and-parsing-links-with-ruby-on-rails/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 22:28:04 +0000</pubDate>
		<dc:creator>Erik Jacobs</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.erikjacobs.com/?p=107</guid>
		<description><![CDATA[A while back, we had an issue with Twitter integration that messed up the homepage. I got some time today to fix things, so I figured I would write a little bit about how RidingResource has integrated Twitter into our homepage and about how parsing links works in Ruby on Rails.]]></description>
			<content:encoded><![CDATA[<p>As per usual, it&#8217;s been a while since I&#8217;ve written anything about <a title="Ruby on Rails" href="http://www.rubyonrails.org" target="_blank">Ruby on Rails</a> or <a title="Riding Resource - A Stable Place to Search" href="http://www.ridingresource.com" target="_blank">RidingResource</a>. A while back, we had an issue with <a title="Twitter" href="http://www.twitter.com" target="_blank">Twitter</a> integration that messed up the homepage. I got some time today to fix things, so I figured I would write a little bit about how RidingResource has integrated Twitter into our homepage and about how parsing links works in Ruby on Rails.</p>
<p>When we were first building RidingResource, we decided it might be cool to have the last few tweets from our RidingResource Twitter account displayed on the home page.  It took me a minute, but, like with most things you want to do with Ruby on Rails, there&#8217;s a <a title="The RubyGems packaging system" href="http://docs.rubygems.org/" target="_blank">gem</a>/plugin for that.  The one we chose happens to be <a title="Dancroak's Twitter Search Gem" href="http://github.com/dancroak/twitter-search" target="_blank">Dancroak&#8217;s Twitter Search</a>.  The neat thing about this gem is that it allows you to grab things off Twitter very easily, and then use them however you like.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> home
  <span style="color:#008000; font-style:italic;">## set up twitter client</span>
  <span style="color:#0066ff; font-weight:bold;">@client</span> = <span style="color:#6666ff; font-weight:bold;">TwitterSearch::Client</span>.<span style="color:#9900CC;">new</span> <span style="color:#996600;">'equine'</span>
&nbsp;
  <span style="color:#008000; font-style:italic;">## pull in last 3 tweets</span>
  <span style="color:#0066ff; font-weight:bold;">@tweets</span> = <span style="color:#0066ff; font-weight:bold;">@client</span>.<span style="color:#9900CC;">query</span> <span style="color:#ff3333; font-weight:bold;">:q</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'from:ridingresource'</span>, <span style="color:#ff3333; font-weight:bold;">:rpp</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">3</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Well, this is all well and good, but one thing I quickly realized when we initially did this is that when we posted a link in a tweet, it is parsed fine if you look at it on Twitter&#8217;s website or through other clients, but we were basically just regurgitating the text of the tweet with no markup. When I went to reinstate the Twitter feed on the homepage today, I started looking into ways to parse URLs with <a title="The Ruby Programming Language" href="http://www.ruby-lang.org/en/" target="_blank">Ruby</a> (on Rails) that were already in strings and to display them with the proper hypertext markup. What I found were some neat snippets on <a title="Snippets - A public source code repository" href="http://snippets.dzone.com/" target="_blank">DZone</a> that did just that.</p>
<p>After some careful Googling and search-term hackery, I stumbled upon this DZone snippet that discusses how to <a title="Convert URLs to Hyperlinks" href="http://snippets.dzone.com/posts/show/7456" target="_blank">convert URLs into hyperlinks</a>. This snippet written by <a title="James Robertson" href="http://www.r0bertson.co.uk/" target="_blank">James Robertson</a> makes use of a gem, <a title="Alex Rabarts TLD" href="http://github.com/alexrabarts/tld/" target="_blank">alexrabarts-tld</a>, which does some checking to see if items are actually a real domain TLD. As James found, like with many things Ruby, you can pass the items that come out of a gsub <a title="Regular Expressions" href="http://en.wikipedia.org/wiki/Regular_expression" target="_blank">regexp</a> into a block, which enables us to replace the URL in the string with the hypertext for the URL.</p>
<p>Because we were going to use this substitution on every single tweet to check if there were any URLs,  I created a nifty little helper function to do just that.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> hyperlink_parser<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">string</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#CC0066; font-weight:bold;">string</span>.<span style="color:#CC0066; font-weight:bold;">gsub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#40;</span>\w<span style="color:#006600; font-weight:bold;">+</span>\.<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006666;">1</span>,<span style="color:#006666;">3</span><span style="color:#006600; font-weight:bold;">&#125;</span>\w<span style="color:#006600; font-weight:bold;">+</span>\<span style="color:#006600; font-weight:bold;">/</span>\w<span style="color:#006600; font-weight:bold;">+</span><span style="color:#006600; font-weight:bold;">&#91;</span>^\s<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>x<span style="color:#006600; font-weight:bold;">|</span> is_tld?<span style="color:#006600; font-weight:bold;">&#40;</span>x<span style="color:#006600; font-weight:bold;">&#41;</span> ? <span style="color:#996600;">&quot;&lt;a href='#{x}' class='#{link_class}'&gt;#{x}&lt;/a&gt;&quot;</span> : x<span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>One thing I noticed was that if URLs were in the text that had http:// in them, we would match the rest of the URL, hyperlink the FQDN and other parts of the link, but ignore the http://. It looked really funny to have a link that looked like http://<a title="Erik Jacobs - A Real American Hero" href="http://www.erikjacobs.com">www.erikjacobs.com</a> I realized that this was just a &#8220;problem&#8221; with the original RegExp that Jason had created, so I started to do some sleuthing.</p>
<p>The first thing I did was try to find a RegExp tester. While there are many out there, the one I ended up using was <a title="Rubular - a Ruby regular expression editor" href="http://rubular.com/" target="_blank">Rubular</a> (conveniently uses Ruby &#8211; look at that!), which displays the results of our RegExp search against the text in real time. Some careful googling of selected RegExp and URL terms resulted in yet another snippet from DZone, by Rafael Trindade. Getting closer!</p>
<p>Lastly, since this function might just possibly be used elsewhere, and since I wanted to apply a style at least to the links generated by its use here, I decided to add another argument to the helper method for the link class. The result is the following helper:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> hyperlink_parser<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">string</span>, link_class=<span style="color:#996600;">&quot;&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#CC0066; font-weight:bold;">string</span>.<span style="color:#CC0066; font-weight:bold;">gsub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#40;</span>ftp<span style="color:#006600; font-weight:bold;">|</span>http<span style="color:#006600; font-weight:bold;">|</span>https<span style="color:#006600; font-weight:bold;">&#41;</span>:\<span style="color:#006600; font-weight:bold;">/</span>\<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#40;</span>\w<span style="color:#006600; font-weight:bold;">+</span>:<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006666;">0</span>,<span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#125;</span>\w<span style="color:#006600; font-weight:bold;">*</span>@<span style="color:#006600; font-weight:bold;">&#41;</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>\S<span style="color:#006600; font-weight:bold;">+</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#40;</span>:<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">9</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span><span style="color:#006600; font-weight:bold;">&#41;</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>\<span style="color:#006600; font-weight:bold;">/|</span>\<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#91;</span>\w<span style="color:#008000; font-style:italic;">#!:.?+=&amp;%@!\-\/]))?/) {|x| is_tld?(x) ? &quot;&lt;a href='#{x}' class='#{link_class}'&gt;#{x}&lt;/a&gt;&quot; : x}</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The view essentially just iterates over the tweets that came back from the search, rendering a partial:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">for</span> tweet <span style="color:#9966CC; font-weight:bold;">in</span> <span style="color:#0066ff; font-weight:bold;">@tweets</span> <span style="color:#006600; font-weight:bold;">-%&gt;</span>
  <span style="color:#006600; font-weight:bold;">&lt;%</span>= render <span style="color:#ff3333; font-weight:bold;">:partial</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;tweet&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:object</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> tweet <span style="color:#006600; font-weight:bold;">%&gt;</span>
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">-%&gt;</span></pre></div></div>

<p>And inside the partial we do a few things with the tweet, including linking to the original tweet on Twitter&#8217;s site, showing the date, and parsing the text for the URL and returning it:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://www.twitter.com/RidingResource/status/<span style="color:#006600; font-weight:bold;">&lt;%</span>= tweet.<span style="color:#9900CC;">id</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&quot; target=&quot;_blank&quot;&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= tweet.<span style="color:#9900CC;">created_at</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">5</span>,<span style="color:#006666;">11</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/a&gt; <span style="color:#006600; font-weight:bold;">&lt;%</span>= hyperlink_parser<span style="color:#006600; font-weight:bold;">&#40;</span>tweet.<span style="color:#9900CC;">text</span>, <span style="color:#996600;">&quot;tweet&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/p&gt;&lt;/li&gt;</pre></div></div>

<p>Hopefully some of you will find this useful in your quest to either integrate Twitter into your Ruby on Rails&#8217; projects, or to perhaps parse some things that live inside strings into markup. There is almost surely something that already does this, so I probably re-invented the wheel, but it didn&#8217;t take long and it seems to work.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.erikjacobs.com/2009/10/29/twitter-integration-and-parsing-links-with-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Git socket timeout issues with CentOS</title>
		<link>http://www.erikjacobs.com/2009/09/13/git-socket-timeout-issues-with-centos/</link>
		<comments>http://www.erikjacobs.com/2009/09/13/git-socket-timeout-issues-with-centos/#comments</comments>
		<pubDate>Sun, 13 Sep 2009 19:50:44 +0000</pubDate>
		<dc:creator>Erik Jacobs</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.erikjacobs.com/?p=104</guid>
		<description><![CDATA[RidingResource.com was developed in Ruby on Rails, as many of you may know.  At some point this year I made the switch from using a local Subversion source control system to using Github, which has been pretty good.  The one pain I was having, which I thought was a CentOS 4 / libcurl issue, actually turned out to be the APF firewall that Wiredtree uses on all of their VPS.]]></description>
			<content:encoded><![CDATA[<p>So <a title="Riding Resource - A Stable Place to Search" href="http://www.ridingresource.com" target="_blank">Riding Resource</a> was developed in <a title="Ruby on Rails" href="http://www.rubyonrails.org" target="_blank">Ruby on Rails</a>, as many of you may know.  At some point this year I made the switch from using a local <a title="Subversion - An open source version control system" href="http://subversion.tigris.org/" target="_blank">Subversion</a> source control system to using <a title="git - Fast Version Control System" href="http://git-scm.com/" target="_blank">git</a> with <a title="Github - Social Coding" href="http://www.github.com/" target="_blank">Github</a>, which has been pretty good.  The one pain I was having, which I thought was a <a title="CentOS - The Community ENterprise Operating System" href="http://www.centos.org/" target="_blank">CentOS</a> 4 / libcurl issue, actually turned out to be the <a title="APF - Advanced Policy Firewall" href="http://www.rfxn.com/?page_id=6" target="_blank">APF</a> firewall that <a title="Wiredtree" href="http://www.wiredtree.com" target="_blank">Wiredtree </a>uses on all of their VPS.</p>
<p>APF is a pretty neat firewall.  It does a lot of neat things.  It&#8217;s also installed by default on the VPS we use from Wiredtree.  When I would pull or clone our private repository for <a title="Riding Resource - A Stable Place to Search" href="http://www.ridingresource.com/" target="_blank">Riding Resource</a>, I had no issues with git.  However, trying to clone public repositories I would always be greeted with something like:</p>
<pre>fatal: unable to connect a socket (Connection timed out)</pre>
<p>It took me a little while to figure out what was going on here, but what I tracked it down to was actually a firewall issue, and not any kind of issue with git or <a title="Github - Social Coding" href="http://www.github.com/" target="_blank">Github</a>.  I don&#8217;t know how I figured it out, but I discovered that cloning with <a title="Github - Social Coding" href="http://www.github.com/" target="_blank">Github</a> uses port 9418.  This link discusses using tunnels and mentions the port.</p>
<p>After some inspection, I realized that inbound and outbound traffic was blocked by <a title="APF - Advanced Policy Firewall" href="http://www.rfxn.com/?page_id=6" target="_blank">APF</a> on port 9418.  A quickie modification to the EG_TCP_CPORTS and IG_TCP_CPORTS values by adding 9418 and restarting the APF service managed to do the trick.</p>
<p>This is definitely not relegated only to<a title="CentOS - The Community ENterprise Operating System" href="http://www.centos.org/" target="_blank"> CentOS</a> or to systems running APF when trying to clone from Github.  Any Linux system could be subject to these timeout issues against Github if your firewall is configured to block 9418. So if you are seeing socket connection issues, or fatal errors with fetch-pack, you might just want to check your firewall.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.erikjacobs.com/2009/09/13/git-socket-timeout-issues-with-centos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom (dynamic) error pages with Ruby on Rails</title>
		<link>http://www.erikjacobs.com/2009/08/05/custom-dynamic-error-pages-with-ruby-on-rails/</link>
		<comments>http://www.erikjacobs.com/2009/08/05/custom-dynamic-error-pages-with-ruby-on-rails/#comments</comments>
		<pubDate>Wed, 05 Aug 2009 18:13:00 +0000</pubDate>
		<dc:creator>Erik Jacobs</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.erikjacobs.com/?p=101</guid>
		<description><![CDATA[One thing that bugged me with Riding Resource was error pages. Sure, Rails allows you to create static 404 and 500 and other pages for those situations when things go awry. But the fact that those pages were static caused me some heartburn.]]></description>
			<content:encoded><![CDATA[<p><a title="Ruby on Rails" href="http://www.rubyonrails.org" target="_blank">Ruby on Rails</a> is pretty neat stuff. Whenever I try to find out how to do something, it seems that I&#8217;m not the first to look. And, fortunately, many have usually solved that problem before. One thing that bugged me with <a title="Riding Resource - A Stable Place to Search" href="http://www.ridingresource.com" target="_blank">Riding Resource</a> was error pages. Sure, Rails allows you to create static 404 and 500 and other pages for those situations when things go awry. But the fact that those pages were static caused me some heartburn.</p>
<p>For one, if the layout of the website changed, it meant I needed to update the error pages. This is certainly not <a title="Don't repeat yourself" href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself" target="_blank">DRY</a>. And, using static pages, I could not use any <a title="Ruby - A programmer's best friend" href="http://www.ruby-lang.org" target="_blank">Ruby</a> code in my error page, or do anything dynamically at all.</p>
<p>After some quick searching, I came across <a title="Rails 2.2 Custom Error Pages With Exception Loggable" href="http://blog.ubrio.us/code/rails-22-custom-error-pages-with-exception-loggable/" target="_blank">this post</a> by Rob Hurring which lead me to <a title="Rescue from dispatching" href="http://m.onkey.org/2008/7/20/rescue-from-dispatching" target="_blank">this post</a> on has_many :bugs, :through =&gt; :rails regarding how to create customized error pages with Ruby on Rails. Granted, neither of these solutions was exactly what I was looking for, so a little customization was required. However, the basic requirements were met.</p>
<ol>
<li>we can see that we can <a title="Module: ActiveSupport::Rescuable::ClassMethods" href="http://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html#M001002" target="_blank">rescue_from</a> many of the standard <a title="Module: ActionController::Rescue" href="http://api.rubyonrails.org/classes/ActionController/Rescue.html" target="_blank">ActionController</a> errors.</li>
<li>using :with, we can specify a method to invoke to process the rescue activity</li>
<li>the method called to rescue us can render a page with a layout</li>
</ol>
<p>This took care of everything we needed. For almost all of the error types that would arise, we could redirect to a custom 404 template that allowed for Ruby to be embedded that would use any number of existing layouts, which keeps things tight and DRY.</p>
<p>One caveat that we had particularly related to <a title="Riding Resource - A Stable Place to Search" href="http://www.ridingresource.com" target="_blank">Riding Resource</a> was that meta tags are currently generated on the fly by a view helper, but we are actually looking at the current params to determine what controller/action we are in, and, therefore, what meta tags to spit out. Unfortunately, I could not find a way to detect, within the template, what status the template had been rendered with.</p>
<p>I ended up creating an instance variable before rendering the error template:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#6666ff; font-weight:bold;">ActionController::Base</span>.<span style="color:#9900CC;">consider_all_requests_local</span>
  <span style="color:#008000; font-style:italic;"># yeah, its a long line</span>
  rescue_from <span style="color:#6666ff; font-weight:bold;">ActiveRecord::RecordNotFound</span>, <span style="color:#6666ff; font-weight:bold;">ActionController::RoutingError</span>, <span style="color:#6666ff; font-weight:bold;">ActionController::UnknownController</span>, <span style="color:#6666ff; font-weight:bold;">ActionController::UnknownAction</span>, <span style="color:#ff3333; font-weight:bold;">:with</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:render_404</span>
  rescue_from <span style="color:#CC00FF; font-weight:bold;">RuntimeError</span>, <span style="color:#ff3333; font-weight:bold;">:with</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:render_500</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
protected
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> render_404
  <span style="color:#0066ff; font-weight:bold;">@status</span> = <span style="color:#996600;">&quot;404&quot;</span>
  render <span style="color:#ff3333; font-weight:bold;">:template</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;shared/404&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:status</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:not_found</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>By creating this instance variable, I could then check for the value of @status in my meta tag generator and properly handle things.</p>
<p>One caveat to this solution, in general, is that errors that occur with your process of rendering the custom page will result in no errors being shown at all, except for in the log. Note Ron&#8217;s trick to be able to generate the custom error pages even while in development mode.</p>
<p>In the long term I will probably clean up the meta tag generator to create instance variables and then use partials to get the information into the view, but that&#8217;s for another day. We also recently added <a title="Paperclip - Manage Uploaded Files Without Hassle" href="http://www.thoughtbot.com/projects/paperclip" target="_blank">Thoughtbot&#8217;s Paperclip</a> plugin to be able to easily attach pictures of facilities, but that post will be made once we get watermarking working.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.erikjacobs.com/2009/08/05/custom-dynamic-error-pages-with-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting non-native resolutions in F11</title>
		<link>http://www.erikjacobs.com/2009/06/24/setting-non-native-resolutions-in-f11/</link>
		<comments>http://www.erikjacobs.com/2009/06/24/setting-non-native-resolutions-in-f11/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 19:45:10 +0000</pubDate>
		<dc:creator>Erik Jacobs</dc:creator>
				<category><![CDATA[Fedora]]></category>

		<guid isPermaLink="false">http://www.erikjacobs.com/?p=96</guid>
		<description><![CDATA[I know, I know -- I haven't blogged about RidingResource in a while, but we've been focusing on other non-blogworthy stuff like starting to promote and fixing little goofy bugs here and there. I have, however, been poking about with Fedora 11 (Leonidas) and have been finding little tricks and things here and there to make life easier. One thing I found was that the new F11 has the nifty KMS stuff that gives you the slick graphical boot up and seamless login into Gnome (X). However, one thing I noticed that was missing was the ability to set non-native resolutions in the display settings.]]></description>
			<content:encoded><![CDATA[<p>I know, I know &#8212; I haven&#8217;t blogged about <a title="Riding Resource - A Stable Place to Search" href="http://www.ridingresource.com" target="_blank">RidingResource</a> in a while, but we&#8217;ve been focusing on other non-blogworthy stuff like starting to promote and fixing little goofy bugs here and there. I have, however, been poking about with <a title="Fedora Project" href="http://www.fedoraproject.org" target="_blank">Fedora</a> 11 (Leonidas) and have been finding little tricks and things here and there to make life easier. One thing I found was that the new F11 has the nifty <a title="KMS in Fedora 11" href="https://fedoraproject.org/wiki/KMS_in_Fedora_11" target="_blank">KMS</a> stuff that gives you the slick graphical boot up and seamless login into Gnome (X). However, one thing I noticed that was missing was the ability to set non-native resolutions in the display settings.</p>
<p>For some, this ability is important. For example, I frequently conduct presentations online and not everyone that I present to has a widescreen monitor. Trying to share a desktop/application at 1680&#215;1050 when the viewer only can see 1024&#215;768 makes things difficult for the viewer.  They end up having to scroll and do all kinds of other goofy stuff that annoys them.</p>
<p>For the life of me, I couldn&#8217;t figure out where these non-native resolutions &#8220;went.&#8221; I remember being able to set them in F10 without doing anything fancy, but in F11 these &#8220;extra&#8221; modes were curiously absent. After some prodding around, a kind fellow in #fedora on <a title="Freenode" href="http://freenode.net/" target="_blank">freenode</a> suggested trying to disable KMS when booting in grub by adding the &#8220;nomodeset&#8221; option. This actually did the trick. While I lose the cute bootup sequence, I can always create another grub boot option that still has the KMS enabled. I can boot normally, or boot with &#8220;nomodeset&#8221; when I know I&#8217;ve got to do a presentation.</p>
<p>Hopefully this information helps!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.erikjacobs.com/2009/06/24/setting-non-native-resolutions-in-f11/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fedora 11 (Leonidas) and Adobe AIR</title>
		<link>http://www.erikjacobs.com/2009/05/21/fedora-11-leonidas-and-adobe-air/</link>
		<comments>http://www.erikjacobs.com/2009/05/21/fedora-11-leonidas-and-adobe-air/#comments</comments>
		<pubDate>Thu, 21 May 2009 21:08:16 +0000</pubDate>
		<dc:creator>Erik Jacobs</dc:creator>
				<category><![CDATA[Fedora]]></category>

		<guid isPermaLink="false">http://www.erikjacobs.com/?p=93</guid>
		<description><![CDATA[As is to be expected with installing or upgrading any operating system, there might be a few speed bumps along the road. I recently updated one of my laptops to run the latest Fedora 11, Leonidas, and have been spending time re-installing software that I want to use. One thing that I ended up using quite a bit was Adobe AIR with Tweetdeck, a Twitter client.  Adobe is kind enough to provide an Adobe AIR for Linux.]]></description>
			<content:encoded><![CDATA[<p>As is to be expected with installing or upgrading any operating system, there might be a few speed bumps along the road. I recently updated one of my laptops to run the latest <a title="Fedora Project" href="http://fedoraproject.org" target="_blank">Fedora 11</a>, Leonidas, and have been spending time re-installing software that I want to use. One thing that I ended up using quite a bit was <a title="Adobe AIR" href="http://www.adobe.com/products/air/" target="_blank">Adobe AIR</a> with <a title="Tweetdeck" href="http://www.tweetdeck.com/" target="_blank">Tweetdeck</a>, a Twitter client.  Adobe is kind enough to provide an Adobe AIR for Linux.</p>
<p>Installing Adobe AIR should be relatively trivial, but I ran into some roadblocks that you might be experiencing, and had some recollection of my experience with F10, so I thought I&#8217;d post them here.</p>
<ol>
<li>Run the installer as the root user or with sudo</li>
<li>I found in several sources that creating a ~/.airinstall.log file will output the (inevitable) error messages in (somewhat) greater detail <em>somewhere</em></li>
<li>If you get such errors, and you see something about rpmbuild, you may need to install the rpm-build package</li>
<li>If you get more errors, you might find something that whines about librpmbuild.so and librpmbuild-4.7.so  I noticed that there was already a librpmbuild.so.0.0.0 in /usr/lib, so I took a gamble and created a symlink to librpmbuild.so and attempted to reinstall.</li>
</ol>
<p>Doing these 4 things managed to get Adobe AIR to install in Fedora 11, so hopefully it will work for you, too.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.erikjacobs.com/2009/05/21/fedora-11-leonidas-and-adobe-air/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Internal Analytics with Open Flash Chart</title>
		<link>http://www.erikjacobs.com/2009/03/28/internal-analytics-with-open-flash-chart/</link>
		<comments>http://www.erikjacobs.com/2009/03/28/internal-analytics-with-open-flash-chart/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 14:01:00 +0000</pubDate>
		<dc:creator>Erik Jacobs</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.erikjacobs.com/?p=90</guid>
		<description><![CDATA[We wanted to be able to get some analytics for the various facilities on RidingResource, and that required some thinking. While Google Analytics is certainly great, and we use it heavily, there are some things that it can't capture that are valuable data to both us and our customers.]]></description>
			<content:encoded><![CDATA[<p>We wanted to be able to get some analytics for the various facilities on <a title="Riding Resource - A Stable Place to Search" href="http://www.RidingResource.com" target="_blank">RidingResource</a>, and that required some thinking. While <a title="Google Analytics - Win customers, not just visitors." href="http://www.google.com/analytics/" target="_blank">Google Analytics</a> is certainly great, and we use it heavily, there are some things that it can&#8217;t capture that are valuable data to both us and our customers.</p>
<p>Since <a title="Riding Resource - A Stable Place to Search" href="http://www.RidingResource.com" target="_blank">RidingResource</a> is essentially a search engine, we realized that there was value in knowing how often a facility&#8217;s listing &#8220;came up,&#8221; either by being directly viewed on it&#8217;s detail page, or also by being seen in the search results page. Since we also built an API for a partner, which we&#8217;ll announce publicly once it goes live, we thought it would be valuable to track API &#8220;hits&#8221; as well.</p>
<p>Creating the table to store the analytics data was relatively simple. We just created an Analytic model and connected it to the Contact model &#8211; Contact is the model that stores the basic information about facilities listed on RidingResource.  We use <a title="Rails Single Table Inheritance" href="http://www.juixe.com/techknow/index.php/2006/06/03/rails-single-table-inheritance/" target="_blank">Single Table Inheritance</a> (STI) for the different types of facilities listed, but that&#8217;s for another posting.</p>
<p>We realized that there were not a lot of fields necessary for the analytics table. Since the analytics were connected to a contact, we needed to store the contact ID. Since we identified three different types of analytics, we store an integer for the type field, which we may make into an actual model later.</p>
<p>Lastly, we decided it would be valuable to store the parameters that were used at the time to cause this listing to be displayed. It&#8217;s entirely possible that there may some more valuable data that we could search on later, so knowing the params of the &#8220;hit&#8221; could be valuable.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Analytic <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:contact</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> CreateAnalytics <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">up</span>
    create_table <span style="color:#ff3333; font-weight:bold;">:analytics</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span>
      t.<span style="color:#CC0066; font-weight:bold;">integer</span> <span style="color:#ff3333; font-weight:bold;">:contact_id</span>
      t.<span style="color:#CC0066; font-weight:bold;">string</span> <span style="color:#ff3333; font-weight:bold;">:parameters</span>
      t.<span style="color:#CC0066; font-weight:bold;">integer</span> <span style="color:#ff3333; font-weight:bold;">:analytic_type</span>
      t.<span style="color:#9900CC;">timestamps</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">down</span>
    drop_table <span style="color:#ff3333; font-weight:bold;">:analytics</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p><a title="Ruby on Rails" href="http://www.rubyonrails.org" target="_blank">Ruby on Rails</a> is kind enough to automatically store the params for us as serialized <a title="YAML: human-readable data serialization" href="http://en.wikipedia.org/wiki/YAML" target="_blank">YAML</a>. This way, when we want to actually process and dissect them later, we can simply do the following to get the params hash back the way we need it:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#0066ff; font-weight:bold;">@the_analytics</span> = Analaytic.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:some_conditions</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#0066ff; font-weight:bold;">@the_params</span> = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span>@the_analytics<span style="color:#006600; font-weight:bold;">&#91;</span>some_specific_one<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">parameters</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>One thing that needed to be carefully considered was storing &#8220;hits&#8221; on the search results pages. Because the database is currently a little bit nasty, we&#8217;re ending up finding all entries in the DB that match a subset of criteria, and then filtering out the rest that don&#8217;t match the remaining criteria. This is actually faster than all the weird joins that end up occuring. After that, there is still the matter of pagination. It&#8217;s entirely possible that a facility could be pulled from the DB several times without actually being displayed, so we couldn&#8217;t just assume that pulling from the DB in the results page was a hit.</p>
<p>What I realized was that <a title="Mislav's will_paginate" href="http://wiki.github.com/mislav/will_paginate" target="_blank">Mislav&#8217;s will_paginate</a> does something nice for us &#8211; it ends up lopping off all the records outside the pagination range, and leaves us with the few for the current page. This enabled us to simply iterate over the paginated records and store the hits.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#0066ff; font-weight:bold;">@contacts</span> = filter_results<span style="color:#006600; font-weight:bold;">&#40;</span>@contact<span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#0066ff; font-weight:bold;">@contacts</span> = <span style="color:#0066ff; font-weight:bold;">@contacts</span>.<span style="color:#9900CC;">paginate</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:page</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:page</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#ff3333; font-weight:bold;">:per_page</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">8</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#0066ff; font-weight:bold;">@contacts</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>contact<span style="color:#006600; font-weight:bold;">|</span>
  contact.<span style="color:#9900CC;">analytics</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> Analytic.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>:contact_id <span style="color:#006600; font-weight:bold;">=&gt;</span> contact.<span style="color:#9900CC;">id</span>, <span style="color:#ff3333; font-weight:bold;">:parameters</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> params, <span style="color:#ff3333; font-weight:bold;">:analytic_type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Storing the hits for the detail page and for the API was trivial. There&#8217;s only one record to grab on the detail page, so obviously someone is looking at it &#8211; hit. Since we don&#8217;t know what the people at the other end of the API are actually doing with the data, all we can do is record that a record was provided to the API.</p>
<p>So now that we&#8217;re storing the analytics, how the heck do we display them? That&#8217;s where <a title="Open Flash Chart" href="http://teethgrinder.co.uk/open-flash-chart-2/" target="_blank">Open Flash Chart</a> comes into play. Unfortunately, this turned out to initially be a nightmare for many reasons.</p>
<p>When we first started building <a title="Riding Resource - A Stable Place to Search" href="http://www.RidingResource.com" target="_blank">RidingResource</a>, I was certainly a rails noob. Not that I am by any means not a noob at this point, but at least I am a little more polished since those early days of not knowing how to do anything. Because I was busy fighting everything at that point, I decided to save myself some headache for the administration area and use <a title="ActiveScaffold - A Rails plugin for dynamic, AJAX CRUD interfaces" href="http://www.activescaffold.com/" target="_blank">Active Scaffold</a>.</p>
<p><a title="ActiveScaffold - A Rails plugin for dynamic, AJAX CRUD interfaces" href="http://www.activescaffold.com/" target="_blank">Active Scaffold</a> certainly is a nice plugin. It does have a tendency to throw wrenches into the works on occasion because it does some strange things using the <a title="Prototype Javascript Framework" href="http://www.prototypejs.org/" target="_blank">Prototype</a> javascript libraries. My first crack at graphing data was to take a look at <a title="flot - Attractive Javascript plotting for jQuery" href="http://code.google.com/p/flot/" target="_blank">Flot</a> because it seemed simple and could do the basic things we wanted. The <a title="flot - Attractive Javascript plotting for jQuery" href="http://code.google.com/p/flot/" target="_blank">Flot</a> plugin I found (<a title="Joshua Miller's Flotilla" href="http://github.com/joshuamiller/flotilla/tree/master" target="_blank">Flotilla</a>) wanted to use <a title="jQuery Javascript Library" href="http://jquery.com/" target="_blank">jQuery</a> via <a title="jRails is a jQuery replacement for Prototype/script.aculo.us" href="http://ennerchi.com/projects/jrails" target="_blank">JRails</a> (don&#8217;t think <a title="JRuby is a 100% pure-Java implementation of Ruby" href="http://jruby.codehaus.org/" target="_blank">JRuby</a>) which interfered with the <a title="Prototype Javascript Framework" href="http://www.prototypejs.org/" target="_blank">Prototype</a> implementation of <a title="ActiveScaffold - A Rails plugin for dynamic, AJAX CRUD interfaces" href="http://www.activescaffold.com/" target="_blank">Active Scaffold</a>. Since the initial graphing was for our admin area, this was out.</p>
<p>After some pondering and question asking in the #rubyonrails channel on <a title="freenode IRC network" href="http://freenode.net/" target="_blank">Freenode</a> (you can find me there as <em>thoraxe</em>), a few other suggestions came up. <a title="Scruffy is a Ruby library for generating attractive and powerful graphs, useful for web applications, print media and many others." href="http://scruffy.rubyforge.org/" target="_blank">Scruffy</a> and <a title="The Gruff Graphing Library is a project to make beautiful graphs with Ruby. " href="http://nubyonrails.com/pages/gruff" target="_blank">Gruff</a> were suggested, but these both used <a title="SVG specifications for two-dimensional vector graphics" href="http://en.wikipedia.org/wiki/Scalable_Vector_Graphics" target="_blank">Scalable Vector Graphics</a>. While Firefox supports these today, I was informed that IE does not without a plugin. Our customer base is mostly going to be IE people, and probably not the most tech-savvy. In case these analytics became customer-facing, I did not want to have to worry about teaching non-tech-savvy people how to install browser plugins for IE. Scruffy and Gruff = out.</p>
<p>Next came the flash implementations, of which there were two notable ones. The first I will mention is <a title="Ziya - charting the rails" href="http://ziya.liquidrail.com/" target="_blank">Ziya</a>, although we did not ultimately choose it. <a title="Ziya - charting the rails" href="http://ziya.liquidrail.com/" target="_blank">Ziya</a> charts certainly are sexy, but for some reason I decided implementation looked difficult and that the charts were a little bit of overkill for what we needed.</p>
<p>Enter <a title="Open Flash Chart" href="http://teethgrinder.co.uk/open-flash-chart-2/" target="_blank">Open Flash Chart</a>, our savior. Well, in the end the savior. It was a hell of a headache getting it to work.</p>
<p>There are several implementations of <a title="Open Flash Chart" href="http://teethgrinder.co.uk/open-flash-chart-2/" target="_blank">Open Flash Chart</a> in <a title="Ruby on Rails" href="http://www.rubyonrails.org" target="_blank">Ruby on Rails</a>. I have to say that, to a certain extent, all of them are a little sucky. Don&#8217;t get me wrong &#8211; it&#8217;s unfair for me to complain about free code that could make me money! But there is something to say about the cleanliness and simplicity of <a title="Rick Olson is techno weenie" href="http://techno-weenie.net/" target="_blank">Technoweenie&#8217;s</a> code when compared to some of these plugins.</p>
<p><a title="Open Flash Chart" href="http://teethgrinder.co.uk/open-flash-chart-2/" target="_blank">Open Flash Chart</a> is smart. It is a flash file that you basically feed <a title="JavaScript Object Notation" href="http://en.wikipedia.org/wiki/JSON" target="_blank">JSON</a> data to generate charts. That makes it simple. Unless you are using the <a title="JSON implementation for Ruby" href="http://json.rubyforge.org/" target="_blank">JSON gem</a> already. Which we are because it is used by <a title="Ruby wrapper for the Twitter Search API" href="http://github.com/dancroak/twitter-search/tree/master" target="_blank">dancroak&#8217;s twitter_search</a> plugin. Which makes things <em>insane</em>. Remember how <a title="ActiveScaffold - A Rails plugin for dynamic, AJAX CRUD interfaces" href="http://www.activescaffold.com/" target="_blank">Active Scaffold</a> was interfering with <a title="flot - Attractive Javascript plotting for jQuery" href="http://code.google.com/p/flot/" target="_blank">Flot</a>? Well, here we were again. Something I was already using interfering with something I wanted to do.</p>
<p>To make a long story short, after much headache surrounding various <a title="Open Flash Chart" href="http://teethgrinder.co.uk/open-flash-chart-2/" target="_blank">Open Flash Chart</a> plugins that used Rails&#8217; built-in JSONification, one of the plugins that is mentioned on the OFC webpage happened to use the <a title="JSON implementation for Ruby" href="http://json.rubyforge.org/" target="_blank">JSON gem</a> itself. Perfect!</p>
<p><a title="Open Flash Chart 2 rails plugin" href="http://github.com/korin/open_flash_chart_2_plugin/tree/master" target="_blank">Korin&#8217;s Open Flash Chart 2</a> plugin did the trick. I won&#8217;t go into the implementation of everything in its entirety, but I will share the following bits which you may or may not find useful.</p>
<p>Korin&#8217;s examples use two controller actions to generate the graph. The first action creates the @graph object which basically just stores the string which represents some code that the swfobject javascript library uses to create the proper html to display the openflashchart.swf.  The second action actually generates the JSON that gets fed into the SWF.</p>
<p>One of the other plugins I had found that did not work for me (because of the previously discussed <a title="JSON implementation for Ruby" href="http://json.rubyforge.org/" target="_blank">JSON gem</a> issues) was <a title="Pullmonkey's Open Flash Chart plugin" href="http://github.com/pullmonkey/open_flash_chart/tree/master" target="_blank">Pullmonkey&#8217;s Open Flash Chart</a> plugin. Pullmonkey did something neat using the <a title="Module: ActionController::MimeResponds::InstanceMethods" href="http://api.rubyonrails.org/classes/ActionController/MimeResponds/InstanceMethods.html" target="_blank">respond_to</a> method of MimeResponds in ActionController.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> show
  <span style="color:#008000; font-style:italic;"># find the contact requested</span>
  <span style="color:#0066ff; font-weight:bold;">@contact</span> = Contact.<span style="color:#9900CC;">find_by_url</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  respond_to <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>wants<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#0066ff; font-weight:bold;">@all_results</span> = Analytic.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:contact_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@contact</span>.<span style="color:#9900CC;">id</span> <span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#0066ff; font-weight:bold;">@data_results</span> = Analytic.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:analytic_type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">1</span>, <span style="color:#ff3333; font-weight:bold;">:contact_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@contact</span>.<span style="color:#9900CC;">id</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#0066ff; font-weight:bold;">@data_details</span> = Analytic.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:analytic_type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">2</span>, <span style="color:#ff3333; font-weight:bold;">:contact_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@contact</span>.<span style="color:#9900CC;">id</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#0066ff; font-weight:bold;">@data_api</span> = Analytic.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:analytic_type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">3</span>, <span style="color:#ff3333; font-weight:bold;">:contact_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@contact</span>.<span style="color:#9900CC;">id</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    wants.<span style="color:#9900CC;">html</span> <span style="color:#9966CC; font-weight:bold;">do</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># set up the graph on the request</span>
      <span style="color:#0066ff; font-weight:bold;">@graph_results</span> = ofc2<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">650</span>,<span style="color:#006666;">300</span>,url_for<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:show</span>, <span style="color:#ff3333; font-weight:bold;">:format</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:json</span>, <span style="color:#ff3333; font-weight:bold;">:graphtype</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:results</span><span style="color:#006600; font-weight:bold;">&#41;</span>,<span style="color:#996600;">&quot;&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@graph_details</span> = ofc2<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">650</span>,<span style="color:#006666;">300</span>,url_for<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:show</span>, <span style="color:#ff3333; font-weight:bold;">:format</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:json</span>, <span style="color:#ff3333; font-weight:bold;">:graphtype</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:details</span><span style="color:#006600; font-weight:bold;">&#41;</span>,<span style="color:#996600;">&quot;&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@graph_api</span> = ofc2<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">650</span>,<span style="color:#006666;">300</span>,url_for<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:show</span>, <span style="color:#ff3333; font-weight:bold;">:format</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:json</span>, <span style="color:#ff3333; font-weight:bold;">:graphtype</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:api</span><span style="color:#006600; font-weight:bold;">&#41;</span>,<span style="color:#996600;">&quot;&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    wants.<span style="color:#9900CC;">json</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      <span style="color:#008000; font-style:italic;"># provide the JSON back to the flash</span>
      <span style="color:#008000; font-style:italic;"># call the function to generate the graph based on the graph type that is supplied via params</span>
      render <span style="color:#ff3333; font-weight:bold;">:text</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> results_graph.<span style="color:#9900CC;">render</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This implementation is a little more elegant, but I&#8217;m actually finding that, because both the HTML and <a title="JavaScript Object Notation" href="http://en.wikipedia.org/wiki/JSON" target="_blank">JSON</a> generation are happening inside the same controller action, some of my finds are being performed multiple times. This is because the records for these finds are needed by both parts of the action, but the action gets called each time any part of the respond_to gets called. I may end up de-elegantizing this and splitting it back into multiple actions if it becomes a performance issue.</p>
<p>In determining what to do with the analytics data, we decided that initially it made sense to simply graph hits by day. Since we cheated in our creation of the analytics table and used the built in timestamps, we already had a created_at field which contained the <a title="DateTime Ruby class" href="http://www.ruby-doc.org/core-1.9/classes/DateTime.html" target="_blank">DateTime</a> of the hit. If you look at that last sentence carefully, you realize that <a title="DateTime Ruby class" href="http://www.ruby-doc.org/core-1.9/classes/DateTime.html" target="_blank">DateTime</a> is not <a title="Date Ruby class" href="http://www.ruby-doc.org/core/classes/Date.html" target="_blank">Date</a>. So how do you lop off the time part? This also still leaves the trouble of calculating how many hits occured on each day, too. This is where the elegance of <a title="Ruby programming language" href="http://www.ruby-lang.org/en/" target="_blank">Ruby</a> really shines.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">line_values = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
x_labels_text = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
instance_variable_get<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;@data_#{params[:graphtype]}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">group_by</span><span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>a<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#CC00FF; font-weight:bold;">Date</span>.<span style="color:#9900CC;">ordinal</span><span style="color:#006600; font-weight:bold;">&#40;</span>a.<span style="color:#9900CC;">created_at</span>.<span style="color:#9900CC;">year</span>, a.<span style="color:#9900CC;">created_at</span>.<span style="color:#9900CC;">yday</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>day, results<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#008000; font-style:italic;"># this will group all of the analytic hits together by day instead of date/time. it then iterates over</span>
  <span style="color:#008000; font-style:italic;"># these results in a block, where day holds the value of the day of the results, and results is an array</span>
  <span style="color:#008000; font-style:italic;"># containing the individual results from that day.</span>
&nbsp;
  x_labels_text <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> day.<span style="color:#9900CC;">to_s</span> <span style="color:#008000; font-style:italic;"># put the value of the day into the x axis label</span>
  line_values  <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> results.<span style="color:#9900CC;">length</span> <span style="color:#008000; font-style:italic;"># how many hits occured on this day</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>group_by, ordinal, and iterating over blocks totally saved our butts here. What the above code enabled us to do was to group the entire array of analytics data by the day (after munching the time off using ordinal), and then iterate over the resulting groups. The blocks allow us to both store the day into the array of labels for the x-axis, as well as determine how many hits occured on that day by using the length of the array of data in the group. Brilliant!</p>
<p>As you can see, what started out as a relatively simple idea (&#8220;Let&#8217;s graph some analytics about the facilities on <a title="Riding Resource - A Stable Place to Search" href="http://www.RidingResource.com" target="_blank">RidingResource</a>!&#8221;) ended up being a relatively non-trivial coding exercise that took us almost a solid day of man-hours. But, in the end, we were left with something simple that did the job, but which leaves us a lot of room for growth and power.</p>
<p>The only real pain point right now has to do with the actual analytics data. If a day goes by without any hits, nothing gets stored in the database. Since we are grouping by the records that we actually pull out of the database, any dates in the middle with no hits will not be represented. So we are left with the problem of how to determine what dates are &#8220;in the middle&#8221; that have no hits. It&#8217;s not an issue right now, but it may become one in the future. I&#8217;m sure we&#8217;ll be able to figure it out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.erikjacobs.com/2009/03/28/internal-analytics-with-open-flash-chart/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CAPTCHA in Rails &#8211; an experiment in anti-spam</title>
		<link>http://www.erikjacobs.com/2009/03/23/captcha-in-rails-an-experiment-in-anti-spam/</link>
		<comments>http://www.erikjacobs.com/2009/03/23/captcha-in-rails-an-experiment-in-anti-spam/#comments</comments>
		<pubDate>Tue, 24 Mar 2009 01:45:12 +0000</pubDate>
		<dc:creator>Erik Jacobs</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.erikjacobs.com/?p=88</guid>
		<description><![CDATA[One of the things that we decided would be a good idea for RidingResource was to let users of the site contact the various facilities that we have listed. We quickly ran into an issue with spam.]]></description>
			<content:encoded><![CDATA[<p>One of the things that we decided would be a good idea for <a title="Riding Resource - A Stable Place to Search" href="http://www.RidingResource.com" target="_blank">RidingResource</a> was to let users of the site contact the various facilities that we have listed. We also wanted to make sure those facilities knew we helped facilitate that contact by injecting some extra information into the email. The email functionality is left for another post.</p>
<p>We quickly ran into an issue with spam. As administrators of the site, we get copies of all of the email that is sent to facilities. We noticed that some weird spam-like email came through. Fortunately it was someone trying to exploit our site as an open mailer, but it didn&#8217;t seem to work, and no email got to our customer. We will have to investigate how to help prevent that (if it&#8217;s even possible to exploit) later. But we knew that we needed to do something to prevent spammers from being able to send automated junk mail to our customers, and <a title="CAPTCHA challenge-response" href="http://en.wikipedia.org/wiki/Captcha" target="_blank">CAPTCHA</a> seemed like a good idea.</p>
<p>Until I tried it.</p>
<p>After some quick <a title="Google" href="http://www.google.com" target="_blank">Googling</a> for &#8220;rails captcha&#8221; and other terms, I discovered the <a title="Rails simple_captcha plugin" href="http://expressica.com/simple_captcha/" target="_blank">simple_captcha</a> plugin. This is a handy plugin that can be used to generate a CAPTCHA image with some convenient options. It also offers a friendly validation of said CAPTCHA in your controllers, amongst other things.</p>
<p>One &#8220;issue&#8221; that I had with simple_captcha is that it requires both the <a title="ImageMagick: Convert, Edit and Compose Images" href="http://www.imagemagick.org/script/index.php" target="_blank">Imagemagick</a> image manipulation program to be installed as well as the <a title="Graphics Processing for Ruby and Ruby on Rails" href="http://rmagick.rubyforge.org/" target="_blank">RMagick</a> gem. The first part was already present, as I was using the <a title="Mini Magick" href="http://rubyforge.org/projects/mini-magick/" target="_blank">mini_magick</a> gem for another <a title="Ruby on Rails" href="http://www.rubyonrails.org" target="_blank">Rails</a> application. Unfortunately, I didn&#8217;t have RMagick, and installing it proved less than trivial.</p>
<p>First, trying to install the RMagick gem resulted in an error:</p>
<p>Can&#8217;t install RMagick 2.9.1. Can&#8217;t find Magick-config in /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin</p>
<p>This got me to poking around. Now, most of the tutorials I had found referenced Debian as the Linux distribution onto which people were using simple_captcha. I happen to be running <a title="Fedora, a Linux-based Operating System" href="http://fedoraproject.org/" target="_blank">Fedora</a> as a development server and <a title="CentOS - The Community ENterprise Operating System" href="http://www.centos.org/" target="_blank">CentOS</a> in production. This meant things were a little different. After some creative Googling, I discovered what was required to install <a title="How to install RMagick on CentOS" href="http://www.cherpec.com/2008/08/howto-install-rmagick-on-centos-4/" target="_blank">RMagick on CentOS</a>. The current version of RMagick is actually 1.15.17 &#8211; slightly newer than the one referenced in the tutorial.</p>
<p>In the end, the tutorials on the <a title="Rails simple_captcha plugin" href="http://expressica.com/simple_captcha/" target="_blank">simple_captcha</a> website were sufficient to get what we needed going. Since we already had a contact form, it really was less than 15 new lines of code to get things up and running. I&#8217;m not as pleased as I could be with the CSS and formatting of where the CAPTCHA is on the contact form, but it looks good enough for now.</p>
<p>If you&#8217;ve got some contact forms and you&#8217;re concerned about spam, or you&#8217;ve got some registration forms that you want to anti-robot, give simple_captcha a try.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.erikjacobs.com/2009/03/23/captcha-in-rails-an-experiment-in-anti-spam/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
