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

<channel>
	<title>Unixmonkey.net</title>
	<atom:link href="http://unixmonkey.net/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://unixmonkey.net</link>
	<description>creative engineering and technological abuse</description>
	<lastBuildDate>Fri, 06 Aug 2010 18:03:10 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>I&#8217;m in love with :symbol.to_proc</title>
		<link>http://unixmonkey.net/?p=35</link>
		<comments>http://unixmonkey.net/?p=35#comments</comments>
		<pubDate>Fri, 06 Aug 2010 18:03:10 +0000</pubDate>
		<dc:creator>Unixmonkey</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[programming ruby rails]]></category>

		<guid isPermaLink="false">http://unixmonkey.net/?p=35</guid>
		<description><![CDATA[I&#8217;ve been crawling over this Rails project and lately finding lots of places where clarity could be increased by using symbol_to_proc, so I thought I would share it a bit for those not in the know on this handy ruby shortcut.
Rails added symbol_to_proc shorthand in version 1.1, and it is such a nice shortcut, that [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been crawling over this Rails project and lately finding lots of places where clarity could be increased by using symbol_to_proc, so I thought I would share it a bit for those not in the know on this handy ruby shortcut.</p>
<p>Rails added symbol_to_proc shorthand in version 1.1, and it is such a nice shortcut, that it became part of the Ruby language in version 1.8.7</p>
<p>So, anywhere you would normally use an iterator with a block like so:</p>
<pre>people.collect { |p| p.name }</pre>
<p>could be shortened to call like:</p>
<pre>people.collect(&amp;:name)</pre>
<p>The difference may not look so dramatic in the above example, but how about this one:</p>
<pre>   # classic
   prison.inmates.select{ |i| i.repeat_offender? }.select{ |i| i.offsenses }.collect{ |o| o.prosecution_fees }.sum

   # to_proc
   prison.inmates.select(&amp;:repeat_offender?).select(&amp;:offenses).collect(&amp;:prosecution_fees).sum</pre>
<p>Some people, including Rails core member pratik (http://m.onkey.org/2007/6/30/let-s-start-with-wtf)<br />
Have criticized and advised against using this shortcut because it is roughly 4 times slower than doing without its syntax sugar.</p>
<p>Now, I would rather have a beautiful, understandable code base than a particularly fast one (after all, I *am* using Ruby), but the reason for the slowness is largely because of the implementation as shown below:</p>
<pre>  class Symbol
    def to_proc
      Proc.new { |*args| args.shift.__send__(self, *args)
    end
  end</pre>
<p>This implementation looks for arguments passed in and shifts self off of them before calling.<br />
This allows for calling a method with arguments like so:</p>
<pre>[1,2,3].inject(&amp;:+)</pre>
<p>I believe this represents a real edge case at the expense of a lot of speed, and Luke Redpath (http://lukeredpath.co.uk/blog/optimising-symbol-to_proc.html) has a lot of good to say about the topic, and even goes as far to present a patch for how this should be implemented for pure speed:</p>
<pre>  class Symbol
  def to_proc
    @to_proc_proc ||= Proc.new { |obj| obj.__send__(self) }
  end
end</pre>
<p>I&#8217;ve patched this in to my Rails project and not a single one of my tests failed, your mileage may vary, but even without the speed boost, I&#8217;ll continue to use :symbol.to_proc because I love it so.</p>
]]></content:encoded>
			<wfw:commentRss>http://unixmonkey.net/?feed=rss2&amp;p=35</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails respond_to rendering wrong format in IE</title>
		<link>http://unixmonkey.net/?p=33</link>
		<comments>http://unixmonkey.net/?p=33#comments</comments>
		<pubDate>Mon, 02 Aug 2010 21:31:13 +0000</pubDate>
		<dc:creator>unixmonkey</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[programming ruby rails ie]]></category>

		<guid isPermaLink="false">http://unixmonkey.net/?p=33</guid>
		<description><![CDATA[I ran into an interesting issue today where a client viewing my Rails site would go to a link; and instead of seeing the html view rendered, it was skipping right to an alternate format in the respond_to block.
Clicking a link going to /orders, was instead taking them to /orders.xls, which I have in a [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into an interesting issue today where a client viewing my Rails site would go to a link; and instead of seeing the html view rendered, it was skipping right to an alternate format in the respond_to block.</p>
<p>Clicking a link going to /orders, was instead taking them to /orders.xls, which I have in a respond_to block like so:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby">  <span style="color:#9966CC; font-weight:bold;">def</span> orders
    <span style="color:#0066ff; font-weight:bold;">@orders</span> = Order.<span style="color:#9900CC;">all</span>
    respond_to <span style="color:#9966CC; font-weight:bold;">do</span> |format|
      <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">html</span> <span style="color:#008000; font-style:italic;"># new.html.erb</span>
      <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">xls</span>   <span style="color:#008000; font-style:italic;"># new.xls.erb</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The client in question was using Internet Explorer. This provided a major clue.<br />
It turns out that IE will send an HTTP_ACCEPT header listing all the stuff it can accept in the browser, and thus, because it can accept .xls files, it requests that format.</p>
<p>I&#8217;m experiencing this in a Rails 2.3.8 app, but documentation at railsguides.info states this behavior was changed in Rails 2.2.  Perhaps an older plugin is switching it back on, I&#8217;ll have to investigate.</p>
<p>In any case, adding this line to application.rb solves the problem:</p>
<pre>config.action_controller.use_accept_header = false</pre>
<p>This causes it to behave as expected, where it uses the file extension alone to determine the format when there is a question which format to use.</p>
]]></content:encoded>
			<wfw:commentRss>http://unixmonkey.net/?feed=rss2&amp;p=33</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ActiveRecord Query Building with Multiple and Optional Conditions</title>
		<link>http://unixmonkey.net/?p=31</link>
		<comments>http://unixmonkey.net/?p=31#comments</comments>
		<pubDate>Tue, 30 Dec 2008 02:43:07 +0000</pubDate>
		<dc:creator>unixmonkey</dc:creator>
				<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[ActiveRecord Rails Ruby Programming Database SQL]]></category>

		<guid isPermaLink="false">http://unixmonkey.net/?p=31</guid>
		<description><![CDATA[For some complex searches, I find myself needing to build a query with some optional conditions that may or may not exist based on search terms.  
I could concatenate an SQL string, but when we are dealing with user-supplied input, we need to parameterize the sql query with question marks (?) for binding parameters [...]]]></description>
			<content:encoded><![CDATA[<p>For some complex searches, I find myself needing to build a query with some optional conditions that may or may not exist based on search terms.  </p>
<p>I could concatenate an SQL string, but when we are dealing with user-supplied input, we need to parameterize the sql query with question marks (?) for binding parameters to to avoid SQL injection attacks.</p>
<p>But I may not know how many parameters I’m actually going to use in a query.</p>
<p>With a form like this:</p>
<pre>
Show me my friends:
  living in: [   ]
  whose hobby is: () skating, () fishing, () basketball
  over: [  ] years old

  *(no required fields)
</pre>
<p>At first stab, you could try something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby">User.<span style="color:#9900CC;">friends</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> =&gt; <span style="color:#006600; font-weight:bold;">&#91;</span>
   <span style="color:#996600;">'town LIKE ? AND hobby = ? AND age &gt;= ?'</span>, 
   <span style="color:#996600;">&quot;%#{params[:town]}%&quot;</span>, params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:hobby</span><span style="color:#006600; font-weight:bold;">&#93;</span>, params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:age</span><span style="color:#006600; font-weight:bold;">&#93;</span> 
<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>This would work, but only if all fields are filled out; otherwise the SQL generated would break looking like this if someone only filled in the name part of the form:</p>
<pre>
"SELECT * FROM users WHERE town LIKE "%indianapolis%" AND hobby = '' AND age >= ''"
</pre>
<p>There are some plugins like Ezra&#8217;s <a href="http://github.com/ezmobius/ez-where/tree">Ez-Where</a> to handle query building; but how about we try using the built-in symbol key interpolation <a href="http://noobkit.com/show/ruby/rails/rails-stable/activerecord/activerecord/base.html#toc-conditions">as described here</a> in ActiveRecord to get the job done.</p>
<p>This lets you use named :symbols in place of question marks for binding.</p>
<p>Find lets you supply your conditions as a 2-element array with a string, and a corresponding hash like so:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby">User.<span style="color:#9900CC;">friends</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> =&gt; <span style="color:#006600; font-weight:bold;">&#91;</span> 
  <span style="color:#996600;">'town LIKE :town AND hobby = :hobby AND age &gt;= :age'</span>, 
  <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:town</span> =&gt; <span style="color:#996600;">&quot;%#{params[:town]}%&quot;</span> , <span style="color:#ff3333; font-weight:bold;">:hobby</span> =&gt; params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:hobby</span><span style="color:#006600; font-weight:bold;">&#93;</span>,  <span style="color:#ff3333; font-weight:bold;">:age</span> = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:age</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Again, this will work just fine if all fields are filled out; but how do we omit conditions and hash keys?</p>
<p>Our final SQL string can be built by joining conditions with AND (or OR if your app suggests it), and stuffing new key/value pairs into our arguments hash, or with Hash.merge!</p>
<p>First we’ll set up our search method like so:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby"><span style="color:#9966CC; font-weight:bold;">def</span> results
  conditions  = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  arguments = <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">unless</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:town</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>?
    conditions &lt;&lt; <span style="color:#996600;">'town LIKE :town'</span>
    arguments<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:town</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;%#{params[:town]}%&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">unless</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:hobby</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>?
    conditions &lt;&lt; <span style="color:#996600;">'hobby = :hobby'</span>
    arguments<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:hobby</span><span style="color:#006600; font-weight:bold;">&#93;</span> = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:hobby</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">unless</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:age</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</span>?
    conditions &lt;&lt; <span style="color:#996600;">'age &gt;= :age'</span>
    arguments<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:age</span><span style="color:#006600; font-weight:bold;">&#93;</span> = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:age</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  all_conditions = conditions.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">' AND '</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  <span style="color:#0066ff; font-weight:bold;">@user_friends</span> = User.<span style="color:#9900CC;">friends</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> =&gt; <span style="color:#006600; font-weight:bold;">&#91;</span>all_conditions, arguments<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;">end</span></pre></div></div>

<p>An alternative is to use Hash.merge! like so:<br />
(this will let you assign more than one key/value pair at a time or to combine hashes)</p>
<p>instead of:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby">arguments<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:town</span><span style="color:#006600; font-weight:bold;">&#93;</span>  = <span style="color:#996600;">&quot;%#{params[:town]}%&quot;</span>
arguments<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:hobby</span><span style="color:#006600; font-weight:bold;">&#93;</span> = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:hobby</span><span style="color:#006600; font-weight:bold;">&#93;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="ruby">  arguments.<span style="color:#9900CC;">merge</span>!<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#123;</span> 
    <span style="color:#ff3333; font-weight:bold;">:town</span>  =&gt; <span style="color:#996600;">&quot;%#{params[:town]}%&quot;</span>,
    <span style="color:#ff3333; font-weight:bold;">:hobby</span> =&gt; params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:hobby</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Maybe not as elegant as using a plugin, but certainly clear and flexible.</p>
]]></content:encoded>
			<wfw:commentRss>http://unixmonkey.net/?feed=rss2&amp;p=31</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>I&#8217;ve got some ActiveRecord in my Shoes</title>
		<link>http://unixmonkey.net/?p=27</link>
		<comments>http://unixmonkey.net/?p=27#comments</comments>
		<pubDate>Wed, 19 Nov 2008 03:09:53 +0000</pubDate>
		<dc:creator>unixmonkey</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Shoes]]></category>

		<guid isPermaLink="false">http://unixmonkey.net/?p=27</guid>
		<description><![CDATA[I&#8217;ve been playing around with Shoes (shoooes.net) lately as a way to put a cross-platform graphical user interface (GUI) on some of my small purpose-built command-line ruby scripts.
I find that it is quite easy to get started with, and lends a lot of flexibility to the way your program is structured and displayed. However, the structure [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been playing around with Shoes (<a href="http://shoooes.net">shoooes.net</a>) lately as a way to put a cross-platform graphical user interface (GUI) on some of my small purpose-built command-line ruby scripts.</p>
<p>I find that it is quite easy to get started with, and lends a lot of flexibility to the way your program is structured and displayed. However, the structure feels a little bit alien compared to everyday ruby, and there are some gotcha&#8217;s you need to keep in mind while developing for Shoes.</p>
<p>I feel I must preface this article by saying that Shoes has excellent documentation, <a href="http://twitter.com/_why">_why (the lucky stiff)</a> turns documentation into its own art form.  The manual, <a href="http://hackety.org/press/">&#8220;Nobody Knows Shoes&#8221;</a> reads a lot like a comic book, full of _why&#8217;s own original artwork and clippings from old-timey photos and art, and is complimented by the documentation at <a href="http://help.shoooes.net">help.shoooes.net</a></p>
<p>I had a bit of trouble at first getting ActiveRecord to interface with a database from a straight port from one of my console apps because I glossed over the parts of the manual that detail the tricky behavior of the garbage collector reaping predefined classes after the app&#8217;s initial load.</p>
<p>The fix is pretty simple. Stick all your classes in an external file (or many) and load them using &#8216;require&#8217;.</p>
<p>Anyhow, here is a barebones example of a working implementation for using ActiveRecord in Shoes:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby"><span style="color:#008000; font-style:italic;"># in foo.rb</span>
<span style="color:#9966CC; font-weight:bold;">class</span> Foo &lt; <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;">#in app.rb</span>
Shoes.<span style="color:#9900CC;">setup</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  gem <span style="color:#996600;">'activerecord'</span>
  <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'active_record'</span>
  <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">establish_connection</span><span style="color:#006600; font-weight:bold;">&#40;</span>
    <span style="color:#ff3333; font-weight:bold;">:adapter</span>   =&gt; <span style="color:#996600;">'sqlite3'</span>,
    <span style="color:#ff3333; font-weight:bold;">:dbfile</span>    =&gt; <span style="color:#996600;">'foos_db.sqlite3'</span>
  <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'foo'</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
Shoes.<span style="color:#9900CC;">app</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  <span style="color:#0066ff; font-weight:bold;">@foos</span> = Foo.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  para <span style="color:#0066ff; font-weight:bold;">@foos</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now, this example requires there is an existing sqlite database with a foos table, change out the establish_connection parameters to connect to any other database. The gem &#8216;activerecord&#8217; statment tells shoes to install the activerecord gem into the shoes ruby library if it isn&#8217;t already there.</p>
<p>If you don&#8217;t already have a database, and just want to use a db to act as a storage layer for your app, then you might want to use ActiveRecord::Schema.define to create a database and setup the tables the same way you do for Rails migrations.</p>
<p>Here is a more complete example of an app to keep track of notes using ActiveRecord as the backend.  I like the &#8220;base class that inherits from Shoes&#8221; pattern, so I&#8217;m using that here.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby"><span style="color:#008000; font-style:italic;"># in note.rb</span>
<span style="color:#9966CC; font-weight:bold;">class</span> Note &lt; <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># in app.rb</span>
Shoes.<span style="color:#9900CC;">setup</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  gem <span style="color:#996600;">'activerecord'</span> <span style="color:#008000; font-style:italic;"># install AR if not found</span>
&nbsp;
  <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'active_record'</span>
  <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'fileutils'</span>
&nbsp;
  <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">establish_connection</span><span style="color:#006600; font-weight:bold;">&#40;</span>
    <span style="color:#ff3333; font-weight:bold;">:adapter</span>   =&gt; <span style="color:#996600;">'sqlite3'</span>,
    <span style="color:#ff3333; font-weight:bold;">:dbfile</span>    =&gt; <span style="color:#996600;">'shoes_app.sqlite3'</span>
  <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># create the db if not found</span>
  <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exist</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;shoes_app.sqlite3&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Schema</span>.<span style="color:#9900CC;">define</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      create_table <span style="color:#ff3333; font-weight:bold;">:notes</span> <span style="color:#9966CC; font-weight:bold;">do</span> |t|
        t.<span style="color:#9900CC;">column</span> <span style="color:#ff3333; font-weight:bold;">:message</span>, <span style="color:#ff3333; font-weight:bold;">:string</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>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> ShoesApp &lt; Shoes
  <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'note'</span>
&nbsp;
  url <span style="color:#996600;">'/'</span>, <span style="color:#ff3333; font-weight:bold;">:index</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> index
    para <span style="color:#996600;">'Say something...'</span>
    flow <span style="color:#9966CC; font-weight:bold;">do</span>
      <span style="color:#0066ff; font-weight:bold;">@note</span> = edit_line
      button <span style="color:#996600;">'OK'</span> <span style="color:#9966CC; font-weight:bold;">do</span>
        Note.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:message</span> =&gt; <span style="color:#0066ff; font-weight:bold;">@note</span>.<span style="color:#9900CC;">text</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">save</span>
        <span style="color:#0066ff; font-weight:bold;">@note</span>.<span style="color:#9900CC;">text</span> = <span style="color:#996600;">''</span>
        <span style="color:#0066ff; font-weight:bold;">@result</span>.<span style="color:#9900CC;">replace</span> get_notes  
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#0066ff; font-weight:bold;">@result</span> = para get_notes
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> get_notes
    messages = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    notes = Note.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:select</span> =&gt; <span style="color:#996600;">'message'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    notes.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> |foo|
      messages &lt;&lt; foo.<span style="color:#9900CC;">message</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    out = messages.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;<span style="color:#000099;">\n</span>&quot;</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;">end</span>
&nbsp;
Shoes.<span style="color:#9900CC;">app</span> <span style="color:#ff3333; font-weight:bold;">:title</span> =&gt; <span style="color:#996600;">'Notes'</span>, <span style="color:#ff3333; font-weight:bold;">:width</span> =&gt; <span style="color:#006666;">260</span>, <span style="color:#ff3333; font-weight:bold;">:height</span> =&gt; <span style="color:#006666;">350</span></pre></div></div>

<p>Here&#8217;s a screenshot:<br />
<a href='http://unixmonkey.net/blog/wp-content/uploads/2008/11/notes.gif'><img src="http://unixmonkey.net/blog/wp-content/uploads/2008/11/notes.gif" alt="notes, the Shoes app" title="notes" class="alignnone size-full wp-image-28" /></a></p>
<p>There you are; a cross-platform desktop app that doesn&#8217;t require a full-on build environment, and can be distributed with the source exposed for later improvements.</p>
<p>The first time this runs, it installs Activerecord, requires it, establishes a connection, creates the table unless one already exists. Then it shows a form to add notes followed by all the existing notes in the database. Adding a new note refreshes the notes shown.</p>
<p>This isn&#8217;t exactly a polished app with full CRUD, but should prove a good introduction to Shoes for someone used to working with ActiveRecord.</p>
]]></content:encoded>
			<wfw:commentRss>http://unixmonkey.net/?feed=rss2&amp;p=27</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Slurping up and Spitting out CSV Files in Ruby with FasterCSV and Ruport</title>
		<link>http://unixmonkey.net/?p=23</link>
		<comments>http://unixmonkey.net/?p=23#comments</comments>
		<pubDate>Thu, 01 May 2008 18:13:38 +0000</pubDate>
		<dc:creator>unixmonkey</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby rails gems plugins csv database]]></category>

		<guid isPermaLink="false">http://unixmonkey.net/?p=23</guid>
		<description><![CDATA[I&#8217;ve got some data in an excel file that I need to put in the database and its far too much to do by hand, what will I do?
Lets throw some ruby at the problem!
First, excel it too darn complicated and proprietary a format to even mess with unless you are creating something really worth [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve got some data in an excel file that I need to put in the database and its far too much to do by hand, what will I do?</p>
<p>Lets throw some ruby at the problem!</p>
<p>First, excel it too darn complicated and proprietary a format to even mess with unless you are creating something really worth it, so lets open that .xls with Excel or OpenOffice and do a File -&gt; Save As -&gt; .csv (comma separated values) to get a file that is easier to work with.</p>
<p>Now, we could write our own CSV parser since its such a simple format, but why futz with it when someone else has already put out a good library for that will likely be more error tolerant? Lets use <a href="http://fastercsv.rubyforge.org" title="FasterCSV ruby library">FasterCSV</a>, as its pretty well-known.</p>
<p>Install by issuing:</p>
<pre>
sudo gem install fastercsv</pre>
<p>Now you can just fire up script/console of your Rails app and type in the below, or just put this in a database migration to slurp up all that good spreadsheet data.</p>
<p>The below assumes you have a &#8216;users&#8217; table with fields name, address, and email that are also rows in your excel file. Adjust as necessary.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'fastercsv'</span>
FasterCSV.<span style="color:#9900CC;">foreach</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{RAILS_ROOT}/myfile.csv&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> |row|
  record = User.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>
    <span style="color:#ff3333; font-weight:bold;">:name</span>    =&gt; row<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#008000; font-style:italic;"># first column of csv file</span>
    <span style="color:#ff3333; font-weight:bold;">:address</span> =&gt; row<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#008000; font-style:italic;"># second column</span>
    <span style="color:#ff3333; font-weight:bold;">:email</span>   =&gt; row<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#93;</span>  <span style="color:#008000; font-style:italic;"># third</span>
  <span style="color:#006600; font-weight:bold;">&#41;</span>
  record.<span style="color:#9900CC;">save</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>That&#8217;s pretty awesome; now how can I export that stuff in the database back out to Excel again?</p>
<p>Lets use Ruport, the Ruby report gem!</p>
<pre>
sudo gem install acts_as_reportable</pre>
<p>Toss the require statement somewhere obvious (like environment.rb or above the model you want to export), and put &#8216;acts_as_reportable&#8217; in your model declaration.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'ruport'</span>
<span style="color:#9966CC; font-weight:bold;">class</span> User &lt; <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  acts_as_reportable
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now I can do this kind of stuff to export to a csv file (again with script/console, but a migration should work equally well):</p>
<p>content = User.report_table.as(:csv) # convert your model table to CSV</p>
<p>or</p>

<div class="wp_syntax"><div class="code"><pre class="ruby">content = User.<span style="color:#9900CC;">report_table_by_sql</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;SELECT name, address, email FROM users&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">as</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:csv</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Then write that to a file like so:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby">file = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{RAILS_ROOT}/report.csv&quot;</span>, <span style="color:#996600;">&quot;w&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;"># open file</span>
file.<span style="color:#CC0066; font-weight:bold;">print</span><span style="color:#006600; font-weight:bold;">&#40;</span>content<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;"># print that csv content to the open file</span>
file.<span style="color:#9900CC;">close</span>          <span style="color:#008000; font-style:italic;"># close the file</span></pre></div></div>

<p>Open that CSV file with Excel and amaze the sales team, your boss, or whoever.</p>
<p>This is a narrow view of what we can do with FasterCSV and Ruport, but I&#8217;m sure you can see how you could build out a format.csv in a respond_to block in a Rails controller, or have a setter in your model that sucks in an uploaded CSV to create some records.</p>
<p>These are some pretty great libraries, and I&#8217;m very glad they were able to help me load, combine, query and output some data I&#8217;d been working with in a pinch.</p>
<p>I hope this post serves to help someone else in a similar situation.</p>
]]></content:encoded>
			<wfw:commentRss>http://unixmonkey.net/?feed=rss2&amp;p=23</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Losing nerd cred. Sold my Commodore 128.</title>
		<link>http://unixmonkey.net/?p=22</link>
		<comments>http://unixmonkey.net/?p=22#comments</comments>
		<pubDate>Fri, 25 Apr 2008 00:57:59 +0000</pubDate>
		<dc:creator>unixmonkey</dc:creator>
				<category><![CDATA[oldschool]]></category>
		<category><![CDATA[rambling]]></category>

		<guid isPermaLink="false">http://unixmonkey.net/?p=22</guid>
		<description><![CDATA[Sure, I haven&#8217;t even turned it on in more than 5 years, and I certainly didn&#8217;t use it very much back then either.  Its been sitting in the bottom of the storage closet doing no one any good, yet it pains me just a bit to let it go.
Not because I won&#8217;t ever be [...]]]></description>
			<content:encoded><![CDATA[<p>Sure, I haven&#8217;t even turned it on in more than 5 years, and I certainly didn&#8217;t use it very much back then either.  Its been sitting in the bottom of the storage closet doing no one any good, yet it pains me just a bit to let it go.</p>
<p><img src="http://www.unixmonkey.net/Commodore/2008%20Feb%2022%20007.tn.jpg" alt="Commodore 128" align="right" height="188" width="250" />Not because I won&#8217;t ever be able to turn it on again, as it was pretty likely I never again would, but because just having it gave me a small sense of &#8220;Hey, I was there. In that short time where computing had been pushed into the living rooms before it was practical, before the internet as we know it existed, where operating the computer was only a few steps away from programming it.&#8221;</p>
<p>The Commodore 128 was a gift to me from a lawyer who also hadn&#8217;t used it in years, but used it as a high-end word processor, as the backspace keys on typewriters left a tell-tale sign that you had definitely erased something (and with a pocketknife, you could probably tell what).</p>
<p>It wasn&#8217;t my first Commodore, though. I got a secondhand Vic-20 when I was about 8. It came with a manual that was little more than a &#8220;How to program basic&#8221; with some sample code to write some simple games, and some atari-like cartridges with games like &#8220;space invaders&#8221;, and &#8220;adventure&#8221;.  I was a big fan of the text-based games.  I later ended up tearing it apart to check out its innards, and left it broken for too long that circuit boards and small parts went missing.</p>
<p>I remember getting in trouble for &#8220;hacking&#8221; in school the first time we were taken to the new computer lab equipped with early apple&#8217;s running basic, and I had instructed the computer to run an infinite loop of the below program I had learned from my trusty Commodore manual.</p>
<pre>10 PRINT "TOMMY STINKS"
20 GOTO 10</pre>
<p>I had a friend whose father was an avid computer geek in these mid-to-late 80&#8217;s days, who would pirate video games by tuning his ham-radio to a station that broadcast the analog signal he could tape onto a cassette he could read back into the computer.</p>
<p>I don&#8217;t know if I&#8217;m reminiscing, or just trying to hold on to the memory of the way things were because they were so drastically different from today.  The information economy and the internet as we know it has forever changed the way we work, play, and live.</p>
<p>Anyhow, I&#8217;ll miss the Commodore all the same; but I&#8217;m happy it found a new home, freed up some of my closet space, and helped me put down the deposit on my new apartment.</p>
<p>I took a bunch of pictures before putting it up on eBay, you can see them all here: <a href="http://unixmonkey.net/Commodore/">http://unixmonkey.net/Commodore/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://unixmonkey.net/?feed=rss2&amp;p=22</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Overkill Email Obfuscation with Ruby and Javascript</title>
		<link>http://unixmonkey.net/?p=20</link>
		<comments>http://unixmonkey.net/?p=20#comments</comments>
		<pubDate>Thu, 13 Mar 2008 00:44:14 +0000</pubDate>
		<dc:creator>unixmonkey</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[encryption]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://unixmonkey.net/?p=20</guid>
		<description><![CDATA[The web is a generally free and open place for all types of communication, but if you put your email address on 1 website, you can expect an email-harvesting robot spider to find that address and send it to its spammer overlords.
Once on a spammer&#8217;s list, you can expect to get all kinds of interesting [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://unixmonkey.net/blog/wp-content/uploads/2008/03/runaway_spiders.jpg" title="Robot Spiders from Runaway"><img src="http://unixmonkey.net/blog/wp-content/uploads/2008/03/runaway_spiders.thumbnail.jpg" alt="Robot Spiders from Runaway" align="right" /></a>The web is a generally free and open place for all types of communication, but if you put your email address on 1 website, you can expect an email-harvesting robot spider to find that address and send it to its spammer overlords.</p>
<p>Once on a spammer&#8217;s list, you can expect to get all kinds of interesting stock tips, products to enhance your manhood, and friendly letters from Nigerian diplomats.</p>
<p>If you simply have too little to do in the day, this can be a great way to meet new people and start a career in day trading. However, some of us are just too darn busy to stop what we are doing every 2/3rds of a second to check our email; but still need it for keeping in contact with friends, family, and business contacts.</p>
<p>From a few tips pulled from the web, I set to create a nice link helper for Ruby / Rails intended to display email links that work indistinguishably from regular mailto: links, and even gracefully downgrade for users without javascript.</p>
<p>Lets not even display the email address on the page at all, and use a little javascript to render the email address after the fact by breaking it up and putting it back together with javascript.</p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#008000; font-style:italic;"># Takes in an email address and (optionally) anchor text,</span>
<span style="color:#008000; font-style:italic;"># its purpose is to obfuscate email addresses so spiders and</span>
<span style="color:#008000; font-style:italic;"># spammers can't harvest them.</span>
<span style="color:#9966CC; font-weight:bold;">def</span> js_antispam_email_link<span style="color:#006600; font-weight:bold;">&#40;</span>email, linktext=email<span style="color:#006600; font-weight:bold;">&#41;</span>
    user, domain = email.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'@'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#008000; font-style:italic;"># if linktext wasn't specified, throw email address builder into js document.write statement</span>
    linktext = <span style="color:#996600;">&quot;'+'#{user}'+'@'+'#{domain}'+'&quot;</span> <span style="color:#9966CC; font-weight:bold;">if</span> linktext == email 
    out =  <span style="color:#996600;">&quot;&lt;noscript&gt;#{linktext} #{user}(at)#{domain}&lt;/noscript&gt;<span style="color:#000099;">\n</span>&quot;</span>
    out += <span style="color:#996600;">&quot;&lt;script language='javascript'&gt;<span style="color:#000099;">\n</span>&quot;</span>
    out += <span style="color:#996600;">&quot;  &lt;!--<span style="color:#000099;">\n</span>&quot;</span>
    out += <span style="color:#996600;">&quot;    string = '#{user}'+'@'+'#{domain}';<span style="color:#000099;">\n</span>&quot;</span>
    out += <span style="color:#996600;">&quot;    document.write('&lt;a href='+'ma'+'il'+'to:'+ string +'&gt;#{linktext}&lt;/a&gt;'); <span style="color:#000099;">\n</span>&quot;</span>
    out += <span style="color:#996600;">&quot;  //--&gt;<span style="color:#000099;">\n</span>&quot;</span>
    out += <span style="color:#996600;">&quot;&lt;/script&gt;<span style="color:#000099;">\n</span>&quot;</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> out
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This is probably good enough for 90% of those robots, but you know if one spammer gets your address, he will likely share (or sell) your email to all his friends. The weak spot in this looks like the noscript version, lets fuzz that up a bit by converting to HTML character entities.</p>
<p>One of the earliest and simplest ways to obfuscate an email address is by converting each character into its HTML equivalent.  This makes the source look nasty, but will be correctly rendered by the browser that the end-user is none the wiser.</p>
<p>An address like abc@example.com will look like this in the source:</p>

<div class="wp_syntax"><div class="code"><pre class="rails">&amp;<span style="color:#008000; font-style:italic;">#097;&amp;#098;&amp;#099;&amp;#064;&amp;#101;&amp;#120;&amp;#097;&amp;#109;&amp;#112;&amp;#108;&amp;#101;&amp;#046;&amp;#099;&amp;#111;&amp;#109;</span></pre></div></div>

<p>Let&#8217;s build a simple method to convert a plaintext string into something like the above.  I&#8217;m going to cheat and only convert a-z and A-Z and leave @ signs, dots, dashes, etc. alone.</p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#008000; font-style:italic;"># HTML encodes ASCII chars a-z, useful for obfuscating</span>
<span style="color:#008000; font-style:italic;"># an email address from spiders and spammers</span>
<span style="color:#9966CC; font-weight:bold;">def</span> html_obfuscate<span style="color:#006600; font-weight:bold;">&#40;</span>string<span style="color:#006600; font-weight:bold;">&#41;</span>
  output_array = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  lower = %w<span style="color:#006600; font-weight:bold;">&#40;</span>a b c d e f g h i j k l m n o <span style="color:#CC0066; font-weight:bold;">p</span> q r s t u v w x y z<span style="color:#006600; font-weight:bold;">&#41;</span>
  upper = %w<span style="color:#006600; font-weight:bold;">&#40;</span>A B C D E F G H I J K L M N O P Q R S T U V W X Y Z<span style="color:#006600; font-weight:bold;">&#41;</span>
  char_array = string.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  char_array.<span style="color:#5A0A0A; font-weight:bold;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> |char|  
    output = lower.<span style="color:#9900CC;">index</span><span style="color:#006600; font-weight:bold;">&#40;</span>char<span style="color:#006600; font-weight:bold;">&#41;</span> + <span style="color:#006666;">97</span> <span style="color:#9966CC; font-weight:bold;">if</span> lower.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>char<span style="color:#006600; font-weight:bold;">&#41;</span>
    output = upper.<span style="color:#9900CC;">index</span><span style="color:#006600; font-weight:bold;">&#40;</span>char<span style="color:#006600; font-weight:bold;">&#41;</span> + <span style="color:#006666;">65</span> <span style="color:#9966CC; font-weight:bold;">if</span> upper.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>char<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> output
      output_array &lt;&lt; <span style="color:#996600;">&quot;&amp;##{output};&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span> 
      output_array &lt;&lt; char
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#0000FF; font-weight:bold;">return</span> output_array.<span style="color:#9900CC;">join</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>now in our js_antispam_email_link method we can &#8220;encrypt&#8221; the user and domain before sending to the browser like so:</p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#9966CC; font-weight:bold;">def</span> js_antispam_email_link<span style="color:#006600; font-weight:bold;">&#40;</span>email, linktext=email<span style="color:#006600; font-weight:bold;">&#41;</span>
  user, domain = email.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'@'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  user = html_obfuscate<span style="color:#006600; font-weight:bold;">&#40;</span>user<span style="color:#006600; font-weight:bold;">&#41;</span>
  domain = html_obfuscate<span style="color:#006600; font-weight:bold;">&#40;</span>domain<span style="color:#006600; font-weight:bold;">&#41;</span>
  ...</pre></div></div>

<p>Not bad, but many spiders these days can still decode HTML entities and get at that address, so lets build up our defenses a bit more by adding some methods to really screw with those spiders.</p>
<p>We&#8217;ll write a method that encrypts a string with ROT13 and puts that on the webpage, and use some javascript to decrypt that on page display. ROT13 is a really simple cipher where you take characters a-z and shift them by half the alphabet.</p>
<p>This is a really simple one-liner borrowed from <a href="http://www.miranda.org/~jkominek/rot13/ruby/">Jay Komineck</a></p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#008000; font-style:italic;"># Rot13 encodes a string</span>
<span style="color:#9966CC; font-weight:bold;">def</span> rot13<span style="color:#006600; font-weight:bold;">&#40;</span>string<span style="color:#006600; font-weight:bold;">&#41;</span>
  string.<span style="color:#9900CC;">tr</span> <span style="color:#996600;">&quot;A-Za-z&quot;</span>, <span style="color:#996600;">&quot;N-ZA-Mn-za-m&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Lets use this to really beef up our link helper by using some javascript that can decipher this. JS code taken from <a href="http://blog.macromates.com/2006/obfuscating-email-addresses/">Allan Odgaard</a></p>

<div class="wp_syntax"><div class="code"><pre class="javascript">string = <span style="color: #3366CC;">'#{email}'</span>.<span style="color: #006600;">replace</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066FF;">/<span style="color: #66cc66;">&#91;</span>a-zA-Z<span style="color: #66cc66;">&#93;</span>/g</span>, 
  <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>c<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span> 
    <span style="color: #000066; font-weight: bold;">return</span> String.<span style="color: #006600;">fromCharCode</span><span style="color: #66cc66;">&#40;</span>
      <span style="color: #66cc66;">&#40;</span>c &lt;= <span style="color: #3366CC;">'Z'</span> ? <span style="color: #CC0000;">90</span> : <span style="color: #CC0000;">122</span><span style="color: #66cc66;">&#41;</span> &gt;= <span style="color: #66cc66;">&#40;</span>c = c.<span style="color: #006600;">charCodeAt</span><span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #66cc66;">&#41;</span> + <span style="color: #CC0000;">13</span><span style="color: #66cc66;">&#41;</span> ? c : c - <span style="color: #CC0000;">26</span>
    <span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p>Now we&#8217;ve got some pretty strong defense against those pesky robots and by using simple HTML character encoding and lightweight ROT13 ciphering it shouldn&#8217;t be too taxing on your webserver to spit out a page with a few emails on it. Less sophisticated browsers still get the contact info and everyone is a little bit happier to come home to a (relatively) clean inbox.</p>
<p>Here&#8217;s the whole shebang put together, put this in application_helper.rb if using rails:</p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#008000; font-style:italic;"># Rot13 encodes a string</span>
<span style="color:#9966CC; font-weight:bold;">def</span> rot13<span style="color:#006600; font-weight:bold;">&#40;</span>string<span style="color:#006600; font-weight:bold;">&#41;</span>
  string.<span style="color:#9900CC;">tr</span> <span style="color:#996600;">&quot;A-Za-z&quot;</span>, <span style="color:#996600;">&quot;N-ZA-Mn-za-m&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># HTML encodes ASCII chars a-z, useful for obfuscating</span>
<span style="color:#008000; font-style:italic;"># an email address from spiders and spammers</span>
<span style="color:#9966CC; font-weight:bold;">def</span> html_obfuscate<span style="color:#006600; font-weight:bold;">&#40;</span>string<span style="color:#006600; font-weight:bold;">&#41;</span>
  output_array = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  lower = %w<span style="color:#006600; font-weight:bold;">&#40;</span>a b c d e f g h i j k l m n o <span style="color:#CC0066; font-weight:bold;">p</span> q r s t u v w x y z<span style="color:#006600; font-weight:bold;">&#41;</span>
  upper = %w<span style="color:#006600; font-weight:bold;">&#40;</span>A B C D E F G H I J K L M N O P Q R S T U V W X Y Z<span style="color:#006600; font-weight:bold;">&#41;</span>
  char_array = string.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  char_array.<span style="color:#5A0A0A; font-weight:bold;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> |char|  
    output = lower.<span style="color:#9900CC;">index</span><span style="color:#006600; font-weight:bold;">&#40;</span>char<span style="color:#006600; font-weight:bold;">&#41;</span> + <span style="color:#006666;">97</span> <span style="color:#9966CC; font-weight:bold;">if</span> lower.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>char<span style="color:#006600; font-weight:bold;">&#41;</span>
    output = upper.<span style="color:#9900CC;">index</span><span style="color:#006600; font-weight:bold;">&#40;</span>char<span style="color:#006600; font-weight:bold;">&#41;</span> + <span style="color:#006666;">65</span> <span style="color:#9966CC; font-weight:bold;">if</span> upper.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>char<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> output
      output_array &lt;&lt; <span style="color:#996600;">&quot;&amp;##{output};&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span> 
      output_array &lt;&lt; char
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#0000FF; font-weight:bold;">return</span> output_array.<span style="color:#9900CC;">join</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Takes in an email address and (optionally) anchor text,</span>
<span style="color:#008000; font-style:italic;"># its purpose is to obfuscate email addresses so spiders and</span>
<span style="color:#008000; font-style:italic;"># spammers can't harvest them.</span>
<span style="color:#9966CC; font-weight:bold;">def</span> js_antispam_email_link<span style="color:#006600; font-weight:bold;">&#40;</span>email, linktext=email<span style="color:#006600; font-weight:bold;">&#41;</span>
  user, domain = email.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'@'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  user   = html_obfuscate<span style="color:#006600; font-weight:bold;">&#40;</span>user<span style="color:#006600; font-weight:bold;">&#41;</span>
  domain = html_obfuscate<span style="color:#006600; font-weight:bold;">&#40;</span>domain<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#008000; font-style:italic;"># if linktext wasn't specified, throw encoded email address builder into js document.write statement</span>
  linktext = <span style="color:#996600;">&quot;'+'#{user}'+'@'+'#{domain}'+'&quot;</span> <span style="color:#9966CC; font-weight:bold;">if</span> linktext == email 
  rot13_encoded_email = rot13<span style="color:#006600; font-weight:bold;">&#40;</span>email<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;"># obfuscate email address as rot13</span>
  out =  <span style="color:#996600;">&quot;&lt;noscript&gt;#{linktext}&lt;br/&gt;&lt;small&gt;#{user}(at)#{domain}&lt;/small&gt;&lt;/noscript&gt;<span style="color:#000099;">\n</span>&quot;</span> <span style="color:#008000; font-style:italic;"># js disabled browsers see this</span>
  out += <span style="color:#996600;">&quot;&lt;script language='javascript'&gt;<span style="color:#000099;">\n</span>&quot;</span>
  out += <span style="color:#996600;">&quot;  &lt;!--<span style="color:#000099;">\n</span>&quot;</span>
  out += <span style="color:#996600;">&quot;    string = '#{rot13_encoded_email}'.replace(/[a-zA-Z]/g, function(c){ return String.fromCharCode((c &lt;= 'Z' ? 90 : 122) &gt;= (c = c.charCodeAt(0) + 13) ? c : c - 26);});<span style="color:#000099;">\n</span>&quot;</span>
  out += <span style="color:#996600;">&quot;    document.write('&lt;a href='+'ma'+'il'+'to:'+ string +'&gt;#{linktext}&lt;/a&gt;'); <span style="color:#000099;">\n</span>&quot;</span>
  out += <span style="color:#996600;">&quot;  //--&gt;<span style="color:#000099;">\n</span>&quot;</span>
  out += <span style="color:#996600;">&quot;&lt;/script&gt;<span style="color:#000099;">\n</span>&quot;</span>
  <span style="color:#0000FF; font-weight:bold;">return</span> out
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>I hope this helps out somebody out there, please leave a comment if you have any suggestions.</p>
]]></content:encoded>
			<wfw:commentRss>http://unixmonkey.net/?feed=rss2&amp;p=20</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Getting attachment_fu to play nice with acts_as_versioned</title>
		<link>http://unixmonkey.net/?p=18</link>
		<comments>http://unixmonkey.net/?p=18#comments</comments>
		<pubDate>Sun, 10 Feb 2008 01:15:29 +0000</pubDate>
		<dc:creator>unixmonkey</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[Acts_as_versioned]]></category>
		<category><![CDATA[Attachment_fu]]></category>

		<guid isPermaLink="false">http://unixmonkey.net/?p=18</guid>
		<description><![CDATA[If you&#8217;ve ever wanted to keep track of revisions to document files or images in your Rails app, you are likely to want to use Acts_as_versioned, which is the authority on versioning database records, and Attachment_fu, which is the authority on uploading files with Rails.
The problem is that they don&#8217;t know about each other and [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve ever wanted to keep track of revisions to document files or images in your Rails app, you are likely to want to use Acts_as_versioned, which is the authority on versioning database records, and Attachment_fu, which is the authority on uploading files with Rails.</p>
<p>The problem is that they don&#8217;t know about each other and will step on each other&#8217;s toes without some changes. This article serves as a quick introduction to each, and shows how to make the two plugins get along like best friends.</p>
<p><a href="http://svn.techno-weenie.net/projects/plugins/acts_as_versioned/" title="techno-weenie.net">Acts_as_versioned</a> was written by Rails Core Team member Rick Olsen (who also wrote <a href="http://svn.techno-weenie.net/projects/plugins/attachment_fu/" title="svn.techno-weenie.net">attachment_fu</a> and <a href="http://svn.techno-weenie.net/projects/plugins/restful_authentication/" title="svn.techno-weenie.net">Restful_authentication</a> among others) that essentially makes a mirror table of the one you want to version, and keeps every version of the record you are updating.</p>
<p>Say I have a document table with fields like this:</p>
<table>
<tr>
<td>id</td>
<td>title</td>
<td>description</td>
</tr>
<tr>
<td>1</td>
<td>rep08</td>
<td>2008 report</td>
</tr>
</table>
<p>Acts_as_versioned will add a column “version”, and a separate table “document_versions”.</p>
<table>
<tr>
<td>id</td>
<td>title</td>
<td>description</td>
<td>version</td>
</tr>
<tr>
<td>1</td>
<td>rep08</td>
<td>2008 report</td>
<td>1</td>
</tr>
</table>
<p>The document_versions table will look a bit like this</p>
<table>
<tr>
<td>id</td>
<td>document_id</td>
<td>title</td>
<td>description</td>
<td>version</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>rep08</td>
<td>2008 report</td>
<td>1</td>
</tr>
</table>
<p>Setting up acts_as_versioned is pretty simple, I got most of my introduction to it from <a href="http://www.urbanhonking.com/ideasfordozens/archives/2006/02/learns_to_use_a_1.html">urbanhonking.com</a></p>
<p>Now every time you update the original document, the changes are saved in your main documents table, and the version column is incremented by 1.</p>
<p>After a few edits of the document, you’ll see the versioning information in the Document_versions table add up.</p>
<table>
<tr>
<td>id</td>
<td>document_id</td>
<td>title</td>
<td>description</td>
<td>version</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>rep08</td>
<td>2008 report</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>1</td>
<td>rep08</td>
<td>2008 report changed</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>1</td>
<td>rep08 chgd</td>
<td>2008 report changed</td>
<td>3</td>
</tr>
</table>
<p>Great! We can now use some of acts_as_versioned’s built-in methods for determining if there are older versions, and be able to view or even revert to them.</p>
<p>Now lets add the ability to upload a file to attach to a document record with attachment_fu.</p>
<p>Attachment_fu is another plugin that makes uploading files and keeping track of them in the database relatively simple.</p>
<p>A good intro to attachment_fu can be found on <a href="http://clarkware.com/cgi/blosxom/2007/02/24">Mike Clark’s blog</a></p>
<p>Attachment_fu would require a few changes to our documents table:</p>
<table>
<tr>
<td>id</td>
<td>title</td>
<td>description</td>
<td>version</td>
<td>filename</td>
<td>content_type</td>
<td>size</td>
</tr>
<tr>
<td>1</td>
<td>rep08</td>
<td>2008 report</td>
<td>1</td>
<td>rep08.jpg</td>
<td>image/jpeg</td>
<td>2854</td>
</tr>
</table>
<p>Don’t forget to add the same fields to your documents_versions table, too.</p>
<p>Once we’ve added the right file fields to the new and edit forms, and image_tag or download link on the show view, we’ve got working file uploads. Nice.</p>
<p>Try to edit a record by attaching a new file, the new file is displayed and the record is preserved as an older version in the versioned table.  But if you try to view the old version&#8230;wait a minute? Where did my version 1 file go!</p>
<p>That’s right, attachment_fu deletes the old file when you add a new one (as it should if you aren’t versioning your data). Attachment_fu’s rename_file method is the one responsible for deleting (or renaming) the old file when a new one is added, so lets monkeypatch that in our model to not do anything.</p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#9966CC; font-weight:bold;">def</span> rename_file
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now, it will only overwrite the file if the filename is the same. Lets store each version in its own folder to keep them from clobbering each other by monkey-patching the path files get written to in our model also:</p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#9966CC; font-weight:bold;">def</span> attachment_path_id
  <span style="color:#996600;">&quot;/#{id}/v#{version}/&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">def</span> partitioned_path<span style="color:#006600; font-weight:bold;">&#40;</span>*args<span style="color:#006600; font-weight:bold;">&#41;</span>
  attachment_path_id + args.<span style="color:#5A0A0A; font-weight:bold;">to_s</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This changes the public path from /0000/0001/rep08.jpg to /1/v1/rep08.jpg</p>
<p>Now, if we want to display the image, we cannot use the ‘public_filename’ method, because it is only given to the Document model, and not the Document_Version model.</p>
<p>That’s okay, because with our new path arrangement, we can reliably predict where the old versions of the files will be kept.  You can show them with some code similar to this in your views:</p>

<div class="wp_syntax"><div class="code"><pre class="rails">&lt;% <span style="color:#9966CC; font-weight:bold;">for</span> version <span style="color:#9966CC; font-weight:bold;">in</span> <span style="color:#0066ff; font-weight:bold;">@document</span>.<span style="color:#9900CC;">versions</span> %&gt;
&nbsp;
  Version &lt;%= version.<span style="color:#9900CC;">version</span> %&gt;
  &lt;%= <span style="color:#5A0A0A; font-weight:bold;">image_tag</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;/documents/#{@document.id}/v#{version.version/&quot;</span> + version.<span style="color:#9900CC;">filename</span><span style="color:#006600; font-weight:bold;">&#41;</span> %&gt;
  &lt;hr /&gt;
&nbsp;
&lt;% <span style="color:#9966CC; font-weight:bold;">end</span> %&gt;</pre></div></div>

<p>Now, when we delete a record, attachment_fu only knows about the current document, and will leave behind orphaned files and folders from the old versions.  Lets fix that by having it get rid of the document id folder.</p>
<p>Rails reserves some special methods (callbacks) for performing actions before or after other major actions, lets tap into that by defining a method that will magically get called every time we delete a record.</p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#9966CC; font-weight:bold;">def</span> after_destroy
  <span style="color:#CC00FF; font-weight:bold;">FileUtils</span>.<span style="color:#9900CC;">rm_rf</span><span style="color:#006600; font-weight:bold;">&#40;</span>RAILS_ROOT + <span style="color:#996600;">&quot;/public/documents/#{id}/&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This translates into the shell command rm -rf and deletes our ID directory and everything inside it.</p>
<p>Hooray!</p>
<p>As a wrap up, lets look at our complete Document model:</p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#9966CC; font-weight:bold;">class</span> Document &lt; <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  acts_as_versioned
  has_attachment <span style="color:#ff3333; font-weight:bold;">:storage</span> =&gt; <span style="color:#ff3333; font-weight:bold;">:file_system</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> rename_file
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> attachment_path_id
    <span style="color:#996600;">&quot;/#{id}/v#{version}/&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> partitioned_path<span style="color:#006600; font-weight:bold;">&#40;</span>*args<span style="color:#006600; font-weight:bold;">&#41;</span>
    attachment_path_id + args.<span style="color:#5A0A0A; font-weight:bold;">to_s</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> after_destroy
    <span style="color:#CC00FF; font-weight:bold;">FileUtils</span>.<span style="color:#9900CC;">rm_rf</span><span style="color:#006600; font-weight:bold;">&#40;</span>RAILS_ROOT + <span style="color:#996600;">&quot;/public/documents/#{id}/&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> id
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>I&#8217;ve whipped up a sample Rails app demonstrating the points and code in this article. It uses Rails 2.0.2 with the sqlite3 database.</p>
<p>Download it here: <a href="http://unixmonkey.net/blog/wp-content/uploads/2008/02/attachments_versioned.zip" title="Attachments_versioned">Attachments_versioned (240kb .zip)</a></p>
<p>I hope this saves some work for someone who wants to leverage these two excellent plugins by Rick Olsen (<a href="http://weblog.techno-weenie.net/" title="weblog.techno-weenie.net">technoweenie</a>) on the same model without having them fight too much.</p>
]]></content:encoded>
			<wfw:commentRss>http://unixmonkey.net/?feed=rss2&amp;p=18</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Autotest with custom growl notifications in Leopard</title>
		<link>http://unixmonkey.net/?p=15</link>
		<comments>http://unixmonkey.net/?p=15#comments</comments>
		<pubDate>Thu, 17 Jan 2008 19:47:17 +0000</pubDate>
		<dc:creator>unixmonkey</dc:creator>
				<category><![CDATA[OSX]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Testing OSX]]></category>

		<guid isPermaLink="false">http://unixmonkey.net/?p=15</guid>
		<description><![CDATA[Autotest is part of the ZenTest suite for testing ruby and rails apps.  Instead of running &#8216;rake test&#8217; every time you want to run your tests, simply open another tab in your terminal, browse to your rails project directory and run &#8216;autotest&#8217;. It will run your test suite and sit there waiting for any [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://nubyonrails.com/articles/autotest-rails" title="nubyonrails.com">Autotest</a> is part of the <a href="http://www.zenspider.com/ZSS/Products/ZenTest/" title="zenspider.com">ZenTest</a> suite for testing ruby and rails apps.  Instead of running &#8216;rake test&#8217; every time you want to run your tests, simply open another tab in your terminal, browse to your rails project directory and run &#8216;autotest&#8217;. It will run your test suite and sit there waiting for any file to be modified.  When you edit any file in your rails project, autotest will automatically run your tests again.</p>
<p>To install ZenTest and autotest, open a terminal and run &#8217;sudo gem install ZenTest&#8217;.</p>
<p>This is great, awesome even. I don&#8217;t want to understate how useful this is, its like breathing when doing test-driven development, but when I&#8217;m coding, I&#8217;ll often have a different terminal up front with a script/console shell or tail-ing the development log. I want my tests to get in my face when something goes wrong.</p>
<p>The way to do this is with <a href="http://growl.info">Growl</a> on OSX, <a href="http://fullphat.net">Snarl</a> for Windows, or several other similar pop-up notification apps.</p>
<p>As of this writing, the latest version of Growl is 1.1.2, the ZenTest Gem is 3.8.0, and OSX Leopard is 10.5.1. I installed Leopard as a clean install.</p>
<p>After downloading and installing Growl, while the .dmg is still mounted, open a terminal and run &#8216;/Volumes/Growl\ 1.1.2/Extras/growlnotify/install.sh&#8217;.</p>
<p>This will put a commandline tool called &#8216;growlnotify&#8217; in your /usr/local/bin dir that is used to pop up those messages. Now you can use a text editor to create a ~/.autotest file.</p>
<p>Lets start simple and check that growl is working with autotest, add this line to your .autotest file:</p>
<p>require &#8216;autotest/growl&#8217;</p>
<p>Then save, and go into your Rails project and run &#8216;autotest&#8217;</p>
<p>If all the pieces were installed right, you should get some nice popups when you run autotest and each time you modify a file in your rails project directory.</p>
<p>Lets pretty this up a bit by over-riding the Autotest::Growl module in our .autotest file.  I&#8217;ve pretty much copied this verbatim from /Library/Ruby/Gems/1.8/gems/ZenTest-3.8.0/lib/autotest/growl.rb<br />
only I&#8217;ve added an image directive to the autotest hooks, a nice red rails logo for test failures, and a green one for test passes, then changed the growl method to substitute my images into the growlnotify command. Be sure the modify the image paths for your images directory.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby"><span style="color:#008000; font-style:italic;"># ~.autotest</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'autotest/redgreen'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'autotest/growl'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> <span style="color:#6666ff; font-weight:bold;">Autotest::Growl</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">growl</span> title, msg, img=<span style="color:#996600;">&quot;/Applications/Mail.app/Contents/Resources/Caution.tiff&quot;</span>, pri=<span style="color:#006666;">0</span>
    title += <span style="color:#996600;">&quot; in #{Dir.pwd}&quot;</span>
    msg += <span style="color:#996600;">&quot; at #{Time.now.strftime(&quot;</span>%I:%M %p<span style="color:#996600;">&quot;)}&quot;</span>
    <span style="color:#CC0066; font-weight:bold;">system</span> <span style="color:#996600;">&quot;growlnotify -n autotest --image #{img} -p #{pri} -m #{msg.inspect} #{title}&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  Autotest.<span style="color:#9900CC;">add_hook</span> <span style="color:#ff3333; font-weight:bold;">:run</span> <span style="color:#9966CC; font-weight:bold;">do</span>  |at|
     growl <span style="color:#996600;">&quot;autotest running&quot;</span>, <span style="color:#996600;">&quot;Started&quot;</span>
   <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
   Autotest.<span style="color:#9900CC;">add_hook</span> <span style="color:#ff3333; font-weight:bold;">:red</span> <span style="color:#9966CC; font-weight:bold;">do</span> |at|
     img = <span style="color:#996600;">&quot;/Users/djones/.autotest_images/rails_fail.png&quot;</span>
     growl <span style="color:#996600;">&quot;Tests Failed&quot;</span>, <span style="color:#996600;">&quot;#{at.files_to_test.size} tests failed&quot;</span>, img, <span style="color:#006666;">2</span>
   <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
   Autotest.<span style="color:#9900CC;">add_hook</span> <span style="color:#ff3333; font-weight:bold;">:green</span> <span style="color:#9966CC; font-weight:bold;">do</span> |at|
     img = <span style="color:#996600;">&quot;/Users/djones/.autotest_images/rails_ok.png&quot;</span>
     growl <span style="color:#996600;">&quot;Tests Passed&quot;</span>, <span style="color:#996600;">&quot;Tests passed&quot;</span>, img, <span style="color:#006666;">-2</span> <span style="color:#9966CC; font-weight:bold;">if</span> at.<span style="color:#9900CC;">tainted</span>
   <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
   Autotest.<span style="color:#9900CC;">add_hook</span> <span style="color:#ff3333; font-weight:bold;">:all_good</span> <span style="color:#9966CC; font-weight:bold;">do</span> |at|
     img = <span style="color:#996600;">&quot;/Users/djones/.autotest_images/rails_fail.png&quot;</span>
     growl <span style="color:#996600;">&quot;Tests Passed&quot;</span>, <span style="color:#996600;">&quot;All tests passed&quot;</span>, img, <span style="color:#006666;">-2</span> <span style="color:#9966CC; font-weight:bold;">if</span> at.<span style="color:#9900CC;">tainted</span>
   <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now create a .autotest_images folder in your home directory and put these images in there (I got them from <a href="http://blog.internautdesign.com/2006/11/12/autotest-growl-goodness" title="blog.internautdesign.com">here</a>), or you can use your own.</p>
<p><a href="http://unixmonkey.net/blog/wp-content/uploads/2008/01/rails_ok.png" title="rails_ok.png"><img src="http://unixmonkey.net/blog/wp-content/uploads/2008/01/rails_ok.png" alt="rails_ok.png" /></a><a href="http://unixmonkey.net/blog/wp-content/uploads/2008/01/rails_fail.png" title="rails_fail.png"><img src="http://unixmonkey.net/blog/wp-content/uploads/2008/01/rails_fail.png" alt="rails_fail.png" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://unixmonkey.net/?feed=rss2&amp;p=15</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Thin: slimmer and faster than mongrel</title>
		<link>http://unixmonkey.net/?p=13</link>
		<comments>http://unixmonkey.net/?p=13#comments</comments>
		<pubDate>Sat, 05 Jan 2008 16:28:26 +0000</pubDate>
		<dc:creator>unixmonkey</dc:creator>
				<category><![CDATA[Deployment]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://unixmonkey.net/?p=13</guid>
		<description><![CDATA[We all know mongrel is the bees knees when it comes to serving Rails or Merb apps, even if its creator had a meltdown.
But there is a new kid on the block named thin that claims to run Rails apps almost twice as fast as mongrel. Check the graph.

A simple &#8216;gem install thin&#8217; and going [...]]]></description>
			<content:encoded><![CDATA[<p>We all know <a href="http://mongrel.rubyforge.org/" title="mongrel.rubyforge.org">mongrel</a> is the bees knees when it comes to serving Rails or <a href="http://merbivore.com/" title="merbivore.com">Merb</a> apps, even if <a href="http://www.zedshaw.com/rants/rails_is_a_ghetto.html" title="zedshaw.com">its creator had a meltdown</a>.</p>
<p>But there is a new kid on the block named <a href="http://code.macournoyer.com/thin/" title="code.macournoyer.com/thin/">thin</a> that claims to run Rails apps almost twice as fast as mongrel. Check the graph.</p>
<p><a href="http://unixmonkey.net/blog/wp-content/uploads/2008/01/chart.png" title="Thin vs mongrel vs webrick comparison chart"><img src="http://unixmonkey.net/blog/wp-content/uploads/2008/01/chart.png" alt="Thin vs mongrel vs webrick comparison chart" /></a></p>
<p>A simple &#8216;gem install thin&#8217; and going into your rails app and issuing &#8216;thin start&#8217; is enough to get you shedding weight.</p>
<p>This is definitely something I&#8217;ll be playing with for the next few days.</p>
]]></content:encoded>
			<wfw:commentRss>http://unixmonkey.net/?feed=rss2&amp;p=13</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
