<?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>Involution &#187; Ruby on Rails</title>
	<atom:link href="http://involution.com/category/ruby-on-rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://involution.com</link>
	<description>Tony Perrie&#039;s Weblog</description>
	<lastBuildDate>Fri, 19 Aug 2011 19:46:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Upgrading to Rails 3.0.8</title>
		<link>http://involution.com/2011/06/08/upgrading-to-rails-3-0-9-rc1/</link>
		<comments>http://involution.com/2011/06/08/upgrading-to-rails-3-0-9-rc1/#comments</comments>
		<pubDate>Thu, 09 Jun 2011 00:16:24 +0000</pubDate>
		<dc:creator>Tony Perrie</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://involution.com/?p=1436</guid>
		<description><![CDATA[This was fixed in 3.0.9. If you&#8217;re using js views and partial html replacements, Rails 3.0.8 was totally broken. Right after the 3.0.8 release, 3.0.9rc1 was released which partially addresses the problem. But, after upgrading, you have to wrap every escape_javascript call with raw() if you want your javascript to replace HTML. This was absolutely [...]]]></description>
			<content:encoded><![CDATA[<p><b>This was fixed in 3.0.9</b>. </p>
<p>If you&#8217;re using js views and partial html replacements, Rails 3.0.8 was totally broken.  Right after the 3.0.8 release, 3.0.9rc1 was released which partially addresses the problem.  But, after upgrading, you have to wrap every escape_javascript call with raw() if you want your javascript to replace HTML.  This was absolutely _not_ the case with 3.0.7.  </p>
<p>So, <code>escape_javascript('&lt;img src="lolcat.jpg" /&gt;')</code> becomes <code>raw(escape_javascript('&lt;img src="lolcat.jpg" /&gt;'))</code>.</p>
<p>This can also be accomplished by monkeypatching escape_javascript like this in application.rb. </p>
<pre><code>def escape_javascript_with_workaround(javascript)
  raw(escape_javascript_without_workaround(javascript))
end

alias_method_chain :escape_javascript, :workaround
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://involution.com/2011/06/08/upgrading-to-rails-3-0-9-rc1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using FORCE INDEX with Rails</title>
		<link>http://involution.com/2010/04/04/using-force-index-with-rails/</link>
		<comments>http://involution.com/2010/04/04/using-force-index-with-rails/#comments</comments>
		<pubDate>Mon, 05 Apr 2010 02:16:19 +0000</pubDate>
		<dc:creator>Tony Perrie</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://involution.com/?p=1277</guid>
		<description><![CDATA[Avoiding a full table scan when performing a MySQL query with both an ORDER and a WHERE clause is more difficult than you would think. This is especially true if you&#8217;re only selecting a subset of the table from a foreign key. First off, you must add a compound index with the order column first. [...]]]></description>
			<content:encoded><![CDATA[<p>Avoiding a full table scan when performing a MySQL query with both an <code>ORDER</code> and a <code>WHERE</code> clause is more difficult than you would think.  This is especially true if you&#8217;re only selecting a subset of the table from a foreign key.</p>
<p>First off, you must add a compound index with the order column first.  If the index is constructed with the column used to order the table last, the index will not work as expected. </p>
<pre>add_index :posts [:created_at, :blog_id]</pre>
<p>Next, you have to specify the index in the ActiveRecord call with <code>USE INDEX</code> or <code>FORCE INDEX</code> or else MySQL will not use it by default.</p>
<pre>named_scope :ordered, {
            :from => 'events FORCE INDEX (index_posts_on_created_at_and_blog_id)',
            :order => 'created_at DESC' }</pre>
<p>The Rails <code>add_index</code> method names the MySQL index as <code>index_table_name_on_column_1_at_and_column_2</code> by default.  If you want to list the indexes available for your database, you can perform the query: <code>SHOW INDEXES</code> to investigate.  </p>
<p>It&#8217;s possible to test the index by copying the MySQL queries from your Rails log and prefixing them with <code>EXPLAIN</code> or <code>EXPLAIN EXTENDED</code>.  Using either of these will display the number of rows searched for each query.  If your query is scanning more rows than you&#8217;ve selected, that is a clear sign that the index your using is either not being used or incorrect.</p>
]]></content:encoded>
			<wfw:commentRss>http://involution.com/2010/04/04/using-force-index-with-rails/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rails Join Query For Empty Right Tables</title>
		<link>http://involution.com/2010/02/04/rails-join-query-for-empty-right-tables/</link>
		<comments>http://involution.com/2010/02/04/rails-join-query-for-empty-right-tables/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 00:38:17 +0000</pubDate>
		<dc:creator>Tony Perrie</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Query]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Rails2]]></category>
		<category><![CDATA[RubyOnRails]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://involution.com/?p=1266</guid>
		<description><![CDATA[Say you wanted to select all the accounts from your applications with no associated users. You&#8217;d think this would be obvious, however I racked my brain for a few minutes thinking of a Rails-way of sorting this out. The good news is with Rails 2.2 or later, it can be accomplished like this thanks to [...]]]></description>
			<content:encoded><![CDATA[<p>Say you wanted to select all the accounts from your applications with no associated users.  You&#8217;d think this would be obvious, however I racked my brain for a few minutes thinking of a Rails-way of sorting this out.  </p>
<p>The good news is with Rails 2.2 or later, it can be accomplished like this thanks to join hashes.</p>
<pre><code>Company.find(:all, :include => :users,
             :conditions => { :users => { :id => nil } })
</code></pre>
<p>Before Rails 2.2, you would have had to resort to the following.</p>
<pre><code>Company.find(:all, :include => :users,
             :conditions => "users.id IS NULL")
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://involution.com/2010/02/04/rails-join-query-for-empty-right-tables/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Interactive Memcached Debugging with Rails</title>
		<link>http://involution.com/2009/06/20/interactive-memcached-debugging-with-rails/</link>
		<comments>http://involution.com/2009/06/20/interactive-memcached-debugging-with-rails/#comments</comments>
		<pubDate>Sat, 20 Jun 2009 23:17:37 +0000</pubDate>
		<dc:creator>Tony Perrie</dc:creator>
				<category><![CDATA[Memcached]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://involution.com/?p=1238</guid>
		<description><![CDATA[The memcached support in Rails is great, but it&#8217;s a bit difficult to see what the heck is going on in a production environment. The first problem is, by default Rails doesn&#8217;t keep a list of all memcached keys that are available on the system. So, you have to use a plugin like memcache_store_with_delete_matched to [...]]]></description>
			<content:encoded><![CDATA[<p>The memcached support in Rails is great, but it&#8217;s a bit difficult to see what the heck is going on in a production environment.  The first problem is, by default Rails doesn&#8217;t keep a list of all memcached keys that are available on the system.  So, you have to use a plugin like <a href="http://github.com/lacomartincik/memcache_store_with_delete_matched/tree/master">memcache_store_with_delete_matched</a> to have memcache itself store a list of all available keys.  </p>
<p>You can install this plugin with the typical <code>script/plugin</code> command. </p>
<pre><code>script/plugin install git://github.com/lacomartincik/memcache-store-with-delete_matched.git
</code></pre>
<p>Then, you configure memcached in your <code>environment.rb</code> like this. </p>
<pre><code>mem_cache_options = {
    :c_threshold => 10000,
    :compression => true,
    :debug => false,
    :timeout => false,
    :namespace => 'app',
    :readonly => false,
    :urlencode => false
  }
  config.action_controller.cache_store = <b>:mem_cache_store_with_delete_matched</b>, ['127.0.0.1:11211'], mem_cache_options
</code></pre>
<p>The other benefit to using memcache_store_with_delete_matched is that regular expressions within <code>expire_fragment</code> works. </p>
<pre><code>expire_fragment(%r!/index_user_.*!)
</code></pre>
<p>So, down to debugging.  If you want to see all keys in a <code>script/console</code>, you can do the following. </p>
<pre><code>YAML.load(ActionController::Base.cache_store.fetch("memcached_store_key_list"))
</code></pre>
<p>You can select certain keys from the memcached_store_keylist. </p>
<pre><code>YAML.load(ActionController::Base.cache_store.fetch("memcached_store_key_list")) .detect{ |k| k.match(/index/) }
</code></pre>
<p>Once you have the list of keys, you can plug them into a fetch command. </p>
<pre><code>ActionController::Base.cache_store.fetch("app/blog/index")
</code></pre>
<p>You can also manually expire keys from a console. </p>
<pre><code>c = ApplicationController.new
c.expire_fragment(/index/)
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://involution.com/2009/06/20/interactive-memcached-debugging-with-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using YUICompressor with Capistrano and Rails 2.3+ on Combined Javascript and CSS</title>
		<link>http://involution.com/2009/06/18/using-yuicompressor-with-capistrano-and-rails-2-3-on-combined-javascript-and-css/</link>
		<comments>http://involution.com/2009/06/18/using-yuicompressor-with-capistrano-and-rails-2-3-on-combined-javascript-and-css/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 15:20:49 +0000</pubDate>
		<dc:creator>Tony Perrie</dc:creator>
				<category><![CDATA[Capistrano]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[YUICompressor]]></category>

		<guid isPermaLink="false">http://involution.com/?p=1225</guid>
		<description><![CDATA[YUICompressor is a standalone Javascript and CSS minifier from the YUI folks. It&#8217;s fairly awesome in that it does deep analysis of Javascript using Rhino (a standalone Javascript interpreter). Most minifiers take the low road and merely remove spaces and newlines, and, if you&#8217;re lucky maybe shorten the variable names. YUICompressor one-ups them all because [...]]]></description>
			<content:encoded><![CDATA[<p>YUICompressor is a standalone Javascript and CSS minifier from the YUI folks.  It&#8217;s fairly awesome in that it does deep analysis of Javascript using Rhino (a standalone Javascript interpreter).  Most minifiers take the low road and merely remove spaces and newlines, and, if you&#8217;re lucky maybe shorten the variable names.  YUICompressor one-ups them all because it actually parses all your JS and aggressively optimizes it for download speed.  </p>
<h3>CSS and Javascript Conflation</h3>
<p>The problem is most of the guides out there for integrating YUICompressor with Capistrano and Rails are woefully out-of-date.  The main issue is that Rails now has built-in support for combining all JS files into a single file.  So, there&#8217;s no need to manually do this in Capistrano these days.  </p>
<p>You can make Rails combine automatically combine your Javascript by adding a <code>:cache => "cache/all"</code> to your <code>javascript_include_tag</code> and <code>stylesheet_link_tag</code> in your layout. </p>
<pre><code><%= stylesheet_link_tag 'one', 'two', :cache => "cache/all" %>
<%= javascript_include_tag 'jquery', 'ninja',  :cache => "cache/all" %>
</code></pre>
<h3>Priming the JS and CSS Caches</h3>
<p>The Capistrano stuff is a bit tricky because Rails doesn&#8217;t generate the Javascript and CSS until after the app has been visited for the first time.  So, you have to visit each of your web servers after restart during your deploy.</p>
<pre><code>task :after_restart, :roles => :web do
  desc "Visiting each web server"
  sleep(5)  # Wait for passenger to fully spin-up
  run "/usr/bin/wget -O- http://127.0.0.1 >/dev/null 2>&#038;1"
end
</code></pre>
<h3>Invoking YUICompressor</h3>
<p>Now, we can invoke YUICompressor after <code>after_restart</code>.  The previous <code>after_restart</code> task automatically gets invoked after the web servers are restarted, however, the compression needs to happen after that.  So, you have to manually chain a <code>minify</code> just after <code>after_restart</code>.</p>
<pre><code>after "deploy:after_restart", "deploy:minify"</code></pre>
<p>The actual task is quite simple for running the compressor itself.  It&#8217;s just a normal Capistrano task. </p>
<pre><code>task :minify, :roles => :web do
  desc "Minify JS and CSS Using YUICompressor"
  javascript = "#{current_path}/public/javascripts/cache/all.js"
  stylesheet = "#{current_path}/public/stylesheets/cache/all.css"
  compressor = "java -jar /usr/lib/java/yuicompressor-2.4.2.jar"
  run "#{compressor} --type js #{javascript} -o #{javascript}"
  run "#{compressor} --type css #{stylesheet} -o #{stylesheet}"
end
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://involution.com/2009/06/18/using-yuicompressor-with-capistrano-and-rails-2-3-on-combined-javascript-and-css/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Using Phusion Passenger with HAProxy</title>
		<link>http://involution.com/2009/02/25/using-phusion-passenger-with-haproxy/</link>
		<comments>http://involution.com/2009/02/25/using-phusion-passenger-with-haproxy/#comments</comments>
		<pubDate>Wed, 25 Feb 2009 21:14:33 +0000</pubDate>
		<dc:creator>Tony Perrie</dc:creator>
				<category><![CDATA[HAProxy]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://involution.com/?p=1196</guid>
		<description><![CDATA[Today I decided to turn on HAProxy to load-balance between Apache instances running Phusion Passenger on two separate machines. The results are clear. Doing this nearly doubled our ApacheBench throughput scores. This config was adaped from the 37Signals blog post here. # /etc/haproxy/haproxy.cfg global maxconn 4096 defaults mode http retries 3 option redispatch maxconn 2000 [...]]]></description>
			<content:encoded><![CDATA[<p>Today I decided to turn on HAProxy to load-balance between Apache instances running Phusion Passenger on two separate machines.  The results are clear.  Doing this nearly doubled our ApacheBench throughput scores.</p>
<p>This config was adaped from the 37Signals blog post <a href="http://www.37signals.com/svn/posts/1073-nuts-bolts-haproxy">here</a>.</p>
<pre># /etc/haproxy/haproxy.cfg
global
        maxconn 4096

defaults
        mode    http
        retries 3
        option redispatch
        maxconn 2000
        contimeout	5000
        clitimeout	50000
        srvtimeout	50000

listen web1 XXX.XXX.XXX.210:80
       mode http
       balance roundrobin
       server web1 XXX.XXX.XXX.210:8080
       server web2 XXX.XXX.XXX.211:8080
</pre>
<p>Passenger is configured the normal way. </p>
<pre><code>&lt;VirtualHost *:8080&gt;
        ServerName www.example.com
        DocumentRoot /var/www/rails_project/current/public
&lt;/VirtualHost&gt;
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://involution.com/2009/02/25/using-phusion-passenger-with-haproxy/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Chaining Named Scopes</title>
		<link>http://involution.com/2008/11/10/chaining-named-scopes/</link>
		<comments>http://involution.com/2008/11/10/chaining-named-scopes/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 03:22:44 +0000</pubDate>
		<dc:creator>Tony Perrie</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://involution.com/?p=1189</guid>
		<description><![CDATA[There aren&#8217;t many examples of how to combine named_scopes programmatically on the ol&#8217; Blogosphere these days. All I could find were a few scant references to using anonymous scopes like this. It took me quite a while to figure this out which is surprising since this use case seems like such a common thing to [...]]]></description>
			<content:encoded><![CDATA[<p>There aren&#8217;t many examples of how to combine named_scopes programmatically on the ol&#8217; Blogosphere these days.  All I could find were a few scant references to using anonymous scopes like this.  It took me quite a while to figure this out which is surprising since this use case seems like such a common thing to do.</p>
<p>If you want to stack conditions on a search form with will_paginate on top of that, this seems to be the spice.</p>
<pre><code>class Shape < ActiveRecord::Base
    named_scope :created_after, lambda { |m| {:conditions => ["created_at > ?", m]} }
    named_scope :with_color, lambda { |color| {:conditions => {:color => color}} }
end

class ShapesController < ApplicationController
  def index
    scope =  Shape.scoped({})
    scope = scope.created_after(params[:months_ago].to_i.months.ago) if params[:months_ago]
    scope = scope.with_color(params[:color]) if params[:color]
    @shapes = scope.paginate(paginate_options({:order => 'id DESC', :page => 1}))
  end
end</code></pre>
<p>I started to use <code>eval</code> to do this, but Ken Turner set me straight today.  I view <code>eval</code> as more of a last resort when all else fails.  In this case, it&#8217;s possible to tap these filters in using a rubber mallet.  No sense in busting out the sledgehammer for this one.</p>
]]></content:encoded>
			<wfw:commentRss>http://involution.com/2008/11/10/chaining-named-scopes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Ruby on Rails&#8217; View Helpers To Create a Javascript Form Reset Button</title>
		<link>http://involution.com/2008/08/22/using-ruby-on-rails-form-helpers-to-create-a-javascript-form-reset-button/</link>
		<comments>http://involution.com/2008/08/22/using-ruby-on-rails-form-helpers-to-create-a-javascript-form-reset-button/#comments</comments>
		<pubDate>Sat, 23 Aug 2008 02:48:22 +0000</pubDate>
		<dc:creator>Tony Perrie</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://involution.com/?p=1167</guid>
		<description><![CDATA[Apparently, it is possible reset an entire form using Javascript from a button using the Rails form helpers. Up until now, I&#8217;ve been sniffing the submit tag&#8217;s name in the controller and avoiding the save when posting an update. The beauty of the Javascript form reset method is that it requires absolutely no code in [...]]]></description>
			<content:encoded><![CDATA[<p>Apparently, it is possible reset an entire form using Javascript from a button using the Rails form helpers.  Up until now, I&#8217;ve been sniffing the submit tag&#8217;s name in the controller and avoiding the save when posting an update.  The beauty of the Javascript form reset method is that it requires absolutely no code in the controller. </p>
<p>Oddly enough, there did not exist any easily findable examples from Google.  So, here is how to reset a form to the original using only Javascript. </p>
<pre>
<% form_for :person, person, :url => { :action => "update" } do |f| %>
# Other stuff
<%= f.submit "Cancel", :type => "button", :onclick => "this.form.reset()" %>
# Resets the form back to the original values set in the edit template
<% end %>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://involution.com/2008/08/22/using-ruby-on-rails-form-helpers-to-create-a-javascript-form-reset-button/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Persisting a Country Selection in Rails Using country_select</title>
		<link>http://involution.com/2008/07/22/persisting-a-country-selection-in-rails-using-country_select/</link>
		<comments>http://involution.com/2008/07/22/persisting-a-country-selection-in-rails-using-country_select/#comments</comments>
		<pubDate>Tue, 22 Jul 2008 21:18:14 +0000</pubDate>
		<dc:creator>Tony Perrie</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://involution.com/?p=1155</guid>
		<description><![CDATA[Rails&#8217; country_select form helper doesn&#8217;t accept a :selected option. If a validation error occurs, you really don&#8217;t want to force the user to reselect a country. However, there&#8217;s no documented way of persisting that data when re-rendering an unvalidated form. Fortunately, the country_select helper accepts a parameter called priority_countries. This exists so you don&#8217;t have [...]]]></description>
			<content:encoded><![CDATA[<p>Rails&#8217; country_select form helper doesn&#8217;t accept a :selected option.  If a validation error occurs, you really don&#8217;t want to force the user to reselect a country.  However, there&#8217;s no documented way of persisting that data when re-rendering an unvalidated form.</p>
<p>Fortunately, the country_select helper accepts a parameter called priority_countries.  This exists so you don&#8217;t have to scroll all the way down past Uganda and Ukraine just to arrive at the good ol&#8217; US of A.  A clever workaround to this problem is to use the priority_countries parameter to effectively &#8220;select&#8221; the previous value through a bit of magic.  </p>
<pre>
&lt;%= form.country_select :country,
  [@location['country'] || 'United States'] %&gt;
</pre>
<p>This ERb line merely appends your selected country to the top of the priority country list.  And, indeed this allows your old country to remain selected even if a validation errors causes the form to be rendered again.</p>
]]></content:encoded>
			<wfw:commentRss>http://involution.com/2008/07/22/persisting-a-country-selection-in-rails-using-country_select/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Monkeypatching For Robots</title>
		<link>http://involution.com/2008/07/16/monkey-patching-for-robots/</link>
		<comments>http://involution.com/2008/07/16/monkey-patching-for-robots/#comments</comments>
		<pubDate>Wed, 16 Jul 2008 11:27:38 +0000</pubDate>
		<dc:creator>Tony Perrie</dc:creator>
				<category><![CDATA[Photos]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://involution.com/?p=1104</guid>
		<description><![CDATA[Even though Jeff Atwood believes that monkeypatching will lead to the apocalypse, I&#8217;ve discovered three cases where it has proven to be most useful. Case 1: Dynamically Patching a Plug-in Let&#8217;s face it. The Ruby on Rails wiki is littered with a cadre of unmaintained plugins. One example is file_column. Attachment_fu pretty much replaces this, [...]]]></description>
			<content:encoded><![CDATA[<p>Even though Jeff Atwood <a href="http://www.codinghorror.com/blog/archives/001151.html">believes</a> that monkeypatching will lead to the apocalypse, I&#8217;ve discovered three cases where it has proven to be most useful.  </p>
<p><b>Case 1: Dynamically Patching a Plug-in</b></p>
<p>Let&#8217;s face it.  The Ruby on Rails wiki is littered with a cadre of unmaintained plugins.  One example is file_column.  Attachment_fu pretty much replaces this, but for whatever reason, the project that I&#8217;m working on is using the old warhorse of file upload packages.  Recently, I&#8217;ve noticed several problems with file_column.  The biggest issue is that it was written pre-Leopard  So, file_column doesn&#8217;t support the new way of calling OS X&#8217;s file command.  Combining monkeypatching with the Rails alias_method_chain allows us to patch the underlying code with minimal effort.  And, keeping the dynamic patch separate, means that updating the plugin will not overwrite the patch.</p>
<pre><code># Rails lib/project_system.rb
module FileColumn
  def get_content_type_with_leopard_rules(fallback=nil)
    if not RUBY_PLATFORM.eql?('universal-darwin9.0')
      return get_content_type_for_leopard_without_apple_rules
    end
    if options[:file_exec]
      begin
        content_type = `#{@options[:file_exec]} -bI "#{@local_file_path}"`.chomp
        content_type = fallback unless $?.success?
        content_type.gsub!(/;.+$/,"") if content_type
        content_type
      rescue
        fallback
      end
    else
      fallback
    end
  end
  alias_method_chain :get_content_type, :leopard_rules
end
</code></pre>
<p><br/><br />
<b>Case 2: Adding a Feature to a Plug-in</b></p>
<p>I&#8217;m a total Unix snob.  Upper-case filenames injure what&#8217;s left of my dwindling sanity.  File_column recklessly allows the user&#8217;s filenames to be saved directly to the filesystem.  This has the side-effect of dumping a flagon full of mime-type detection FAIL when you view the files that have been uploaded to the server.  Think of users uploading images named <code>me.jpeg</code>, <code>me.JPG</code> and <code>me.Jpeg</code>.  Inconsistent capitalization is clearly evil and has to be sanitized before it gets to our precious disks.  Using a monkeypatch with alias_method_chain, you can override file_column&#8217;s sanitize_filename method to convert the filename to lowercase.</p>
<pre><code># Rails lib/project_system.rb
module FileColumn
  class << self
    def sanitize_filename_with_downcase_rules(filename)
      self.sanitize_filename_without_downcase_rules(filename).downcase.gsub(/\.jpeg$/,'jpg')
    end
    alias_method_chain :sanitize_filename, :downcase_rules
  end
end
</code></pre>
<p><br/><br />
<b>Case 3: Overriding a Native Ruby Class to Facilitate Symbol#to_proc Abuses</b></p>
<p>Ever since reading <a href="http://weblog.raganwald.com">Reg Braithwaite</a>'s <a href="http://weblog.raganwald.com/2008/02/1100inject.html">(1..100).inject(&#038;:+)</a> post, I've been mystified and rather infatuated with Rails' <code>Symbol#to_proc</code> method (which, incidentally, was only possible through Rails' monkeypatch to the Ruby Symbol class).</p>
<p>Recently, I wrote a method to detect whether any one checkbox or radio button had been selected on a HTML form.  This would serve as a form validation, but was complicated due to the fact that radio button values are arbitrary strings and checkbox values are posted as "0" and "1".  The radio button values had to be converted to boolean by the controller, but ActiveRecord's value_to_boolean method does not support this.  Monkeypatching came to the rescue yet again and allowed me to override Object in an inject-friendly way. </p>
<pre><code># Rails lib/project_system.rb
class Object
  def selected?
    return true if self and self.is_a?(String) and self.include?('location')
    ActiveRecord::ConnectionAdapters::Column.value_to_boolean(self)
  end
end
</code></pre>
<p>Rather than writing a massive case statement or nested if/elsifs, we can just write the following in a model.</p>
<p><code>
<pre># Rails app/models/model_name.rb
def selected_place?
  places.collect(&#038;:selected?).inject(&#038;:|)
  # Logically, the same as places.collect(&#038;:selected?).any?
end
</code></pre>
<p>The preceding loop calls our new Object selected? method on each of the location_types column, and the inject ORs all the data together.</p>
<p><img src="/images/robotmonkey.jpg" /></p>
<p>I don't really understand why Jeff is writing these slime pieces on monkeypatching.  Jeff's logic is equivalent to reasoning that driving should be outlawed because cars are dangerous.  However, just because a few people drive drunk doesn't mean that no one should drive!  Oddly, I would get behind a law to make drunken monkeypatching a felony. </p>
]]></content:encoded>
			<wfw:commentRss>http://involution.com/2008/07/16/monkey-patching-for-robots/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Malfeasance in 64-bit PowerPC MySQL Gem Compilation</title>
		<link>http://involution.com/2008/05/12/malfeasance-in-64-bit-powerpc-mysql-gem-compilation/</link>
		<comments>http://involution.com/2008/05/12/malfeasance-in-64-bit-powerpc-mysql-gem-compilation/#comments</comments>
		<pubDate>Tue, 13 May 2008 01:25:12 +0000</pubDate>
		<dc:creator>Tony Perrie</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://involution.com/?p=1102</guid>
		<description><![CDATA[For the three people in the world building the Rails mysql gem on a PowerPC G5-based OS X Server with the 64-bit MySQL installed getting this crazy error: lazy symbol binding failed: Symbol not found: _mysql_init The magic ninja gem install command that will cure all your ills goes a little something like this: sudo [...]]]></description>
			<content:encoded><![CDATA[<p>For the three people in the world building the Rails <code>mysql</code> gem on a PowerPC G5-based OS X Server with the 64-bit MySQL installed getting this crazy error:</p>
<pre>
lazy symbol binding failed: Symbol not found: _mysql_init
</pre>
<p>The magic ninja gem install command that will cure all your ills goes a little something like this:</p>
<pre>
sudo env ARCHFLAGS="-arch ppc64" gem install -V mysql -- --with-mysql-include=/usr/local/mysql/include/ --with-mysql-lib=/usr/local/mysql/lib --with-mysql-config=/usr/local/mysql/bin/mysql_config --with-mysql-dir=/usr/local/mysql
</pre>
<p>Pretty obvious when you think about it.  Not sure why it took me a little over an hour to discover the crucial lynchpin for correcting this system-wide thought-tastrophy.</p>
]]></content:encoded>
			<wfw:commentRss>http://involution.com/2008/05/12/malfeasance-in-64-bit-powerpc-mysql-gem-compilation/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>CSS Templating with Sass</title>
		<link>http://involution.com/2007/07/09/css-templating-with-sass/</link>
		<comments>http://involution.com/2007/07/09/css-templating-with-sass/#comments</comments>
		<pubDate>Tue, 10 Jul 2007 03:38:07 +0000</pubDate>
		<dc:creator>Tony Perrie</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://involution.com/2007/07/09/css-templating-with-sass/</guid>
		<description><![CDATA[I don&#8217;t hear many people talking about Sass, but it is indeed fantastic. Basically, Sass is kind of like the Smarty of CSS Templating. Sass files compile to CSS after every change just like Smarty&#8217;s TPL files compile directly to PHP. Sass fits well into the Rails don&#8217;t-repeat-yourself methodology because you can define color and [...]]]></description>
			<content:encoded><![CDATA[<p>I don&#8217;t hear many people talking about Sass, but it is indeed fantastic.  Basically, Sass is kind of like the Smarty of CSS Templating.  Sass files compile to CSS after every change just like Smarty&#8217;s TPL files compile directly to PHP.  Sass fits well into the Rails don&#8217;t-repeat-yourself methodology because you can define color and style constants within CSS rather than explicitly specifying them twenty times.  The beauty of Sass is that you get a level of abstraction without any runtime overhead.  As a result, Sass performs well and allows quick updates to color schemes and typography without resorting to perl/find or ninja text editor foo.  So, why aren&#8217;t more people using it?</p>
]]></content:encoded>
			<wfw:commentRss>http://involution.com/2007/07/09/css-templating-with-sass/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

