<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Matt Huggins</title>
	
	<link>http://www.matthuggins.com</link>
	<description>Web &amp; mobile applications developer</description>
	<lastBuildDate>Sun, 27 May 2012 14:04:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/matthuggins" /><feedburner:info uri="matthuggins" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>matthuggins</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Allowing Unit Tests to Work as Intended</title>
		<link>http://feedproxy.google.com/~r/matthuggins/~3/K1PVVtu4XXk/allowing-unit-tests-to-work-as-intended</link>
		<comments>http://www.matthuggins.com/articles/allowing-unit-tests-to-work-as-intended#comments</comments>
		<pubDate>Sun, 15 Apr 2012 16:55:23 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.matthuggins.com/?p=252</guid>
		<description><![CDATA[Several months ago, I had the opportunity to improve part of a testing suite for an application I worked on. Specifically, I was improving some unit testing pertaining to the creation of DelayedJob entries when emailing users. The code being tested related to users being emailed upon registration on the site. def User &#60; ActiveRecord::Base [...]]]></description>
			<content:encoded><![CDATA[<p>Several months ago, I had the opportunity to improve part of a testing suite for an application I worked on.  Specifically, I was improving some unit testing pertaining to the creation of DelayedJob entries when emailing users.</p>
<p>The code being tested related to users being emailed upon registration on the site.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span>
  <span style="color:#5A0A0A; font-weight:bold;">after_create</span> <span style="color:#ff3333; font-weight:bold;">:send_welcome_email</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> send_welcome_email
    UserMailer.<span style="color:#9900CC;">welcome</span><span style="color:#006600; font-weight:bold;">&#40;</span>email<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#5A0A0A; font-weight:bold;">deliver</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  handle_asynchronously <span style="color:#ff3333; font-weight:bold;">:send_welcome_email</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The test&#8217;s original implementation compared the number of delayed jobs being created to the number of expected delayed job entries.  The unit test code essentially looked like this.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> UserTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span></span>
  context <span style="color:#996600;">&quot;when creating a new user&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    setup <span style="color:#9966CC; font-weight:bold;">do</span>
      <span style="color:#0066ff; font-weight:bold;">@user</span> = Factory.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:user</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    should <span style="color:#996600;">&quot;send new user a welcome email&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      <span style="color:#5A0A0A; font-weight:bold;">assert_equal</span> <span style="color:#006666;">1</span>, <span style="color:#6666ff; font-weight:bold;">Delayed::Job</span>.<span style="color:#5A0A0A; font-weight:bold;">count</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>Since the email is sent via a delayed job, its implementation for success is to compare the number of delayed jobs to the number of expected delayed jobs (in this case, just one).  Everything works, and the test passes successfully.  That&#8217;s great for this particular instance.</p>
<p>But what happens if we change the User model&#8217;s code to the following?</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span>
  <span style="color:#5A0A0A; font-weight:bold;">after_create</span> <span style="color:#ff3333; font-weight:bold;">:send_notification_to_referring_user</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> send_notification_to_referring_user
    UserMailer.<span style="color:#9900CC;">referral</span><span style="color:#006600; font-weight:bold;">&#40;</span>referrer.<span style="color:#9900CC;">email</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#5A0A0A; font-weight:bold;">deliver</span> <span style="color:#9966CC; font-weight:bold;">if</span> referrer
  <span style="color:#9966CC; font-weight:bold;">end</span>
  handle_asynchronously <span style="color:#ff3333; font-weight:bold;">:send_notification_to_referring_user</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>When we run our unit test again, it still passes.  However, the unit test is supposed to be ensuring the user receives a welcome email, given the line of code reading <code>should "send new user a welcome email"</code>.  Clearly given the updated model code, that is no longer happening.</p>
<p>An improvement for our test would be to check that the correct method is being called via Delayed Job.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">assert_delayed_method <span style="color:#ff3333; font-weight:bold;">:send_notifications</span></pre></div></div>

<p>There is no <code>assert_delayed_method</code> supplied by default, but that doesn&#8217;t mean we can&#8217;t create one.  Within <code>test/test_helper.rb</code>, let&#8217;s go ahead and add the following code.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> assert_delayed_method<span style="color:#006600; font-weight:bold;">&#40;</span>method_name, msg = <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  method_name = method_name.<span style="color:#9900CC;">to_sym</span>
  full_message = build_message<span style="color:#006600; font-weight:bold;">&#40;</span>msg, <span style="color:#996600;">&quot;Delayed Job should exist for ?.&quot;</span>, method_name<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  assert_block<span style="color:#006600; font-weight:bold;">&#40;</span>full_message<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    match = <span style="color:#0000FF; font-weight:bold;">false</span>
    <span style="color:#6666ff; font-weight:bold;">Delayed::Job</span>.<span style="color:#9900CC;">find_each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>job<span style="color:#006600; font-weight:bold;">|</span>
      match = <span style="color:#0000FF; font-weight:bold;">true</span> <span style="color:#9966CC; font-weight:bold;">and</span> <span style="color:#9966CC; font-weight:bold;">break</span> <span style="color:#9966CC; font-weight:bold;">if</span> job.<span style="color:#9900CC;">payload_object</span>.<span style="color:#9900CC;">method</span> == method_name
    <span style="color:#9966CC; font-weight:bold;">end</span>
    match
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now, let&#8217;s change our unit test to take advantage of this new assertion method.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> UserTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span></span>
  context <span style="color:#996600;">&quot;when creating a new user&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    setup <span style="color:#9966CC; font-weight:bold;">do</span>
      <span style="color:#0066ff; font-weight:bold;">@user</span> = Factory.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:user</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    should <span style="color:#996600;">&quot;send new user a welcome email&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      assert_delayed_method <span style="color:#ff3333; font-weight:bold;">:send_notification_to_referring_user</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>The unit test still passes, and we can rest assured that if a different delayed job is created in the future, our test will fail.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/matthuggins?a=K1PVVtu4XXk:bNoY1m8uGBE:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=K1PVVtu4XXk:bNoY1m8uGBE:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=K1PVVtu4XXk:bNoY1m8uGBE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/matthuggins?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=K1PVVtu4XXk:bNoY1m8uGBE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=K1PVVtu4XXk:bNoY1m8uGBE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=K1PVVtu4XXk:bNoY1m8uGBE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=K1PVVtu4XXk:bNoY1m8uGBE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=K1PVVtu4XXk:bNoY1m8uGBE:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=K1PVVtu4XXk:bNoY1m8uGBE:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/matthuggins/~4/K1PVVtu4XXk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matthuggins.com/articles/allowing-unit-tests-to-work-as-intended/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.matthuggins.com/articles/allowing-unit-tests-to-work-as-intended?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=allowing-unit-tests-to-work-as-intended</feedburner:origLink></item>
		<item>
		<title>Creating a Custom Formtastic File Upload Input with Image Thumbnail</title>
		<link>http://feedproxy.google.com/~r/matthuggins/~3/6r2JTFgSmJM/creating-a-custom-formtastic-file-upload-input-with-image-thumbnail</link>
		<comments>http://www.matthuggins.com/articles/creating-a-custom-formtastic-file-upload-input-with-image-thumbnail#comments</comments>
		<pubDate>Mon, 26 Mar 2012 16:50:31 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.matthuggins.com/?p=266</guid>
		<description><![CDATA[Just today, I ran into a situation where I wanted to modify the output generated by Formtastic while building an input element. In this particular scenario, the input field was a file input in which the user is expected to upload an image (PNG, JPG, or GIF). The customization I wanted was the ability to [...]]]></description>
			<content:encoded><![CDATA[<p>Just today, I ran into a situation where I wanted to modify the output generated by Formtastic while building an input element. In this particular scenario, the input field was a file input in which the user is expected to upload an image (PNG, JPG, or GIF). The customization I wanted was the ability to display the thumbnail of the current image if one has already been uploaded. A screenshot of the goal can be seen below.</p>
<p><a href="http://www.matthuggins.com/wp-content/uploads/2012/03/formtastic-image-upload.png"><img class="aligncenter size-medium wp-image-267" title="Formtastic Image File Upload" src="http://www.matthuggins.com/wp-content/uploads/2012/03/formtastic-image-upload-300x59.png" alt="" width="300" height="59" /></a></p>
<p>My first approach was not at all elegant, although it achieved the goal.  Depending on whether this is a new or existing record, I conditionally display the input differently.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">form</span>.<span style="color:#9900CC;">inputs</span> <span style="color:#9966CC; font-weight:bold;">do</span> <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;">if</span> <span style="color:#5A0A0A; font-weight:bold;">form</span>.<span style="color:#9900CC;">object</span>.<span style="color:#9900CC;">new_record</span>? <span style="color:#006600; font-weight:bold;">-%&gt;</span>
        <span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">form</span>.<span style="color:#5A0A0A; font-weight:bold;">input</span> <span style="color:#ff3333; font-weight:bold;">:image</span>, <span style="color:#ff3333; font-weight:bold;">:required</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>, <span style="color:#ff3333; font-weight:bold;">:hint</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Maximum size of 3MB. JPG, GIF, PNG.'</span> <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;">else</span> <span style="color:#006600; font-weight:bold;">-%&gt;</span>
        &lt;li class=&quot;file input required&quot; id=&quot;profile_image_input&quot;&gt;
            &lt;label class=&quot;label&quot; for=&quot;profile_image&quot;&gt;Image&lt;/label&gt;
            <span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">image_tag</span> <span style="color:#5A0A0A; font-weight:bold;">form</span>.<span style="color:#9900CC;">object</span>.<span style="color:#9900CC;">image</span>.<span style="color:#9900CC;">url</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:thumb</span><span style="color:#006600; font-weight:bold;">&#41;</span>, :<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'attachment'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
            <span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">form</span>.<span style="color:#5A0A0A; font-weight:bold;">file_field</span> <span style="color:#ff3333; font-weight:bold;">:image</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
            &lt;p class=&quot;inline-hints&quot;&gt;Maximum size of 3MB. JPG, GIF, PNG.&lt;/p&gt;
        &lt;/li&gt;
    <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>
<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>There are a few problems with this.  For one, I have repeated code between the two conditions.  For example, the &#8220;hint&#8221; string is repeated, as well as the required setting.  If I ever change the value in one spot, I have to remember to change it in the other.  The other bigger problem is that my code is based upon the internal rendering performed by Formtastic.  That means that if I ever update Formtastic, I need to make sure my custom HTML is updated to match as well.</p>
<p>Being somewhat of a perfectionist (well, at least as close as I can get) when it comes to my code, I wanted to address these issues right away rather than putting it on a &#8220;to do&#8221; list that would always take second place to other more important tasks.</p>
<p>After doing a bit of digging, I was reminded about Formtastic&#8217;s ability to utilize custom inputs.  This can be seen on the &#8220;Creating New Inputs Based on Existing Ones&#8221; section of <a href="https://github.com/justinfrench/formtastic#readme">Formtastic&#8217;s README</a>.  In only 5-10 minutes of coding, I was able to completely refactor my original approach.  First, I created my custom input class.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> AttachmentInput <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Formtastic::Inputs::FileInput</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> image_html_options
    <span style="color:#006600; font-weight:bold;">&#123;</span>:<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'attachment'</span><span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">merge</span><span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:image_html</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;">&#123;</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>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> to_html
    input_wrapping <span style="color:#9966CC; font-weight:bold;">do</span>
      label_html <span style="color:#006600; font-weight:bold;">&lt;&lt;</span>
      image_html <span style="color:#006600; font-weight:bold;">&lt;&lt;</span>
      builder.<span style="color:#5A0A0A; font-weight:bold;">file_field</span><span style="color:#006600; font-weight:bold;">&#40;</span>method, input_html_options<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
protected
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> image_html
    <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#996600;">&quot;&quot;</span>.<span style="color:#9900CC;">html_safe</span> <span style="color:#9966CC; font-weight:bold;">if</span> builder.<span style="color:#9900CC;">object</span>.<span style="color:#9900CC;">new_record</span>?
&nbsp;
    url = <span style="color:#9966CC; font-weight:bold;">case</span> options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:image</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#9966CC; font-weight:bold;">when</span> <span style="color:#CC00FF; font-weight:bold;">Symbol</span>
      builder.<span style="color:#9900CC;">object</span>.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:image</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">when</span> <span style="color:#CC00FF; font-weight:bold;">Proc</span>
      options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:image</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#5A0A0A; font-weight:bold;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span>builder.<span style="color:#9900CC;">object</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:image</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#5A0A0A; font-weight:bold;">to_s</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    builder.<span style="color:#9900CC;">template</span>.<span style="color:#5A0A0A; font-weight:bold;">image_tag</span><span style="color:#006600; font-weight:bold;">&#40;</span>url, image_html_options<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">html_safe</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now, with my input class created, I could simply specify the type of input as <code>:attachment</code> instead of using the default of <code>:file</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">form</span>.<span style="color:#5A0A0A; font-weight:bold;">input</span> <span style="color:#ff3333; font-weight:bold;">:image</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:attachment</span>,
                       <span style="color:#ff3333; font-weight:bold;">:required</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>,
                       <span style="color:#ff3333; font-weight:bold;">:hint</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Maximum size of 3MB. JPG, GIF, PNG.'</span>,
                       <span style="color:#ff3333; font-weight:bold;">:image</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#CC0066; font-weight:bold;">proc</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>o<span style="color:#006600; font-weight:bold;">|</span> o.<span style="color:#9900CC;">image</span>.<span style="color:#9900CC;">url</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:thumb</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></pre></div></div>

<p>Note the additional <code>:image</code> option.  In order to know what URL to render for the image, this option must be supplied.  In the example above, I utilized a Proc object to generate the URL string.  The Proc receives the object that the form is currently working with.  In this case, it is the instance of my model.</p>
<p>Alternatively, I set up my AttachmentInput class to accept a Symbol representing the name of a method on the object to call, as well as any other object type that is simply cast to a String.  Examples of these implementations can be seen below.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">form</span>.<span style="color:#5A0A0A; font-weight:bold;">input</span> <span style="color:#ff3333; font-weight:bold;">:image</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:attachment</span>, <span style="color:#ff3333; font-weight:bold;">:image</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> :<span style="color:#5A0A0A; font-weight:bold;">to_s</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
<span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">form</span>.<span style="color:#5A0A0A; font-weight:bold;">input</span> <span style="color:#ff3333; font-weight:bold;">:image</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:attachment</span>, <span style="color:#ff3333; font-weight:bold;">:image</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;profile.png&quot;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></pre></div></div>

<p>Formtastic inputs also accepts custom HTML options via <code>:input_html</code>, <code>:wrapper_html</code>, and <code>:button_html</code> Hash options depending on what is currently being generated.  Similarly, a new <code>:image_html</code> Hash option can be provided when building an AttachmentInput.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">form</span>.<span style="color:#5A0A0A; font-weight:bold;">input</span> <span style="color:#ff3333; font-weight:bold;">:image</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:attachment</span>,
                       <span style="color:#ff3333; font-weight:bold;">:image</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> :<span style="color:#5A0A0A; font-weight:bold;">to_s</span>,
                       <span style="color:#ff3333; font-weight:bold;">:image_html</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>:<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'thumbnail'</span>, <span style="color:#ff3333; font-weight:bold;">:alt</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Profile Photo'</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></pre></div></div>

<p>All that&#8217;s left now is to style the rendered HTML.  Nothing fancy here.</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">form img<span style="color: #6666ff;">.attachment</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">float</span><span style="color: #00AA00;">:</span> <span style="color: #000000; font-weight: bold;">left</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #933;">4px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span> <span style="color: #933;">10px</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">border</span><span style="color: #00AA00;">:</span> <span style="color: #933;">1px</span> <span style="color: #993333;">solid</span> <span style="color: #cc00cc;">#ccc</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">background-color</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#fff</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>And there you have it!  With just a few extra minutes of research and coding, I was able to clean up my code significantly.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/matthuggins?a=6r2JTFgSmJM:hRmR6SvQiFA:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=6r2JTFgSmJM:hRmR6SvQiFA:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=6r2JTFgSmJM:hRmR6SvQiFA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/matthuggins?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=6r2JTFgSmJM:hRmR6SvQiFA:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=6r2JTFgSmJM:hRmR6SvQiFA:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=6r2JTFgSmJM:hRmR6SvQiFA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=6r2JTFgSmJM:hRmR6SvQiFA:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=6r2JTFgSmJM:hRmR6SvQiFA:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=6r2JTFgSmJM:hRmR6SvQiFA:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/matthuggins/~4/6r2JTFgSmJM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matthuggins.com/articles/creating-a-custom-formtastic-file-upload-input-with-image-thumbnail/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.matthuggins.com/articles/creating-a-custom-formtastic-file-upload-input-with-image-thumbnail?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=creating-a-custom-formtastic-file-upload-input-with-image-thumbnail</feedburner:origLink></item>
		<item>
		<title>Implement Multiple Table Inheritance Into Your ActiveRecord Models</title>
		<link>http://feedproxy.google.com/~r/matthuggins/~3/Ak-982PzrC4/implement-multiple-table-inheritance-into-your-activerecord-models</link>
		<comments>http://www.matthuggins.com/articles/implement-multiple-table-inheritance-into-your-activerecord-models#comments</comments>
		<pubDate>Mon, 12 Mar 2012 03:05:34 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.matthuggins.com/?p=255</guid>
		<description><![CDATA[This past week, I released my first ever Ruby gem: multiple_table_inheritance. Multiple Table Inheritance is an ActiveRecord plugin designed for Rails 3.0+ designed to make table-level inheritance easier than ever. Imagine you have an application that needs to maintain a list of employees. You&#8217;ll probably start out with a few columns including first name, last [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.matthuggins.com/wp-content/uploads/2012/03/inheritance-150x150.png" alt="" title="Multiple Table Inheritance" width="150" height="150" class="alignright size-thumbnail wp-image-257" />This past week, I released my first ever Ruby gem: <a href="https://github.com/mhuggins/multiple_table_inheritance">multiple_table_inheritance</a>. Multiple Table Inheritance is an ActiveRecord plugin designed for Rails 3.0+ designed to make table-level inheritance easier than ever.</p>
<p>Imagine you have an application that needs to maintain a list of employees.  You&#8217;ll probably start out with a few columns including first name, last name, address, city, state, phone number, social security number, salary, and so on.  However, as you start to work on defining the structure, you might find that certain roles need to track pieces of information that other roles don&#8217;t.  For example, a manager might have a yearly bonus.  Similarly, a programmer might have a list of languages they&#8217;re familiar with.</p>
<p>With the Multiple Table Inheritance gem, you&#8217;ll be able to implement this concept easily.  All that is required is some special treatment with your migrations, and a method call in each ActiveRecord model that extends or inherits from another model.  For example:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Employee <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span>
  acts_as_superclass
  attr_accessible <span style="color:#ff3333; font-weight:bold;">:first_name</span>, <span style="color:#ff3333; font-weight:bold;">:last_name</span>
  validates <span style="color:#ff3333; font-weight:bold;">:first_name</span>, <span style="color:#ff3333; font-weight:bold;">:presence</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>
  validates <span style="color:#ff3333; font-weight:bold;">:last_name</span>, <span style="color:#ff3333; font-weight:bold;">:presence</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>
  validates <span style="color:#ff3333; font-weight:bold;">:salary</span>, <span style="color:#ff3333; font-weight:bold;">:presence</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>, <span style="color:#ff3333; font-weight:bold;">:numericality</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;">:min</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">0</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> Programmer <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span>
  inherits_from <span style="color:#ff3333; font-weight:bold;">:employee</span>
  <span style="color:#5A0A0A; font-weight:bold;">has_many</span> <span style="color:#ff3333; font-weight:bold;">:known_languages</span>
  <span style="color:#5A0A0A; font-weight:bold;">has_many</span> <span style="color:#ff3333; font-weight:bold;">:languages</span>, <span style="color:#ff3333; font-weight:bold;">:through</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:known_languages</span>, <span style="color:#ff3333; font-weight:bold;">:dependent</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> :<span style="color:#5A0A0A; font-weight:bold;">destroy</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> Manager <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span>
  inherits_from <span style="color:#ff3333; font-weight:bold;">:employee</span>
  validates <span style="color:#ff3333; font-weight:bold;">:bonus</span>, <span style="color:#ff3333; font-weight:bold;">:presence</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>, <span style="color:#ff3333; font-weight:bold;">:numericality</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now, whenever you perform any kind of <code>find</code> on your <code>Employee</code> model, you&#8217;ll receive instances of <code>Programmer</code> and <code>Manager</code> as a result.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">Employee.<span style="color:#5A0A0A; font-weight:bold;">first</span>
<span style="color:#008000; font-style:italic;"># yields: &lt;Programmer employee_id: 1&gt;</span>
<span style="color:#008000; font-style:italic;">#     or: &lt;Manager: employee_id: 1 bonus: 5000&gt;</span></pre></div></div>

<p>It even works with named scoped.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">Employee.<span style="color:#9900CC;">where</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'created_at &gt;= ?'</span>, <span style="color:#006666;">3</span>.<span style="color:#9900CC;">weeks</span>.<span style="color:#5A0A0A; font-weight:bold;">ago</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">limit</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#008000; font-style:italic;"># yields: [&lt;Programmer employee_id: 1&gt;,</span>
<span style="color:#008000; font-style:italic;">#          &lt;Programmer employee_id: 2&gt;,</span>
<span style="color:#008000; font-style:italic;">#          &lt;Manager employee_id: 5 bonus: 4500&gt;,</span>
<span style="color:#008000; font-style:italic;">#          &lt;Programmer employee_id: 12&gt;,</span>
<span style="color:#008000; font-style:italic;">#          &lt;Manager employee_id: 14 bonus: 3500&gt;]</span></pre></div></div>

<p>To get started, check out the <a href="https://github.com/mhuggins/multiple_table_inheritance">Multiple Table Inheritance homepage</a> on Github.  Please keep in mind that it&#8217;s a work in progress.  Feel free to submit a new issue or create a pull request if you encounter any problems, fix an issue, or add a new feature.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/matthuggins?a=Ak-982PzrC4:xbBi-GOspVs:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=Ak-982PzrC4:xbBi-GOspVs:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=Ak-982PzrC4:xbBi-GOspVs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/matthuggins?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=Ak-982PzrC4:xbBi-GOspVs:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=Ak-982PzrC4:xbBi-GOspVs:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=Ak-982PzrC4:xbBi-GOspVs:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=Ak-982PzrC4:xbBi-GOspVs:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=Ak-982PzrC4:xbBi-GOspVs:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=Ak-982PzrC4:xbBi-GOspVs:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/matthuggins/~4/Ak-982PzrC4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matthuggins.com/articles/implement-multiple-table-inheritance-into-your-activerecord-models/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.matthuggins.com/articles/implement-multiple-table-inheritance-into-your-activerecord-models?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=implement-multiple-table-inheritance-into-your-activerecord-models</feedburner:origLink></item>
		<item>
		<title>Extending jQuery UI’s Autocomplete to Improve Success</title>
		<link>http://feedproxy.google.com/~r/matthuggins/~3/pwLXTgO_cAo/extending-jquery-uis-autocomplete-to-improve-success</link>
		<comments>http://www.matthuggins.com/articles/extending-jquery-uis-autocomplete-to-improve-success#comments</comments>
		<pubDate>Sun, 04 Dec 2011 18:28:31 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://www.matthuggins.com/?p=238</guid>
		<description><![CDATA[On Black Book Singles, one of the steps in the signup process is to provide the city and country in which you live. The country part is easy to get right since it&#8217;s a simple drop-down list where the user can be sure that the value they&#8217;ve selected is correct. The problem most users are [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.matthuggins.com/wp-content/uploads/2011/12/autosuggest-150x150.jpg" alt="" title="jQuery UI Autocomplete" width="150" height="150" class="alignright size-thumbnail wp-image-249" />On <a href="http://blackbooksingles.com">Black Book Singles</a>, one of the steps in the signup process is to provide the city and country in which you live.  The country part is easy to get right since it&#8217;s a simple drop-down list where the user can be sure that the value they&#8217;ve selected is correct.  The problem most users are encountering is that the city name allows freeform text.  This is necessary due to the large number of possible cities available in each country (with over 11,400 cities per country on average).</p>
<p>My initial solution was to convert the city input into an autocomplete field via <a href="http://jqueryui.com/demos/autocomplete/">jQuery UI&#8217;s autocomplete plugin</a>.  However, I found that a simple autocomplete wasn&#8217;t working as well as I&#8217;d hoped.  After reviewing my first implementation of the autocomplete field, I came to the following conclusion:</p>
<ol>
<li>The autocomplete field is visually styled the same as other text input fields on the page.  There&#8217;s nothing indicating to users that they&#8217;re going to have to do anything other than type into the field and proceed to the next step.</li>
<li>The jQuery UI autocomplete plugin defaults to a 250ms delay prior to fetching the list of possible values.  This can be overridden via the <code>delay</code> option, but setting it to 0 (i.e.: immediately search) is not viable since it will result in extra unnecessary requests to the server while the user is still typing most of the time.</li>
<li>There&#8217;s an additional request/response delay after the built-in 250ms delay.</li>
</ol>
<p>The solution I came up with was to provide hints similar to what the <a href="http://loopj.com/jquery-tokeninput/">jQuery Tokeninput plugin</a> does:</p>
<ol>
<li>Immediately show a hint such as &#8220;Type in a search term&#8221; when the user focuses on the input field.</li>
<li>Immediately update the hint to read &#8220;Searching&#8230;&#8221; when the plugin starts searching for matching values.</li>
</ol>
<p>So if jQuery Tokeninput already has these features, why not just use that?  The problem is that plugin is intended to replace a <a href="http://www.w3.org/TR/html4/interact/forms.html#adef-multiple">multiple select input</a>; for my purpose, I&#8217;m looking for a substitute for a single select input.</p>
<p>Given this, there are several possible solutions to my problem:</p>
<ol>
<li>Find a jQuery (or raw JavaScript) autocomplete plugin that already does something similar.</li>
<li>Create a custom autocomplete plugin from scratch that includes this functionality.</li>
<li>Extend jQuery UI&#8217;s autocomplete plugin to include this missing functionality.</li>
</ol>
<p>After spending a good amount of time searching for an existing plugin that does this, I was surprised to find myself empty-handed.  It seems as though there&#8217;s no good open-source solution that provides this.</p>
<p>Moving onto the second option, I could build my own autocomplete plugin from scratch.  This approach seemed fruitless considering the number of tried and true solutions already available for free.  Similarly, I briefly considered branching from jQuery UI&#8217;s autocomplete plugin, customizing it as a new plugin by editing and adding only what was needed.  I tossed this idea aside as well, as it resulted in too much code duplication, and I would miss out on the benefit of updates to jQuery UI.</p>
<p>Finally, I considered the possibility of extending jQuery UI&#8217;s autocomplete, only touching the parts that need to be changed and adding the missing pieces from there.  This seemed like the best option among the three.  A simple search on extending jQuery plugins led to an <a href="http://stackoverflow.com/a/4414356/107277">answer on StackOverflow</a> that explained the basic premise.  The raw boilerplate code looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><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: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span> $<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;ui&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;autocomplete&quot;</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">prototype</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
        myCustomFunctionA<span style="color: #339933;">:</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;">// TODO</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
        myCustomFunctionB<span style="color: #339933;">:</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;">// TODO</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">// etc...</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: #009900;">&#40;</span>jQuery<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>This is a great start.  From this, I can assume that I&#8217;ll want to create a few methods for showing and hiding a hint text DOM element, as well as binding to some user events to have these methods called.  However, I would need to make all this happen through the existing initialization happening within jQuery UI autocomplete.</p>
<p>To do this, I needed to replace jQuery UI autocomplete&#8217;s <code>_create</code> function with my own, while still allowing the the original version to execute as intended.  I recognized, however, that I would have to do this for multiple functions in the plugin; as such, I wanted a solution that would handle all of these cases.  My solution was to make backup copies of the original function definitions, referencing them from my replacement definitions.  (I&#8217;m open to suggestions for improvement on this approach.)</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><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> plugin <span style="color: #339933;">=</span> $<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;ui&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;autocomplete&quot;</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">prototype</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// store copies of the original plugin functions before overwriting</span>
    <span style="color: #003366; font-weight: bold;">var</span> functions <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #000066; font-weight: bold;">in</span> plugin<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span><span style="color: #009900;">&#40;</span>plugin<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #3366CC;">&quot;function&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            functions<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> plugin<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// extend existing functionality of the autocomplete plugin</span>
    $.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span> plugin<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
        _create<span style="color: #339933;">:</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;">// call the original plugin _create code</span>
            functions<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;_create&quot;</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">call</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: #339933;">;</span>
&nbsp;
            <span style="color: #006600; font-style: italic;">// TODO create the hint DOM element, and bind</span>
            <span style="color: #006600; font-style: italic;">//      to events for showing/hiding the hint</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>jQuery<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>With this, I can take the code to completion by filling in the missing pieces of functionality I originally set out to implement.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><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> plugin <span style="color: #339933;">=</span> $<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;ui&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;autocomplete&quot;</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">prototype</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// store copies of the original plugin functions before overwriting</span>
    <span style="color: #003366; font-weight: bold;">var</span> functions <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #000066; font-weight: bold;">in</span> plugin<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span><span style="color: #009900;">&#40;</span>plugin<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #3366CC;">&quot;function&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            functions<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> plugin<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// extend existing functionality of the autocomplete plugin</span>
    $.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span> plugin<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
        _create<span style="color: #339933;">:</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> self <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #006600; font-style: italic;">// call the original plugin _create code</span>
            functions<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;_create&quot;</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">call</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: #339933;">;</span>
&nbsp;
            <span style="color: #006600; font-style: italic;">// capture the data-hint string on the input element</span>
            <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">hintText</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">element</span>.<span style="color: #660066;">data</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;hint&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #006600; font-style: italic;">// set up the hint object</span>
            <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">hint</span> <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;&lt;div&gt;&lt;/div&gt;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                .<span style="color: #660066;">addClass</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;ui-autocomplete-hint&quot;</span><span style="color: #009900;">&#41;</span>
                .<span style="color: #660066;">appendTo</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span>.<span style="color: #660066;">appendTo</span> <span style="color: #339933;">||</span> <span style="color: #3366CC;">&quot;body&quot;</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">element</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">ownerDocument</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #006600; font-style: italic;">// show/hide hint text on focus/blur</span>
            <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">element</span>
                .<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;focus.autocomplete&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    self._showHint<span style="color: #009900;">&#40;</span>self.<span style="color: #660066;">hintText</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: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;blur.autocomplete&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    self._hideHint<span style="color: #009900;">&#40;</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: #339933;">,</span>
&nbsp;
        destroy<span style="color: #339933;">:</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: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">hint</span>.<span style="color: #660066;">remove</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            functions<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;destroy&quot;</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">call</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: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
        _search<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>value<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">this</span>._hideHint<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            functions<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;_search&quot;</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
        _showHint<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>text<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>text <span style="color: #339933;">!==</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">hint</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>text<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000066; font-weight: bold;">this</span>._resizeHint<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
        _hideHint<span style="color: #339933;">:</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: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">hint</span>.<span style="color: #660066;">hide</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
        _resizeHint<span style="color: #339933;">:</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: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">hint</span>
                .<span style="color: #660066;">outerWidth</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">element</span>.<span style="color: #660066;">outerWidth</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                .<span style="color: #660066;">position</span><span style="color: #009900;">&#40;</span>$.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
                    of<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">element</span>
                <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">options</span>.<span style="color: #660066;">position</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;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>jQuery<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The above example is not the full implementation, as it doesn&#8217;t include some cleanup I&#8217;ve included as well as the &#8220;Searching&#8230;&#8221; hint functionality I mentioned previously.  However, it still demonstrates how to cleanly extend the jQuery UI autocomplete plugin, the basis of which can easily be reused on other jQuery plugins.</p>
<p>To view the full code, visit my <a href="https://github.com/mhuggins/jquery-ui-autocomplete-hints">jQuery UI Autocomplete Hints extension</a> on Github.  Feel free to use the code in your projects, and if you see any opportunities for improvement, send me a pull request to include your changes.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/matthuggins?a=pwLXTgO_cAo:vZD01pqPsUs:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=pwLXTgO_cAo:vZD01pqPsUs:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=pwLXTgO_cAo:vZD01pqPsUs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/matthuggins?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=pwLXTgO_cAo:vZD01pqPsUs:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=pwLXTgO_cAo:vZD01pqPsUs:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=pwLXTgO_cAo:vZD01pqPsUs:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=pwLXTgO_cAo:vZD01pqPsUs:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=pwLXTgO_cAo:vZD01pqPsUs:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=pwLXTgO_cAo:vZD01pqPsUs:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/matthuggins/~4/pwLXTgO_cAo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matthuggins.com/articles/extending-jquery-uis-autocomplete-to-improve-success/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.matthuggins.com/articles/extending-jquery-uis-autocomplete-to-improve-success?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=extending-jquery-uis-autocomplete-to-improve-success</feedburner:origLink></item>
		<item>
		<title>Android Voice Recognition in Appcelerator Titanium</title>
		<link>http://feedproxy.google.com/~r/matthuggins/~3/HgMe_zOgL68/android-voice-recognition-in-appcelerator-titanium</link>
		<comments>http://www.matthuggins.com/articles/android-voice-recognition-in-appcelerator-titanium#comments</comments>
		<pubDate>Sat, 19 Nov 2011 16:32:55 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[titanium]]></category>

		<guid isPermaLink="false">http://www.matthuggins.com/?p=193</guid>
		<description><![CDATA[One of my most recent tasks at Food on the Table was to implement speech recognition for our meal planning app&#8217;s grocery list on Android. Now that the first version of the feature is released, the fully featured product allows users to quickly add items just by speaking into their phone. Not only that, but [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.matthuggins.com/wp-content/uploads/2011/11/android-speech-recognition-150x150.jpg" alt="" title="Android Speech Recognition" width="150" height="150" class="alignright size-thumbnail wp-image-203" />One of my most recent tasks at <a href="http://www.foodonthetable.com/">Food on the Table</a> was to implement speech recognition for our meal planning app&#8217;s grocery list on Android.  Now that the first version of the feature is released, the fully featured product allows users to quickly add items just by speaking into their phone.  Not only that, but the app knows to separate items whenever you say &#8220;and&#8221; in between (e.g. &#8220;bacon and eggs and cheese&#8221; get added as separate items to your list as &#8220;bacon&#8221;, &#8220;eggs&#8221;, and &#8220;cheese&#8221;), determines which department the item should be categorized into, and automatically appends sale data based upon whether or not the item is on sale where you shop.</p>
<p>Most of the backend for this was already implemented from our company working on other tasks.  The newest piece to get this working was the voice recognition itself.  Fortunately, Android 2.1+ comes with speech recognition capabilities via the <code><a href="http://developer.android.com/reference/android/speech/RecognizerIntent.html">RecognizerIntent</a></code>.</p>
<p>The basic logic is as follows:</p>
<ol>
<li>Create an Intent that calls the speech recognizer action,</li>
<li>Pass various parameters, such as the user prompt string and max number of desired results,</li>
<li>Accept the response in the form of an array of strings, where the first array item is most likely to correctly match what the user said.</li>
</ol>
<p>Because we&#8217;re using Appcelerator Titanium for our mobile development, this means all our code is built using JavaScript with wrappers and proxies that act as interfaces to the raw Java Android code.  This also means that some of the work is simplified, such as a callback method being directly passed to an intent that returns a result, as opposed to defining a special method that handles all results as is typically done on Android.</p>
<p>Unfortunately, at times it becomes clear that working with Titanium is going to take a bit of extra work compared to coding natively for Android.</p>
<p>As I mentioned above, when Android&#8217;s speech recognition Intent is successful, it returns an array of text strings that are most likely to match what the user said.  To access this array of strings, there is a method on the Intent class named <code><a href="http://developer.android.com/reference/android/content/Intent.html#getStringArrayListExtra(java.lang.String)">getStringArrayListExtra</a></code>.  The problem is that Titanium&#8217;s IntentProxy does not provide a wrapper for this method.  As such, the temporary solution until it is included in <a href="https://github.com/appcelerator/titanium_mobile">Titanium Mobile core</a> is to create a custom module that acts as a middleman between the JavaScript and Android layers.</p>
<p>Implementing this took some time, as it was my first time working with Titanium modules, but it turned out to be relatively simple.  Since extending Titanium&#8217;s core implementation of IntentProxy into a subclass won&#8217;t work, I had to essentially create a helper class that accepts the IntentProxy and the parameters required for the method, calling the actual method on the Intent given those parameters.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@Kroll.<span style="color: #006633;">method</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> getStringArrayListExtra<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> IntentProxy intentProxy, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> name<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>DBG<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		Log.<span style="color: #006633;">d</span><span style="color: #009900;">&#40;</span>LCAT, <span style="color: #0000ff;">&quot;getStringArrayListExtra called with name:&quot;</span> <span style="color: #339933;">+</span> name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> ArrayList<span style="color: #339933;">&lt;</span>String<span style="color: #339933;">&gt;</span> list <span style="color: #339933;">=</span> intentProxy.<span style="color: #006633;">getIntent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getStringArrayListExtra</span><span style="color: #009900;">&#40;</span>name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">return</span> list <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">?</span> list.<span style="color: #006633;">toArray</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span>list.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Let&#8217;s break down what&#8217;s happening here.  First, the <code>@Kroll.method</code> is a simple annotation used by Titanium to say &#8220;this method should be available when accessed through the JavaScript.&#8221;  If the annotation weren&#8217;t included, then the method would only be accessible by other Java classes.</p>
<p>Next, the <code>DGB</code> and <code>Log.d</code> lines simply create an entry in the Android log for debugging purposes.  This doesn&#8217;t effect the outcome of the function at all, and is simply useful for anyone attempting to debug their code.  Removing these lines would have no effect on the actual implementation of the core functionality.</p>
<p>On the next line, where I define <code>list</code>, I first get the actual Android Intent object from the IntentProxy.  Once I have the Intent object, I can call the method I&#8217;ve been trying to reach in the first place &#8212; <code>getStringArrayListExtra</code> &#8212; passing the <code>name</code> parameter provided to the proxy.  This method returns an ArrayList of String objects.</p>
<p>Finally, we want to turn a simple array of String objects from our new method.  The reason I chose a string array is that Titanium already has the built-in logic to convert a Java array into an array object that JavaScript understands.  To return a string array, we need to convert the ArrayList into an array.  Fortunately, this can easily be done by calling the <code>toArray</code> method on the ArrayList object that we already have.  (If the object is null, then we simply return that instead.)</p>
<p>Great!  So now it&#8217;s time to compile, implement, and test out our module.  Throwing a little speech recognition code together, it quickly becomes clear that there&#8217;s another problem.  As it turns out, Titanium does not properly handle <code><a href="http://developer.android.com/reference/android/content/Intent.html#putExtra(java.lang.String, int)">putExtra</a></code> for integer values.  As such, we&#8217;ll need to add a new method called <code>putIntExtra</code> to our custom Intent module to perform this task.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@Kroll.<span style="color: #006633;">method</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> putIntExtra<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> IntentProxy intentProxy, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> key, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">Object</span> value<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>DBG<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		Log.<span style="color: #006633;">d</span><span style="color: #009900;">&#40;</span>LCAT, <span style="color: #0000ff;">&quot;putIntExtra called with key:&quot;</span> <span style="color: #339933;">+</span> key <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\&quot;</span>, value:&quot;</span> <span style="color: #339933;">+</span> value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>value <span style="color: #000000; font-weight: bold;">instanceof</span> <span style="color: #003399;">Integer</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		intentProxy.<span style="color: #006633;">getIntent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">putExtra</span><span style="color: #009900;">&#40;</span>key, <span style="color: #009900;">&#40;</span><span style="color: #003399;">Integer</span><span style="color: #009900;">&#41;</span> value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
		intentProxy.<span style="color: #006633;">getIntent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">putExtra</span><span style="color: #009900;">&#40;</span>key, <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span><span style="color: #009900;">&#41;</span> <span style="color: #003399;">Double</span>.<span style="color: #006633;">parseDouble</span><span style="color: #009900;">&#40;</span>value.<span style="color: #006633;">toString</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;">&#125;</span></pre></div></div>

<p>Breaking this down, you can see that it behaves similar in structure to the original module method I described.  First, we accept the IntentProxy object along with the desired key and value for the extra data.  Note that we accept the value as an Object though since JavaScript uses loose variable types.</p>
<p>Next, we provide the same basic debug logging as mentioned before.</p>
<p>Now we get to the actual heart of what&#8217;s happening.  Even though I don&#8217;t do so myself, this code can technically be called from the Java itself.  As such, I perform a preliminary check to see if the value is already an Integer instance.  If so, then we don&#8217;t perform any magic, and simply call <code>putExtra</code> on the intent.  (Java&#8217;s automatic unboxing handles the Integer to int conversion.)  However, if the object is not already an Integer, then we need to convert it to one.</p>
<p>At first, I tried to utilize the <code>Integer.parseInt</code> method to convert the string representation of the object.  However, it turns out that the object was being passed in as &#8220;1.0&#8243;, and the decimal point was causing an exception to be thrown when this method was called.  As such, the solution was to parse the string as a Double, then case that to an integer.  This simply removes anything after the decimal, meaning that a value of 1.9999 would become 1.  I decided this is acceptable since the method is intended to only be receiving integer representations in the first place.</p>
<p>Finally, after recompiling, reimplementing, and retesting the code, we find that speech recognition now works.  The Titanium JavaScript code is returned an array of strings when our RecognizerIntent finishes successfully, and we can use this string to populate our grocery list items for the user.</p>
<p>Here&#8217;s an example of the Titanium code used to perform the speech recognition through our new module.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> intentModule <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;com.foodonthetable.intent&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> intent <span style="color: #339933;">=</span> Ti.<span style="color: #660066;">Android</span>.<span style="color: #660066;">createIntent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
  action<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;android.speech.action.RECOGNIZE_SPEECH&quot;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
intent.<span style="color: #660066;">putExtra</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;calling_package&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;com.foodonthetable.mobile&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
intent.<span style="color: #660066;">putExtra</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;android.speech.extra.PROMPT&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;Start speaking...&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
intent.<span style="color: #660066;">putExtra</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;android.speech.extra.LANGUAGE_MODEL&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;free_form&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
intentModule.<span style="color: #660066;">putIntExtra</span><span style="color: #009900;">&#40;</span>intent<span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;android.speech.extra.MAX_RESULTS&quot;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// For retrieving the array list </span>
Ti.<span style="color: #660066;">Android</span>.<span style="color: #660066;">currentActivity</span>.<span style="color: #660066;">startActivityForResult</span><span style="color: #009900;">&#40;</span>intent<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>event.<span style="color: #660066;">resultCode</span> <span style="color: #339933;">==</span> Ti.<span style="color: #660066;">Android</span>.<span style="color: #660066;">RESULT_OK</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> intent <span style="color: #339933;">=</span> event.<span style="color: #660066;">intent</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> results <span style="color: #339933;">=</span> intentModule.<span style="color: #660066;">getStringArrayListExtra</span><span style="color: #009900;">&#40;</span>intent<span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;android.speech.extra.RESULTS&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>results <span style="color: #339933;">&amp;&amp;</span> results.<span style="color: #660066;">length</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;There were &quot;</span> <span style="color: #339933;">+</span> results.<span style="color: #660066;">length</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot; results&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #000066; font-weight: bold;">in</span> results<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Result &quot;</span> <span style="color: #339933;">+</span> i <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot; = &quot;</span> <span style="color: #339933;">+</span> results<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
      console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;No results&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Feel free to view or modify the <a href="https://github.com/mhuggins/intent">full source code</a> on Github.  If you have any suggestions for improvement or actual code changes, feel free to contact me or fork my code and submit a pull request.  Also, check out the <a href="https://market.android.com/details?id=com.foodonthetable.mobile">Android meal planning app</a> that&#8217;s using this feature for a full demonstration.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/matthuggins?a=HgMe_zOgL68:Qx_5ZmuoQrk:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=HgMe_zOgL68:Qx_5ZmuoQrk:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=HgMe_zOgL68:Qx_5ZmuoQrk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/matthuggins?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=HgMe_zOgL68:Qx_5ZmuoQrk:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=HgMe_zOgL68:Qx_5ZmuoQrk:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=HgMe_zOgL68:Qx_5ZmuoQrk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=HgMe_zOgL68:Qx_5ZmuoQrk:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=HgMe_zOgL68:Qx_5ZmuoQrk:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=HgMe_zOgL68:Qx_5ZmuoQrk:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/matthuggins/~4/HgMe_zOgL68" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matthuggins.com/articles/android-voice-recognition-in-appcelerator-titanium/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://www.matthuggins.com/articles/android-voice-recognition-in-appcelerator-titanium?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=android-voice-recognition-in-appcelerator-titanium</feedburner:origLink></item>
		<item>
		<title>Rotating Paperclip Image Attachments in Rails</title>
		<link>http://feedproxy.google.com/~r/matthuggins/~3/8a_uY2AkYis/rotating-paperclip-image-attachments-in-rails</link>
		<comments>http://www.matthuggins.com/articles/rotating-paperclip-image-attachments-in-rails#comments</comments>
		<pubDate>Sat, 22 Oct 2011 20:30:44 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[paperclip]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.matthuggins.com/?p=169</guid>
		<description><![CDATA[With users uploading personal photos, especially ones coming their phones that capture landscape photos in portrait mode and vice versa, one of the things I wanted to integrate into Black Book Singles is the ability to rotate photos. Since I&#8217;m using the Paperclip gem, this should be relatively easy to achieve through a custom attachment [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.matthuggins.com/wp-content/uploads/2011/10/two-finger-rotate-150x150.png" alt="" title="Two Finger Rotate" width="150" height="150" class="alignright size-thumbnail wp-image-182" />With users uploading personal photos, especially ones coming their phones that capture landscape photos in portrait mode and vice versa, one of the things I wanted to integrate into <a href="http://blackbooksingles.com">Black Book Singles</a> is the ability to rotate photos.  Since I&#8217;m using the <a href="https://github.com/thoughtbot/paperclip">Paperclip gem</a>, this should be relatively easy to achieve through a custom attachment processor.</p>
<p>Doing a precursory search resulted in a bit of helpful code to get me started.  Thanks to tekn0t for sharing his example in <a href="https://gist.github.com/827760/bf178d3b293dc67ee6d2af8cbabab377659be728">this gist</a>.</p>
<p>Unfortunately, I came to the conclusion that this example has three main issues:</p>
<ol>
<li>It doesn&#8217;t follow Paperclip convention of passing a set of option key/value pairs into the Processor class to enable the processing.</li>
<li>It assumes any class that implements it also implements both <code>rotating?</code> and <code>rotation</code> methods or attributes, with no flexibility on the naming.</li>
<li>The base class of the implemented <code>Rotator</code> class is <code>Thumbnail</code>.  Because <code>Thumbnail</code> is included by default when the geometry option is used, this means the geometry commands will unnecessarily be executed twice.</li>
</ol>
<p>With these things in mind, I set out to rewrite the example code into a more robust implementation.</p>
<p>First, we&#8217;re going to need an attribute on our model that keeps track of the current angle of rotation.  This is necessary so that future rotations will be based upon the current angle in degrees.  To do this, create a migration that adds an integer column named <code>rotation</code> to whichever Paperclip model you&#8217;re working with.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> AddRotationToPhotos <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span></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>
    add_column <span style="color:#ff3333; font-weight:bold;">:photos</span>, <span style="color:#ff3333; font-weight:bold;">:rotation</span>, <span style="color:#ff3333; font-weight:bold;">:integer</span>, <span style="color:#ff3333; font-weight:bold;">:null</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">false</span>, <span style="color:#ff3333; font-weight:bold;">:default</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">0</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>
    remove_column <span style="color:#ff3333; font-weight:bold;">:photos</span>, <span style="color:#ff3333; font-weight:bold;">:rotation</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Next, we&#8217;ll want a simple way to update the rotation value on a model.  Since Paperclip needs to be explicitly told when to reprocess an image, we&#8217;ll need to tell it to do so whenever this value changes.  Also, keep in mind that basic math tells us that the only degrees we should worry about are between 0-360, meaning we can perform a simple modulus operation on our rotation to keep it in this range.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Photo <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span>
  <span style="color:#5A0A0A; font-weight:bold;">before_save</span> <span style="color:#ff3333; font-weight:bold;">:adjust_rotation</span>
  before_update <span style="color:#ff3333; font-weight:bold;">:reprocess_image</span>
&nbsp;
protected
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> adjust_rotation
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">rotation</span> = <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">rotation</span>.<span style="color:#5A0A0A; font-weight:bold;">to_i</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">rotation</span> = <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">rotation</span> <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#006666;">360</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">rotation</span> <span style="color:#006600; font-weight:bold;">&gt;</span>= <span style="color:#006666;">360</span> <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">rotation</span> <span style="color:#006600; font-weight:bold;">&lt;</span>= <span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">360</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> reprocess_image
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">image</span>.<span style="color:#9900CC;">reprocess</span>! <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">rotation_changed</span>?
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now we can set the rotation value when creating a record (defaulting to 0) or when updating an existing record.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># new record example to rotate 90 degrees clockwise</span>
photo = Photo.<span style="color:#5A0A0A; font-weight:bold;">new</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;">:photo</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
photo.<span style="color:#9900CC;">rotation</span> = <span style="color:#006666;">90</span>
photo.<span style="color:#5A0A0A; font-weight:bold;">save</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># update record example to rotate 90 degrees counter-clockwise</span>
photo = Photo.<span style="color:#9900CC;">find</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>
photo.<span style="color:#9900CC;">update_attribute</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:rotation</span>, <span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">90</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>So far, our code has&#8217;t done anything to tell Paperclip what to do.  The first step in notifying Paperclip is to update the hash passed into <code>has_attached_file</code>.  Notably, we&#8217;ll want to include <code>:rotator</code> (which will be the name of our processor class) into the array of processors.  Also, we&#8217;ll need to pass a <code>:rotation</code> key/value pair in with each attachment style we wish to process as such.  Since this call is being made at the model level, we can&#8217;t simply use <code>self.rotation</code> to access the value of the record&#8217;s rotation angle.  Fortunately, Paperclip allows us to use a <code>lambda</code> function to return a styles hash, which includes the Attachment object.  Knowing this, we can access this current record&#8217;s rotation via <code>attachment.instance.rotation</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Photo <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span>
  has_attached_file <span style="color:#ff3333; font-weight:bold;">:image</span>,
    <span style="color:#ff3333; font-weight:bold;">:processors</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:rotator</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
    <span style="color:#ff3333; font-weight:bold;">:styles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#CC0066; font-weight:bold;">lambda</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:#006600; font-weight:bold;">&#123;</span>
      <span style="color:#ff3333; font-weight:bold;">:thumb</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;">:geometry</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'50x50#'</span>,
        <span style="color:#ff3333; font-weight:bold;">:rotation</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> a.<span style="color:#9900CC;">instance</span>.<span style="color:#9900CC;">rotation</span>,
      <span style="color:#006600; font-weight:bold;">&#125;</span>,
      <span style="color:#ff3333; font-weight:bold;">:full</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;">:geometry</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'640x640&gt;'</span>,
        <span style="color:#ff3333; font-weight:bold;">:rotation</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> a.<span style="color:#9900CC;">instance</span>.<span style="color:#9900CC;">rotation</span>,
      <span style="color:#006600; font-weight:bold;">&#125;</span>,
    <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Finally, now that we&#8217;re passing the <code>rotation</code> value to Paperclip, we need to create the processor to handle it.  Much of the basis of this code is taken from the Thumbnail processor included with Paperclip, which I won&#8217;t be delving into.  The main thing to pay attention to is any code pertaining to the <code>rotation</code> attribute being set and used, most notably in the <code>transformation_command</code> method.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Paperclip
  <span style="color:#9966CC; font-weight:bold;">class</span> Rotator <span style="color:#006600; font-weight:bold;">&lt;</span> Processor
    attr_accessor <span style="color:#ff3333; font-weight:bold;">:file</span>, <span style="color:#ff3333; font-weight:bold;">:rotation</span>, <span style="color:#ff3333; font-weight:bold;">:source_file_options</span>, <span style="color:#ff3333; font-weight:bold;">:convert_options</span>, <span style="color:#ff3333; font-weight:bold;">:whiny</span>, <span style="color:#ff3333; font-weight:bold;">:current_format</span>, <span style="color:#ff3333; font-weight:bold;">:basename</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>file, options = <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span>, attachment = <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">super</span>
      <span style="color:#0066ff; font-weight:bold;">@file</span>                = file
      <span style="color:#0066ff; font-weight:bold;">@rotation</span>            = options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:rotation</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#5A0A0A; font-weight:bold;">to_i</span>
      <span style="color:#0066ff; font-weight:bold;">@source_file_options</span> = options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:source_file_options</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0066ff; font-weight:bold;">@convert_options</span>     = options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:convert_options</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0066ff; font-weight:bold;">@whiny</span>               = options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:whiny</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>? ? <span style="color:#0000FF; font-weight:bold;">true</span> : options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:whiny</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0066ff; font-weight:bold;">@current_format</span>      = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">extname</span><span style="color:#006600; font-weight:bold;">&#40;</span>@file.<span style="color:#9900CC;">path</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@basename</span>            = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">basename</span><span style="color:#006600; font-weight:bold;">&#40;</span>@file.<span style="color:#9900CC;">path</span>, <span style="color:#0066ff; font-weight:bold;">@current_format</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> make
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@rotation</span> != <span style="color:#006666;">0</span>
        dst = <span style="color:#CC00FF; font-weight:bold;">Tempfile</span>.<span style="color:#5A0A0A; font-weight:bold;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#91;</span>@basename, @<span style="color:#CC0066; font-weight:bold;">format</span> ? <span style="color:#996600;">&quot;.#{@format}&quot;</span> : <span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        dst.<span style="color:#9900CC;">binmode</span>
&nbsp;
        <span style="color:#9966CC; font-weight:bold;">begin</span>
          parameters = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
          parameters <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> source_file_options
          parameters <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#996600;">&quot;:source&quot;</span>
          parameters <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> transformation_command
          parameters <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> convert_options
          parameters <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#996600;">&quot;:dest&quot;</span>
&nbsp;
          parameters = parameters.<span style="color:#9900CC;">flatten</span>.<span style="color:#9900CC;">compact</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot; &quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">strip</span>.<span style="color:#9900CC;">squeeze</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot; &quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
          success = Paperclip.<span style="color:#9900CC;">run</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;convert&quot;</span>, parameters, <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">expand_path</span><span style="color:#006600; font-weight:bold;">&#40;</span>@file.<span style="color:#9900CC;">path</span><span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#ff3333; font-weight:bold;">:dest</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">expand_path</span><span style="color:#006600; font-weight:bold;">&#40;</span>dst.<span style="color:#9900CC;">path</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#6666ff; font-weight:bold;">Cocaine::ExitStatusError</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e
          <span style="color:#CC0066; font-weight:bold;">raise</span> PaperclipError, <span style="color:#996600;">&quot;There was an error processing the image rotation for #{@basename}&quot;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@whiny</span>
        <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#6666ff; font-weight:bold;">Cocaine::CommandNotFoundError</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e
          <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#6666ff; font-weight:bold;">Paperclip::CommandNotFoundError</span>.<span style="color:#5A0A0A; font-weight:bold;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Could not run the `convert` command. Please install ImageMagick.&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
        dst
      <span style="color:#9966CC; font-weight:bold;">else</span>
        <span style="color:#0066ff; font-weight:bold;">@file</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  private
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> transformation_command
      <span style="color:#996600;">&quot;-rotate #{@rotation}&quot;</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>And there you have it!  An easy-to-use rotation processor for use with your Paperclip enabled model in Rails.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/matthuggins?a=8a_uY2AkYis:4rZimn2PLdM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=8a_uY2AkYis:4rZimn2PLdM:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=8a_uY2AkYis:4rZimn2PLdM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/matthuggins?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=8a_uY2AkYis:4rZimn2PLdM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=8a_uY2AkYis:4rZimn2PLdM:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=8a_uY2AkYis:4rZimn2PLdM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=8a_uY2AkYis:4rZimn2PLdM:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=8a_uY2AkYis:4rZimn2PLdM:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=8a_uY2AkYis:4rZimn2PLdM:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/matthuggins/~4/8a_uY2AkYis" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matthuggins.com/articles/rotating-paperclip-image-attachments-in-rails/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.matthuggins.com/articles/rotating-paperclip-image-attachments-in-rails?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rotating-paperclip-image-attachments-in-rails</feedburner:origLink></item>
		<item>
		<title>Credit Where Credit Is Due</title>
		<link>http://feedproxy.google.com/~r/matthuggins/~3/VaCl9C--_do/credit-where-credit-is-due</link>
		<comments>http://www.matthuggins.com/articles/credit-where-credit-is-due#comments</comments>
		<pubDate>Thu, 20 Oct 2011 23:00:51 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[sphinx]]></category>

		<guid isPermaLink="false">http://www.matthuggins.com/?p=133</guid>
		<description><![CDATA[While I continue to work on my free online dating service (as well as the accompanying Android dating app), I delve into new territories of Ruby, Rails, and Android programming that I previously have not had to deal with. As such, I&#8217;m constantly searching for info to teach myself where to start, where to turn, [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.matthuggins.com/wp-content/uploads/2011/10/thank-you-150x150.jpg" alt="Thank You!" title="Thank You" width="150" height="150" class="alignright size-thumbnail wp-image-157" />While I continue to work on my <a href="http://blackbooksingles.com" title="Black Book Singles">free online dating</a> service (as well as the accompanying <a href="https://market.android.com/details?id=com.blackbooksingles" title="Black Book Singles for Android">Android dating app</a>), I delve into new territories of Ruby, Rails, and Android programming that I previously have not had to deal with.  As such, I&#8217;m constantly searching for info to teach myself where to start, where to turn, why I&#8217;m encountering errors, and more.  I just want to take an opportunity to spread some love to various articles, posts, and comments that have helped me with my work.</p>
<h4>Upload Multipart Image Using Android&#8217;s HttpPost</h4>
<p>Most of my searches about how to upload images to a web server via Java led to information on classes not directly pertaining to Android&#8217;s built-in <a href="http://developer.android.com/reference/org/apache/http/client/HttpClient.html" rel="nofollow">HttpClient</a> and <a href="http://developer.android.com/reference/org/apache/http/client/methods/HttpRequestBase.html" rel="nofollow">HttpRequestBase</a> classes.  However, since the entirety of my JSON HTTP requests in my Android app is based upon these classes, I wanted to utilize them if possible.  Finally, I came across <a href="http://vikaskanani.wordpress.com/2011/01/11/android-upload-image-or-file-using-http-post-multi-part/" title="Android: Upload image or file using http POST multi-part">Vikas&#8217; post</a> that led me along the correct path.  The key is to download and include Apache&#8217;s HttpMime library, which is a part of HttpClient 4.1.  Because Android is using HttpClient 3.0, this class isn&#8217;t available by default on Android.  Read Vikas&#8217; post for more info.</p>
<h4>Mimicking HTML Drop-downs with Android Spinners</h4>
<p>Part of my registration process when for my Android app is to utilize numeric IDs that represent the visible text for various drop-down options (known as Spinners in Android).  Simply utilizing the zero-based index of a standard ArrayAdapter wasn&#8217;t suitable, however, since the IDs should match up with database values on my server, and will not necessarily be numerically ordered.  <a href="http://stackoverflow.com/questions/2129903/call-a-spinners-value-also-use-other-values-based-on-a-spinners-value/4059301#4059301" title="Call a spinner's value?">The solution</a>, as outlined by user385674 on StackOverflow was to utilize a custom Object that includes a custom key and text value, with the toString method returning what the spinner should display.</p>
<h4>Loading List Item Images Asynchronously on Android</h4>
<p>This is definitely one of the more complex issues I&#8217;ve come across in my early development for Android, and it makes me wish there was a built-in method for ImageViews to download remote images.  <a href="http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html" title="Multithreading For Performance">Tim Bray&#8217;s post</a> on the official Android blog helps to find a way to handle this situation.  However, between his blog post and the <a href="http://code.google.com/p/android-imagedownloader/source/browse/#svn%2Ftrunk%2Fsrc%2Fcom%2Fexample%2Fandroid%2Fimagedownloader" title="android-imagedownloader Source">sample project on Google Code</a>, I&#8217;m sure you&#8217;ll see the great level of complexity involved here.  The main issue revolves around the race condition between Android&#8217;s reuse of views while scrolling through lists and the HTTP response containing the image data for one of these reusable views.  The result is that an ImageView could load with the correct image, being replaced moments later by a slower-loading image that shouldn&#8217;t even be on the screen anymore.</p>
<h4>Integer Out of Range with ThinkingSphinx in Rails</h4>
<p>One of the most fun (read: teeth-grindingly frustrating) things about coding is that sometimes things don&#8217;t work right out of the box.  And not in a &#8220;oh, I just need to add a configuration line&#8221; kind of way.  No, I&#8217;m talking about the &#8220;I&#8217;m using a specific version of [this], and it doesn&#8217;t work with a specific version of [that], and there&#8217;s no way of knowing it until digging deep into the code&#8230;and my soul.&#8221;  The <a href="http://kueda.net/blog/2011/07/21/integer-out-of-range-for-thinking-sphinx-and-postgres/" title="Integer out of range for Thinking Sphinx and Postgres">integer out of range issue</a> I was running into with ThinkingSphinx is exactly the type of thing I&#8217;m talking about here.  Specifically, it was only happening because I&#8217;m using ThinkingSphinx with PostgreSQL, and I needed to set the <code>use_64_bit</code> flag on Sphinx v2.0.1.  Since I was using a 1.X version of Sphinx, this meant I had to upgrade.</p>
<p>After attempting to upgrade, I quickly learned that Sphinx 2.0.1 doesn&#8217;t work with OS X.  User pat on StackOverflow <a href="http://stackoverflow.com/questions/6400839/thinking-sphinx-rails-not-running" title="Thinking sphinx rails not running">posted a solution</a>: upgrade Sphinx to 2.0.2-dev.  This, of course, did not fix the problem for me, resulting in a new &#8220;missing pthread_mutex_timedlock&#8221; error.  After much more digging, I found that at the time pat posted his solution, Sphinx was at revision 2887.  However, when I tried to update, the code was at revision 2888, which is where the new error was introduced.  The solution was to install revision 2887 from the SVN repository.</p>
<p>According to <a href="http://sphinxsearch.com/bugs/view.php?id=881" title="Cannot build sphinx on MacOS X">the official bug report</a>, this issue is now fixed as of revision 2913, although I have not tested personally.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/matthuggins?a=VaCl9C--_do:G7qn1h91iZs:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=VaCl9C--_do:G7qn1h91iZs:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=VaCl9C--_do:G7qn1h91iZs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/matthuggins?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=VaCl9C--_do:G7qn1h91iZs:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=VaCl9C--_do:G7qn1h91iZs:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=VaCl9C--_do:G7qn1h91iZs:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=VaCl9C--_do:G7qn1h91iZs:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=VaCl9C--_do:G7qn1h91iZs:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=VaCl9C--_do:G7qn1h91iZs:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/matthuggins/~4/VaCl9C--_do" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matthuggins.com/articles/credit-where-credit-is-due/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.matthuggins.com/articles/credit-where-credit-is-due?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=credit-where-credit-is-due</feedburner:origLink></item>
		<item>
		<title>Tracking New User Registrations by Source &amp; Search Terms</title>
		<link>http://feedproxy.google.com/~r/matthuggins/~3/pxmKfx2B7sE/tracking-new-user-registrations-by-source-search-terms</link>
		<comments>http://www.matthuggins.com/articles/tracking-new-user-registrations-by-source-search-terms#comments</comments>
		<pubDate>Fri, 07 Oct 2011 21:38:55 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.matthuggins.com/?p=108</guid>
		<description><![CDATA[In order to better analyze my registrations, I wanted to be able to associate them with their respective traffic sources and any search terms used to find my dating service. While searching for an existing gem that takes care of this, the closest thing I could find was a plugin named search_sniffer. Unfortunately, this plugin [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.matthuggins.com/wp-content/uploads/2011/10/google-glasses.jpg"><img src="http://www.matthuggins.com/wp-content/uploads/2011/10/google-glasses-150x150.jpg" alt="" title="Google Search Terms" width="150" height="150" class="alignright size-thumbnail wp-image-124" /></a>In order to better analyze my registrations, I wanted to be able to associate them with their respective traffic sources and any search terms used to find my dating service.  While searching for an existing gem that takes care of this, the closest thing I could find was a plugin named <a href="https://github.com/squeejee/search_sniffer">search_sniffer</a>.  Unfortunately, this plugin hasn&#8217;t been updated in over 3 years, and I&#8217;d much prefer a gem in order to take advantage of the benefits of <a href="http://gembundler.com/">bundler</a>.</p>
<p>After finding nothing on my own and not getting any help from StackOverflow, I resigned to the fact that I&#8217;m going to have to implement my own solution.  The solution I came up with is relatively easy, though I would ultimately like to refactor it so it doesn&#8217;t seem quite as spread out between the controller and model layers.</p>
<p>First, I created a migration to add new columns to my user model to capture the data I want.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> AddTrafficSourceToUsers <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span></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>
    add_column <span style="color:#ff3333; font-weight:bold;">:users</span>, <span style="color:#ff3333; font-weight:bold;">:referrer</span>, <span style="color:#ff3333; font-weight:bold;">:text</span>
    add_column <span style="color:#ff3333; font-weight:bold;">:users</span>, <span style="color:#ff3333; font-weight:bold;">:traffic_source</span>, <span style="color:#ff3333; font-weight:bold;">:string</span>
    add_column <span style="color:#ff3333; font-weight:bold;">:users</span>, <span style="color:#ff3333; font-weight:bold;">:traffic_keywords</span>, <span style="color:#ff3333; font-weight:bold;">:string</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>
    remove_column <span style="color:#ff3333; font-weight:bold;">:users</span>, <span style="color:#ff3333; font-weight:bold;">:referrer</span>
    remove_column <span style="color:#ff3333; font-weight:bold;">:users</span>, <span style="color:#ff3333; font-weight:bold;">:traffic_source</span>
    remove_column <span style="color:#ff3333; font-weight:bold;">:users</span>, <span style="color:#ff3333; font-weight:bold;">:traffic_keywords</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Next, I updated my <code>ApplicationController</code> to capture the referrer on a user&#8217;s first visit.  (Non sequitur: the grammar Nazi in me can&#8217;t stand that &#8220;referer&#8221; is misspelled in the HTTP spec.)</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> ApplicationController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActionController::Base</span></span>
  <span style="color:#5A0A0A; font-weight:bold;">before_filter</span> <span style="color:#ff3333; font-weight:bold;">:capture_referrer</span>
&nbsp;
protected
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> capture_referrer
    <span style="color:#5A0A0A; font-weight:bold;">session</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:referrer</span><span style="color:#006600; font-weight:bold;">&#93;</span> = request.<span style="color:#9900CC;">env</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'HTTP_REFERER'</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">if</span> !<span style="color:#5A0A0A; font-weight:bold;">session</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:referrer</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Since it&#8217;s bad practice in the MVC methodology for the model to talk directly to the session (since models can be used outside the scope of a web request), I had to then manually set the <code>referrer</code> value on the model via the signup controller action.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> UsersController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController
  <span style="color:#9966CC; font-weight:bold;">def</span> create
    <span style="color:#0066ff; font-weight:bold;">@user</span> = User.<span style="color:#5A0A0A; font-weight:bold;">new</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;">:user</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">referrer</span> = <span style="color:#5A0A0A; font-weight:bold;">session</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:referrer</span><span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#5A0A0A; font-weight:bold;">save</span>
      <span style="color:#5A0A0A; font-weight:bold;">redirect_to</span> home_path
    <span style="color:#9966CC; font-weight:bold;">else</span>
      <span style="color:#5A0A0A; font-weight:bold;">render</span> :<span style="color:#5A0A0A; font-weight:bold;">new</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>By this point, you&#8217;re probably wondering why I&#8217;ve only set the <code>referrer</code> attribute on the model when we also need to worry about the <code>traffic_source</code> and <code>traffic_keywords</code>.  Since the latter two attributes are based upon the value of the <code>referrer</code> attribute, that means we can set them in a model callback at the point when the record is created.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveModel::Base</span>
  <span style="color:#008000; font-style:italic;"># NOTE: Ensure that referrer, traffic_source, and traffic_keywords</span>
  <span style="color:#008000; font-style:italic;"># are NOT included in the call to attr_accessible since we don't</span>
  <span style="color:#008000; font-style:italic;"># want the user to pass faux values.</span>
  attr_accessible <span style="color:#ff3333; font-weight:bold;">:username</span>, <span style="color:#ff3333; font-weight:bold;">:email</span>, <span style="color:#ff3333; font-weight:bold;">:password</span>
&nbsp;
  <span style="color:#5A0A0A; font-weight:bold;">before_create</span> <span style="color:#ff3333; font-weight:bold;">:set_traffic_source</span>
&nbsp;
private
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> set_traffic_source
    <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">referrer</span>
      uri = <span style="color:#CC00FF; font-weight:bold;">URI</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">referrer</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">traffic_source</span> <span style="color:#006600; font-weight:bold;">||</span>= uri.<span style="color:#9900CC;">host</span>.<span style="color:#9900CC;">downcase</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>^www\.<span style="color:#006600; font-weight:bold;">/</span>, <span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">traffic_keywords</span> <span style="color:#006600; font-weight:bold;">||</span>= search_terms<span style="color:#006600; font-weight:bold;">&#40;</span>uri<span style="color:#006600; font-weight:bold;">&#41;</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> search_terms<span style="color:#006600; font-weight:bold;">&#40;</span>uri<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#0000FF; font-weight:bold;">nil</span> <span style="color:#9966CC; font-weight:bold;">if</span> uri.<span style="color:#0000FF; font-weight:bold;">nil</span>?
    <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#0000FF; font-weight:bold;">nil</span> <span style="color:#9966CC; font-weight:bold;">if</span> uri.<span style="color:#9900CC;">query</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>?
&nbsp;
    host = uri.<span style="color:#9900CC;">host</span>.<span style="color:#9900CC;">downcase</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>^www\.<span style="color:#006600; font-weight:bold;">/</span>, <span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    params = <span style="color:#CC00FF; font-weight:bold;">CGI</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>uri.<span style="color:#9900CC;">query</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    result = host.<span style="color:#9900CC;">match</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>yahoo\.<span style="color:#9900CC;">com</span>$<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span> ? params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'p'</span><span style="color:#006600; font-weight:bold;">&#93;</span> : <span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'q'</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">||</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'query'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    result ? result.<span style="color:#9900CC;">join</span> : <span style="color:#0000FF; font-weight:bold;">nil</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>There&#8217;s definitely a bit of explaining I need to do here.  First, when setting <code>traffic_source</code>, I&#8217;m only interested in the domain (sans leading &#8220;www.&#8221;).  The <code>gsub</code> call is used to strip out any leading &#8220;www.&#8221; so that, for example, &#8220;www.google.com&#8221; and &#8220;google.com&#8221; both end up being saved as &#8220;google.com&#8221;.  Similarly, I converted all domain names to lowercase to ensure all capitalization variations are treated the same since they ultimately are.</p>
<p>Second, I made an assumption that any search string is going to be passed in under a query parameter named either &#8220;q&#8221; or &#8220;query&#8221;.  When testing the major search engines along with a few of the lesser used ones, I found this to be true for all of them with the exception of Yahoo, which uses &#8220;p&#8221; for some reason.  This is why you&#8217;ll see in my code that there is a specific check for the domain name ending in &#8220;yahoo.com&#8221; that is used to determine which query string parameter to check before defaulting to &#8220;q&#8221; or &#8220;query&#8221;.</p>
<p>There you have it!  Now I&#8217;m able to perform simple queries on where my users are coming from and how they&#8217;re finding me.  This alone isn&#8217;t much more useful than what a free service like Google Analytics offers, but obviously with greater data-mining, truly insightful information can be learned about each of your users and their behaviors&#8217; depending upon where they&#8217;re from and how they found you.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/matthuggins?a=pxmKfx2B7sE:F_BVIR8n2UI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=pxmKfx2B7sE:F_BVIR8n2UI:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=pxmKfx2B7sE:F_BVIR8n2UI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/matthuggins?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=pxmKfx2B7sE:F_BVIR8n2UI:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=pxmKfx2B7sE:F_BVIR8n2UI:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=pxmKfx2B7sE:F_BVIR8n2UI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=pxmKfx2B7sE:F_BVIR8n2UI:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=pxmKfx2B7sE:F_BVIR8n2UI:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=pxmKfx2B7sE:F_BVIR8n2UI:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/matthuggins/~4/pxmKfx2B7sE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matthuggins.com/articles/tracking-new-user-registrations-by-source-search-terms/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.matthuggins.com/articles/tracking-new-user-registrations-by-source-search-terms?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=tracking-new-user-registrations-by-source-search-terms</feedburner:origLink></item>
		<item>
		<title>Simple User Registration Spam Prevention in Rails 3</title>
		<link>http://feedproxy.google.com/~r/matthuggins/~3/vcSTjvkRfho/simple-user-registration-spam-prevention-in-rails-3</link>
		<comments>http://www.matthuggins.com/articles/simple-user-registration-spam-prevention-in-rails-3#comments</comments>
		<pubDate>Thu, 06 Oct 2011 03:42:24 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.matthuggins.com/?p=79</guid>
		<description><![CDATA[Tonight, in a little under an hour, I was able to implement spam prevention for my user registration flow thanks to the simple API provided by Stop-Registration-Spam.org. In Rails 3, creating new validators is relatively painless. Create a new validator class in a folder defined by you. For my project, I decided to place all [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.matthuggins.com/wp-content/uploads/2011/09/stop-spam-150x150.jpg" alt="" title="Stop SPAM" width="150" height="150" class="alignright size-thumbnail wp-image-104" />Tonight, in a little under an hour, I was able to implement spam prevention for my user registration flow thanks to the simple API provided by <a href="http://www.stop-registration-spam.org">Stop-Registration-Spam.org</a>.</p>
<p>In Rails 3, creating new validators is relatively painless.  Create a new validator class in a folder defined by you.  For my project, I decided to place all validators within <code>app/validators</code>.</p>
<p>The class should extend the <code><a href="https://github.com/rails/rails/blob/c495bfc127405f7ead0d1c275c4d75682a51e00e/activemodel/lib/active_model/validator.rb#L133">ActiveModel::EachValidator</a></code> class found within Rails 3 core, in which you&#8217;ll generally override two methods: <code>check_validity!</code> and <code>validate_each</code>.</p>
<ol>
<li><code>check_validity!</code> is called by the class&#8217; initializer to verify that the validator&#8217;s arguments supplied are valid. If they are not, throw an exception that will be seen by the developer using your validator.</li>
<li><code>validate_each</code> is where the actual validation occurs on the values set for each attribute implementing this validator at runtime.</li>
</ol>
<p>The code for the validator is included in the code snippet below.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> SpamValidator <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveModel::EachValidator</span>
  DEFAULTS = <span style="color:#006600; font-weight:bold;">&#123;</span>:level <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">1</span>, <span style="color:#ff3333; font-weight:bold;">:timeout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">freeze</span>
  MESSAGES = <span style="color:#006600; font-weight:bold;">&#123;</span>:block <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;is blacklisted&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:no_domain</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;includes invalid domain&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:ip_not_recognized</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">nil</span>, <span style="color:#ff3333; font-weight:bold;">:over_limit</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">freeze</span>
  RESERVED_OPTIONS = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:level</span>, <span style="color:#ff3333; font-weight:bold;">:timeout</span>, <span style="color:#ff3333; font-weight:bold;">:block</span>, <span style="color:#ff3333; font-weight:bold;">:no_domain</span>, <span style="color:#ff3333; font-weight:bold;">:ip_not_recognized</span>, <span style="color:#ff3333; font-weight:bold;">:over_limit</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">freeze</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#41;</span>
    DEFAULTS.<span style="color:#5A0A0A; font-weight:bold;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>key, value<span style="color:#006600; font-weight:bold;">|</span>
      options<span style="color:#006600; font-weight:bold;">&#91;</span>key<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">||</span>= value
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">super</span><span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> check_validity!
    <span style="color:#9966CC; font-weight:bold;">unless</span> options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:level</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">is_a</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">Integer</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">1</span>..<span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:level</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">ArgumentError</span>, <span style="color:#996600;">&quot;:level must be an Integer between 1-5&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">unless</span> options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:timeout</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">is_a</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">Integer</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:timeout</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#006666;">0</span>
      <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">ArgumentError</span>, <span style="color:#996600;">&quot;:timeout must be an Integer greater than 0&quot;</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> validate_each<span style="color:#006600; font-weight:bold;">&#40;</span>record, attribute, value<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#9966CC; font-weight:bold;">if</span> value.<span style="color:#0000FF; font-weight:bold;">nil</span>?
    <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">ArgumentError</span>, <span style="color:#996600;">&quot;#{attribute} must be a String.&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> value.<span style="color:#9900CC;">is_a</span>?<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>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">begin</span>
      <span style="color:#008000; font-style:italic;"># API REF: http://www.stop-registration-spam.org/api</span>
      url = <span style="color:#996600;">&quot;http://www.stop-registration-spam.org/api/level#{options[:level]}/json?email=#{CGI.escape(value)}&quot;</span>
      result = JSON.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>url, <span style="color:#ff3333; font-weight:bold;">:read_timeout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:timeout</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">rescue</span>
      <span style="color:#008000; font-style:italic;"># TODO log error</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">if</span> result <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> result<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'request_status'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      error_key = result<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'request_status'</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#5A0A0A; font-weight:bold;">to_s</span>.<span style="color:#9900CC;">downcase</span>.<span style="color:#9900CC;">to_sym</span>
      error_message = MESSAGES<span style="color:#006600; font-weight:bold;">&#91;</span>error_key<span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">if</span> error_message
        errors_options = options.<span style="color:#9900CC;">except</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>RESERVED_OPTIONS<span style="color:#006600; font-weight:bold;">&#41;</span>
        errors_options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:message</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">||</span>= options<span style="color:#006600; font-weight:bold;">&#91;</span>error_key<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">if</span> options<span style="color:#006600; font-weight:bold;">&#91;</span>error_key<span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
        record.<span style="color:#5A0A0A; font-weight:bold;">errors</span>.<span style="color:#5A0A0A; font-weight:bold;">add</span><span style="color:#006600; font-weight:bold;">&#40;</span>attribute, error_message, errors_options<span style="color:#006600; font-weight:bold;">&#41;</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>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Using this validator is incredibly easy.  In your model, just add a <code>:spam</code> key with whatever values you require passed as a hash within the <code>validates</code> call for your email-formatted attributes.</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span>
  validates <span style="color:#ff3333; font-weight:bold;">:email</span>, <span style="color:#ff3333; font-weight:bold;">:spam</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;">:level</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">5</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The hash accepts the following parameters:</p>
<ul>
<li><code>:level</code> &#8211; integer from 1-5 (default 1) &#8211; The level of spam prevention to utilize as defined by the <a href="http://www.stop-registration-spam.org/api">Stop-Registration-Spam.org API</a>.</li>
<li><code>:timeout</code> &#8211; integer greater than 0 (default 5) &#8211; The number of seconds to timeout when unable to connect with, or receive a response from, the API.</li>
<li><code>:block</code> &#8211; string (default &#8220;is blacklisted&#8221;) &#8211; The message to use for response code BLOCK, meaning this email address did not meet the checks at the level requested.</li>
<li><code>:no_domain</code> &#8211; string (default &#8220;includes invalid domain&#8221;) &#8211; The message to use for response code NO_DOMAIN, meaning the domain provided is not valid.</li>
<li><code>:ip_not_recognized</code> &#8211; string (default <code>nil</code>) &#8211; The message to use for response code IP_NOT_RECOGNISED, meaning the requesting IP is not valid for high volume commercial use.</li>
<li><code>:over_limit</code> &#8211; string (default <code>nil</code>) &#8211; The message to use for response code OVER_LIMIT, meaning you have reached your daily request limit.</li>
</ul>
<p>My decision to leave <code>:ip_not_recognized</code> and <code>:over_limit</code> as <code>nil</code> values with no error messages is due to my not wanting to prevent users from registering when the service is not responding as expected.  Similarly, the validator passes when a timeout occurs.  This could easily be modified to allow for further customizations through additional hash values, but this is suitable for my needs, and it demonstrates the simplicity behind implementing a custom Rails 3 validator.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/matthuggins?a=vcSTjvkRfho:caSZFWB_Gi4:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=vcSTjvkRfho:caSZFWB_Gi4:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=vcSTjvkRfho:caSZFWB_Gi4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/matthuggins?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=vcSTjvkRfho:caSZFWB_Gi4:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=vcSTjvkRfho:caSZFWB_Gi4:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=vcSTjvkRfho:caSZFWB_Gi4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=vcSTjvkRfho:caSZFWB_Gi4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=vcSTjvkRfho:caSZFWB_Gi4:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=vcSTjvkRfho:caSZFWB_Gi4:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/matthuggins/~4/vcSTjvkRfho" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matthuggins.com/articles/simple-user-registration-spam-prevention-in-rails-3/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.matthuggins.com/articles/simple-user-registration-spam-prevention-in-rails-3?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=simple-user-registration-spam-prevention-in-rails-3</feedburner:origLink></item>
		<item>
		<title>Baker to Builder: From CakePHP to Rails</title>
		<link>http://feedproxy.google.com/~r/matthuggins/~3/brD1Koble2w/baker-to-builder-from-cakephp-to-rails</link>
		<comments>http://www.matthuggins.com/articles/baker-to-builder-from-cakephp-to-rails#comments</comments>
		<pubDate>Fri, 30 Sep 2011 17:03:00 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.matthuggins.com/?p=20</guid>
		<description><![CDATA[This past Tuesday night, I gave my first presentation for an Austin on Rails meeting. As a Ruby on Rails developer who comes from a PHP background &#8212; specifically utilizing CakePHP &#8212; I was asked to present on my experiences between the two frameworks. The presentation itself covers beginner level material. It describes my personal [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.matthuggins.com/wp-content/uploads/2011/09/cakephp-150x150.png" alt="" title="CakePHP" width="150" height="150" class="alignright size-thumbnail wp-image-66" />This past Tuesday night, I gave my first presentation for an <a href="http://austinonrails.org/">Austin on Rails</a> meeting.  As a <a href="http://rubyonrails.org/">Ruby on Rails</a> developer who comes from a PHP background &#8212; specifically utilizing <a href="http://cakephp.org/">CakePHP</a> &#8212; I was asked to present on my experiences between the two frameworks.</p>
<p>The presentation itself covers beginner level material.  It describes my personal reasons for moving from CakePHP to Rails, and why I now prefer the latter.  Although it does not delve into any of the finer details, it does cover a few key points about both Rails and Ruby in general:</p>
<ul>
<li>A comparison of the overall structure of each framework</li>
<li>Some general Ruby language benefits not found in PHP</li>
<li>The simplicity of plugin (gem) integration in Rails compared to CakePHP</li>
<li>Deployment strategies available in Rails</li>
</ul>
<p>Again, the topics here only scratch the surface.  There is a lot of information not included that make the Rails framework superior to my own experiences with CakePHP.</p>
<p>If you&#8217;re currently developing with PHP, I definitely encourage you to consider giving Rails a try.  Feel free to download the PDF version of my presentation: <a href="http://www.matthuggins.com/wp-content/uploads/2011/09/cakephp-to-rails.pdf">Baker to Builder: CakePHP to Rails</a>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/matthuggins?a=brD1Koble2w:_T3MnFBJ_Hw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=brD1Koble2w:_T3MnFBJ_Hw:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=brD1Koble2w:_T3MnFBJ_Hw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/matthuggins?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=brD1Koble2w:_T3MnFBJ_Hw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=brD1Koble2w:_T3MnFBJ_Hw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=brD1Koble2w:_T3MnFBJ_Hw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=brD1Koble2w:_T3MnFBJ_Hw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/matthuggins?a=brD1Koble2w:_T3MnFBJ_Hw:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/matthuggins?i=brD1Koble2w:_T3MnFBJ_Hw:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/matthuggins/~4/brD1Koble2w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matthuggins.com/articles/baker-to-builder-from-cakephp-to-rails/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.matthuggins.com/articles/baker-to-builder-from-cakephp-to-rails?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=baker-to-builder-from-cakephp-to-rails</feedburner:origLink></item>
	</channel>
</rss>

