<?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>Mike Perham &#187; Rails</title>
	<atom:link href="http://www.mikeperham.com/category/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mikeperham.com</link>
	<description>On Ruby, software and the Internet</description>
	<lastBuildDate>Sat, 22 May 2010 03:05:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Introducing Phat, an Asynchronous Rails app</title>
		<link>http://www.mikeperham.com/2010/04/03/introducing-phat-an-asynchronous-rails-app/</link>
		<comments>http://www.mikeperham.com/2010/04/03/introducing-phat-an-asynchronous-rails-app/#comments</comments>
		<pubDate>Sat, 03 Apr 2010 22:51:37 +0000</pubDate>
		<dc:creator>Mike Perham</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[eventmachine]]></category>

		<guid isPermaLink="false">http://www.mikeperham.com/?p=509</guid>
		<description><![CDATA[Phat is my new Rails 2.3.5 application which runs 100% asynchronous, supporting many concurrent requests in a single Ruby process.
This is a new breed of Rails application which uses a new mode of execution available in Ruby 1.9: single Thread, multiple Fiber.  Existing modes of execution suck:

Single thread harkens back to the days of [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://github.com/mperham/phat">Phat</a> is my new Rails 2.3.5 application which runs 100% asynchronous, supporting many concurrent requests in a single Ruby process.</p>
<p>This is a new breed of Rails application which uses a new mode of execution available in Ruby 1.9: single Thread, multiple Fiber.  Existing modes of execution suck:</p>
<ul>
<li>Single thread harkens back to the days of Rails 1.x, where you started N mongrels to handle up to N concurrent requests.</li>
<li>Multiple threads is better but still has fundamental issues in Ruby.  <a href="http://redmine.ruby-lang.org/issues/show/921">Autoloading is simply broken</a> and Ruby&#8217;s thread implementation does not scale at all due to the GIL.</li>
</ul>
<p>Here&#8217;s a sample action which uses memcached and the database.  There&#8217;s nothing odd here &#8211; it&#8217;s the same old Rails API and codebase we are used to as Ruby developers, it just executes differently under the covers.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> HelloController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController
  <span style="color:#9966CC; font-weight:bold;">def</span> world
    site_ids = Rails.<span style="color:#9900CC;">cache</span>.<span style="color:#9900CC;">fetch</span> <span style="color:#996600;">'site_ids'</span>, <span style="color:#ff3333; font-weight:bold;">:expires_in</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> 1.<span style="color:#9900CC;">minute</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      Site.<span style="color:#9900CC;">all</span>.<span style="color:#9900CC;">map</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>:id<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    render <span style="color:#ff3333; font-weight:bold;">:text</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> site_ids
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>How does it work?  If you want the nitty-gritty, <a href="/2010/01/27/scalable-ruby-processing-with-eventmachine/">watch my talk on EventMachine and Fibers</a>.  Everything that does network access ideally should be modified to be Fiber-aware.  I&#8217;ve updated many gems to be Fiber-aware: <a href="http://github.com/mperham/memcache-client">memcache-client</a>, <a href="http://github.com/mperham/em_postgresql">em_postgresql</a> (and activerecord), cassandra, bunny and rsolr to name a few.  You&#8217;ll also need to run thin as your app server, since all of this code assumes it is executing within EventMachine.</p>
<p>Additionally we need to ensure that each request runs in its own Fiber.  My new gem, <a href="http://github.com/mperham/rack-fiber_pool">rack-fiber_pool</a>, will do this for you, just add it as Rack middleware in <code>config/environment.rb</code>.  Here&#8217;s the basic configuration:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Asynchronous DNS lookup</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'em-resolv-replace'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rack/fiber_pool'</span>
<span style="color:#008000; font-style:italic;"># Pull in the evented memcache-client.</span>
<span style="color:#008000; font-style:italic;"># You'll need to configure config.cache_store as normal.</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'memcache/event_machine'</span>
&nbsp;
<span style="color:#6666ff; font-weight:bold;">Rails::Initializer</span>.<span style="color:#9900CC;">run</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>config<span style="color:#006600; font-weight:bold;">|</span>
  config.<span style="color:#9900CC;">cache_store</span> = <span style="color:#ff3333; font-weight:bold;">:mem_cache_store</span>
  <span style="color:#008000; font-style:italic;"># Run each request in a Fiber</span>
  config.<span style="color:#9900CC;">middleware</span>.<span style="color:#9900CC;">use</span> <span style="color:#6666ff; font-weight:bold;">Rack::FiberPool</span>
  <span style="color:#008000; font-style:italic;"># Get rid of Rack::Lock so we don't kill our concurrency</span>
  config.<span style="color:#9900CC;">threadsafe</span>!
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Additionally we need to <a href="http://github.com/mperham/phat/blob/master/config/database.yml">configure Postgresql</a> and <a href="http://github.com/mperham/phat/blob/master/config/initializers/disable_locking.rb">disable ActionController&#8217;s reloader mutex</a> as it really doesn&#8217;t like fibered execution.  This is ok because remember &#8211; there&#8217;s only a single thread executing in our process!</p>
<p>With that done, we can try some tests to see how we scale now.  EventMachine works best when you have significant network latency.  A simple test with database access over coffeeshop WiFi:</p>
<blockquote><p>
    Without EventMachine:<br />
    Requests per second:    4.39 [#/sec] (mean)</p>
<p>    With EventMachine:<br />
    Requests per second:    21.31 [#/sec] (mean)
</p></blockquote>
<p>That&#8217;s it!  There&#8217;s no magic here: you can make your Rails app a &#8220;phat&#8221; app by following the same guidelines above.  Fire up one thin instance per processor/core, put nginx in front of it and it should scale like crazy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikeperham.com/2010/04/03/introducing-phat-an-asynchronous-rails-app/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Using ActiveRecord with EventMachine</title>
		<link>http://www.mikeperham.com/2010/03/30/using-activerecord-with-eventmachine/</link>
		<comments>http://www.mikeperham.com/2010/03/30/using-activerecord-with-eventmachine/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 05:25:14 +0000</pubDate>
		<dc:creator>Mike Perham</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[eventmachine]]></category>

		<guid isPermaLink="false">http://www.mikeperham.com/?p=494</guid>
		<description><![CDATA[Given all my work with Fibers and EventMachine over the last three months, it should come as no surprise that I&#8217;ve been working on infrastructure based on Fibers and EventMachine to get maximum scalability without the callback style of code which I dislike for many reasons.  Watch my talk on scaling with EventMachine if [...]]]></description>
			<content:encoded><![CDATA[<p>Given all my work with Fibers and EventMachine over the last three months, it should come as no surprise that I&#8217;ve been working on infrastructure based on Fibers and EventMachine to get maximum scalability without the callback style of code which I dislike for many reasons.  <a href="/2010/01/27/scalable-ruby-processing-with-eventmachine/">Watch my talk on scaling with EventMachine</a> if you need more background on the problem.</p>
<p>Now that I have RabbitMQ, Cassandra, Solr and the Amazon AWS services evented, the only holdup was ActiveRecord.  Some people may advocate using another ORM layer but when you have 2-3 other Rails apps, all sharing 100+ models, you can&#8217;t afford to maintain two separate ORM layers.  Plus, frankly I like the Rails stack: it works pretty well, is thoroughly documented and every Ruby developer is familiar with it.</p>
<p>So what do we need to do to get AR working event-style?  At a high level, there&#8217;s two things required:</p>
<ul>
<li>The database driver itself must be modified to send SQL asynchronously.  The postgresql driver, for instance, calls the <code>exec(sql)</code> method for all traffic to the database.  So we just need to provide an exec method which uses Fibers under the covers to work asynchronously.</li>
<li>AR&#8217;s connection pooling needs to be Fiber-safe.  Out of the box, it is Thread-safe.  Since we are using an execution model based on a single Thread with multiple Fibers, all the Fibers would try to use the same connection, with disastrous consequences.</li>
</ul>
<p>These are the things that em_postgresql does.</p>
<ul>
<li><a href="http://github.com/mperham/em_postgresql/blob/master/lib/postgres_connection.rb">postgres_connection</a> is a basic, EM-aware Postgres driver.  It provides the Fibered <code>exec()</code> method which makes the whole thing asynchronous.
<li><a href="http://github.com/mperham/em_postgresql/blob/master/lib/active_record/connection_adapters/em_postgresql_adapter.rb">em_postgresql_adapter.rb</a> wraps postgres_connection to make it a proper ActiveRecord driver.</li>
<li><a href="http://github.com/mperham/em_postgresql/blob/master/lib/active_record/patches.rb">patches.rb</a> overrides a bunch of AR&#8217;s internal connection pooling to make it Fiber-friendly.</li>
</ul>
<p>Unfortunately the latter makes one hack necessary &#8211; we have to have a list of current Fibers to release any lingering connections associated with those Fibers.  The Threaded version can use <code>Thread.list</code> but Ruby does not provide an equivalent method for Fibers.  Instead I require the application to register a FiberPool with AR to clear stale connections.</p>
<p>So what does it all mean?  Well, here&#8217;s <a href="http://github.com/mperham/em_postgresql/blob/master/examples/app.rb">a Sinatra application</a> that uses plain old ActiveRecord and <strong>is completely asynchronous</strong>!  Try <code>ab -n 100 -c 20 http://localhost:9292/test</code> to hit the app with 20 concurrent connections; it will process them all in parallel, without any painful threading issues (autoloading, misbehaving extensions, etc).  Awesome!</p>
<p>You should guess what&#8217;s next.  Coming soon: the whole Rails stack, running asynchronously&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikeperham.com/2010/03/30/using-activerecord-with-eventmachine/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>DataFabric &#8211; database sharding for Rails</title>
		<link>http://www.mikeperham.com/2009/10/05/datafabric-database-sharding-for-rails/</link>
		<comments>http://www.mikeperham.com/2009/10/05/datafabric-database-sharding-for-rails/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 02:52:50 +0000</pubDate>
		<dc:creator>Mike Perham</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.mikeperham.com/?p=342</guid>
		<description><![CDATA[With the closing of FiveRuns, the blog post that was the main page for DataFabric has disappeared.  I&#8217;m creating this blog post as a replacement.
DataFabric is a Rails plugin/gem that adds sharding support to ActiveRecord.  It supports Rails 2.x and is theoretically database independent, although I haven&#8217;t tested it personally with anything but [...]]]></description>
			<content:encoded><![CDATA[<p>With the closing of FiveRuns, the blog post that was the main page for <a href="http://github.com/mperham/data_fabric">DataFabric</a> has disappeared.  I&#8217;m creating this blog post as a replacement.</p>
<p>DataFabric is a Rails plugin/gem that adds sharding support to ActiveRecord.  It supports Rails 2.x and is theoretically database independent, although I haven&#8217;t tested it personally with anything but MySQL and SQLite.  Please see the <a href="http://github.com/mperham/data_fabric">github home page</a> for the latest code, examples and a more in-depth explanation.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikeperham.com/2009/10/05/datafabric-database-sharding-for-rails/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rails Engines at LSRC</title>
		<link>http://www.mikeperham.com/2009/08/28/rails-engines-at-lsrc/</link>
		<comments>http://www.mikeperham.com/2009/08/28/rails-engines-at-lsrc/#comments</comments>
		<pubDate>Fri, 28 Aug 2009 21:46:13 +0000</pubDate>
		<dc:creator>Mike Perham</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.mikeperham.com/?p=317</guid>
		<description><![CDATA[Here&#8217;s my slides for LSRC covering the new Engines feature in Rails 2.3.  Basically I cover Rails&#8217; history from monolithic application to supporting code reuse via plugins to supporting MVC reuse via engines.
Rails Engines (PPT, 2.9MB)
Rails Engines (Keynote, 1.8MB)
]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s my slides for LSRC covering the new Engines feature in Rails 2.3.  Basically I cover Rails&#8217; history from monolithic application to supporting code reuse via plugins to supporting MVC reuse via engines.</p>
<p><a href='http://www.mikeperham.com/wp-content/uploads/2009/08/railsengines.ppt'>Rails Engines (PPT, 2.9MB)</a><br />
<a href='http://www.mikeperham.com/wp-content/uploads/2009/08/railsengines.key'>Rails Engines (Keynote, 1.8MB)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikeperham.com/2009/08/28/rails-engines-at-lsrc/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Old versus New</title>
		<link>http://www.mikeperham.com/2009/07/29/old-versus-new/</link>
		<comments>http://www.mikeperham.com/2009/07/29/old-versus-new/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 18:02:48 +0000</pubDate>
		<dc:creator>Mike Perham</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.mikeperham.com/?p=310</guid>
		<description><![CDATA[We had some performance issues recently and discovered we were using memcache-client 1.5.0.  Our daemon was blocked by memcached socket operations hanging forever, which caused monit to kill and restart the daemon after 5 minutes.
I performed the brain surgery to use 1.7.4 (since we are using Rails 2.1) and deployed.  See if you [...]]]></description>
			<content:encoded><![CDATA[<p>We had some performance issues recently and discovered we were using memcache-client 1.5.0.  Our daemon was blocked by memcached socket operations hanging forever, which caused monit to kill and restart the daemon after 5 minutes.</p>
<p>I performed the brain surgery to use 1.7.4 (since we are using Rails 2.1) and deployed.  See if you can guess when.  Graph shows operations per hour (more is better).</p>
<p><a href="http://www.mikeperham.com/wp-content/uploads/2009/07/picture-1.png"><img src="http://www.mikeperham.com/wp-content/uploads/2009/07/picture-1.png" alt="picture-1" title="picture-1" width="515" height="777" class="aligncenter size-full wp-image-311" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikeperham.com/2009/07/29/old-versus-new/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding multi-get support to Rails</title>
		<link>http://www.mikeperham.com/2009/06/13/adding-multi-get-support-to-rails/</link>
		<comments>http://www.mikeperham.com/2009/06/13/adding-multi-get-support-to-rails/#comments</comments>
		<pubDate>Sat, 13 Jun 2009 20:14:34 +0000</pubDate>
		<dc:creator>Mike Perham</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.mikeperham.com/?p=292</guid>
		<description><![CDATA[Memcache-client has the ability to fetch multiple keys in one request but Rails does not expose this functionality.  It&#8217;s really easy to add it yourself though:
config/initializers/rails_patches.rb

Rails.cache.instance_eval &#60;&#60;-EOM
  def read_multi&#40;*keys&#41;
    @data.get_multi&#40;*keys&#41;
  end
EOM

Rails uses read/write for its API naming so we name the method read_multi rather than get_multi.  Here&#8217;s a [...]]]></description>
			<content:encoded><![CDATA[<p>Memcache-client has the ability to fetch multiple keys in one request but Rails does not expose this functionality.  It&#8217;s really easy to add it yourself though:</p>
<p><strong>config/initializers/rails_patches.rb</strong></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Rails.<span style="color:#9900CC;">cache</span>.<span style="color:#9900CC;">instance_eval</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;-</span>EOM
  <span style="color:#9966CC; font-weight:bold;">def</span> read_multi<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>keys<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@data</span>.<span style="color:#9900CC;">get_multi</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>keys<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
EOM</pre></div></div>

<p>Rails uses read/write for its API naming so we name the method <code>read_multi</code> rather than <code>get_multi</code>.  Here&#8217;s a sample usage in script/console:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&gt;&gt;</span> Rails.<span style="color:#9900CC;">cache</span>.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'a'</span>, <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> Rails.<span style="color:#9900CC;">cache</span>.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'b'</span>, <span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> Rails.<span style="color:#9900CC;">cache</span>.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'c'</span>, <span style="color:#006666;">3</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> Rails.<span style="color:#9900CC;">cache</span>.<span style="color:#9900CC;">read_multi</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'a'</span>, <span style="color:#996600;">'b'</span>, <span style="color:#996600;">'c'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">&quot;a&quot;</span><span style="color:#006600; font-weight:bold;">=&gt;</span><span style="color:#006666;">1</span>, <span style="color:#996600;">&quot;b&quot;</span><span style="color:#006600; font-weight:bold;">=&gt;</span><span style="color:#006666;">2</span>, <span style="color:#996600;">&quot;c&quot;</span><span style="color:#006600; font-weight:bold;">=&gt;</span><span style="color:#006666;">3</span><span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikeperham.com/2009/06/13/adding-multi-get-support-to-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Engines in Rails 2.3</title>
		<link>http://www.mikeperham.com/2009/04/18/engines-in-rails-23/</link>
		<comments>http://www.mikeperham.com/2009/04/18/engines-in-rails-23/#comments</comments>
		<pubDate>Sat, 18 Apr 2009 20:53:29 +0000</pubDate>
		<dc:creator>Mike Perham</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.mikeperham.com/?p=248</guid>
		<description><![CDATA[Engines have been around Rails for years but it wasn&#8217;t until the recent 2.3 release that Rails officially supported Engines.  So what is an Engine?  An Engine is a Rails plugin with full MVC capabilities.  In essence, that means your Engine has an app directory with helpers, controllers, models and views just [...]]]></description>
			<content:encoded><![CDATA[<p>Engines have been around Rails for years but it wasn&#8217;t until the recent 2.3 release that Rails officially supported Engines.  So what is an Engine?  An Engine is a Rails plugin with full MVC capabilities.  In essence, that means your Engine has an app directory with helpers, controllers, models and views just like a standard Rails application.  You add an engine to <code>vendor/plugins</code> or through <code>config.gem</code> in your application, just like a plugin, but additionally its app directory is effectively overlaid on top of your application&#8217;s app directory.</p>
<p>Let&#8217;s spelunk through the code:</p>
<p><code>rails-2.3.2/lib/rails/plugin/loader.rb</code></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">        <span style="color:#9966CC; font-weight:bold;">def</span> configure_engines
          <span style="color:#9966CC; font-weight:bold;">if</span> engines.<span style="color:#9900CC;">any</span>?
            add_engine_routing_configurations
            add_engine_controller_paths
            add_engine_view_paths
          <span style="color:#9966CC; font-weight:bold;">end</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
        <span style="color:#9966CC; font-weight:bold;">def</span> add_engine_routing_configurations
          engines.<span style="color:#CC0066; font-weight:bold;">select</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>:routed?<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">collect</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>:routing_file<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>routing_file<span style="color:#006600; font-weight:bold;">|</span>
            <span style="color:#6666ff; font-weight:bold;">ActionController::Routing::Routes</span>.<span style="color:#9900CC;">add_configuration_file</span><span style="color:#006600; font-weight:bold;">&#40;</span>routing_file<span style="color:#006600; font-weight:bold;">&#41;</span>
          <span style="color:#9966CC; font-weight:bold;">end</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
        <span style="color:#9966CC; font-weight:bold;">def</span> add_engine_controller_paths
          <span style="color:#6666ff; font-weight:bold;">ActionController::Routing</span>.<span style="color:#9900CC;">controller_paths</span> <span style="color:#006600; font-weight:bold;">+</span>= engines.<span style="color:#9900CC;">collect</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>:controller_path<span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
        <span style="color:#9966CC; font-weight:bold;">def</span> add_engine_view_paths
          <span style="color:#008000; font-style:italic;"># reverse it such that the last engine can overwrite view paths from the first, like with routes</span>
          paths = <span style="color:#6666ff; font-weight:bold;">ActionView::PathSet</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>engines.<span style="color:#9900CC;">collect</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>:view_path<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">reverse</span><span style="color:#006600; font-weight:bold;">&#41;</span>
          <span style="color:#6666ff; font-weight:bold;">ActionController::Base</span>.<span style="color:#9900CC;">view_paths</span>.<span style="color:#9900CC;">concat</span><span style="color:#006600; font-weight:bold;">&#40;</span>paths<span style="color:#006600; font-weight:bold;">&#41;</span>
          <span style="color:#6666ff; font-weight:bold;">ActionMailer::Base</span>.<span style="color:#9900CC;">view_paths</span>.<span style="color:#9900CC;">concat</span><span style="color:#006600; font-weight:bold;">&#40;</span>paths<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> configuration.<span style="color:#9900CC;">frameworks</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:action_mailer</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>For each engine, we add any routes, any controllers and any views.  Additionally, the directories within app will be added to the global LOAD_PATH, as with a normal application.  Note that engines are processed in order exactly like plugins: alphabetically or based on the order they are listed in <code>config/environment.rb</code>.</p>
<p>There are some limitations you should be aware of:</p>
<ul>
<li>No migration support: while the engine can add models, it is not obvious how to manage any database structure needed by the engine.  I would imagine the engine should use the install.rb hook to copy migrations to the app&#8217;s <code>db/migrate</code> directory.</li>
<li>No public asset support: like migrations, any stylesheets, javascripts or images must be copied as part of the install.rb hook to the app&#8217;s public directory.</li>
<li>Like plugins, naming becomes a concern.  An engine can have a User model but this will lead to problems with the 90% of Rails applications that have a model of the same name.  You can put your models within a module but I&#8217;ve heard of problems when trying to mix Rails autoloading with modularized classes.  As with plugins, be sure to err on the side of safety and use a unique name for your classes.  I&#8217;m building an engine called <strong>Queso</strong> and it provides a model called <strong>QuesoSearch</strong>, which is unlikely to collide with application classes unless you are building an application for a Mexican cheese provider.  <img src='http://www.mikeperham.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
</ul>
<p>So while Engines do have some limitations to be aware of, they do fill a valuable niche; engines provide a good framework for building full-stack generic application functionality.  <a href="http://activescaffold.com">ActiveScaffold</a> is one example of a Rails plugin that would be an excellent choice to rewrite as an Engine.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikeperham.com/2009/04/18/engines-in-rails-23/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Caching and Rails</title>
		<link>http://www.mikeperham.com/2009/03/25/caching-and-rails/</link>
		<comments>http://www.mikeperham.com/2009/03/25/caching-and-rails/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 14:44:32 +0000</pubDate>
		<dc:creator>Mike Perham</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.mikeperham.com/?p=237</guid>
		<description><![CDATA[Here&#8217;s the slides from my AOR talk last night: Caching, Memcached and Rails (600KB).
Caching, Memcached And Rails


I was a little unhappy with my wrapup &#8211; the one thing I wanted to teach people was when to use each different caching mechanism provided by Rails and I didn&#8217;t really revisit and summarize that content.  So [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s the slides from my AOR talk last night: <a href='http://www.mikeperham.com/wp-content/uploads/2009/03/caching-memcached-and-rails.key'>Caching, Memcached and Rails</a> (600KB).</p>
<div style="width:425px;text-align:left" id="__ss_1196725"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/guestac752c/caching-memcached-and-rails?type=presentation" title="Caching, Memcached And Rails">Caching, Memcached And Rails</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cachingmemcachedandrails-090325105739-phpapp02&#038;stripped_title=caching-memcached-and-rails" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cachingmemcachedandrails-090325105739-phpapp02&#038;stripped_title=caching-memcached-and-rails" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"></div>
</div>
<p>I was a little unhappy with my wrapup &#8211; the one thing I wanted to teach people was when to use each different caching mechanism provided by Rails and I didn&#8217;t really revisit and summarize that content.  So here&#8217;s a quick summary:</p>
<ul>
<li>HTTP caching &#8211; prefer this over all other mechanisms.  This is really the only mechanism that prevents the request from ever hitting Ruby.  This topic is big enough for a book so I won&#8217;t cover it here but review the Expires, Etag and Cache-Control headers to understand how HTTP caching works.  You&#8217;ll need to configure Varnish, Squid, mod_cache or some other HTTP caching proxy.</li>
<li>Page caching &#8211; I believe this is really legacy from before Rails supported HTTP caching properly.  Stick with HTTP caching and proper headers.</li>
<li>Action caching &#8211; useful when the entire page contents can be cached but you need to run before_filters (e.g. to ensure the user is logged in).  Use AJAX/javascript to do minor customization to the cached content.</li>
<li>Fragment caching &#8211; useful when various boxes of content on the page can be cached, but have different dependencies and need to be expired at different times</li>
<li>Object caching (the Rails.cache.fetch method) &#8211; the most granular mechanism.  Good for caching the results of intensive logic or queries.</li>
</ul>
<p>I hope this helps demystify the myriad of caching mechanisms Rails supports.  If you want to learn even more,  Gregg Pollack has an amazing set of videos on <a href="http://railslab.newrelic.com/scaling-rails">Scaling Rails</a> which covers caching in great depth.  Happy Caching!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikeperham.com/2009/03/25/caching-and-rails/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using memcache-client 1.6.x in Rails &lt; 2.3</title>
		<link>http://www.mikeperham.com/2009/03/03/using-memcache-client-16x-in-rails-23/</link>
		<comments>http://www.mikeperham.com/2009/03/03/using-memcache-client-16x-in-rails-23/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 15:54:48 +0000</pubDate>
		<dc:creator>Mike Perham</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.mikeperham.com/?p=195</guid>
		<description><![CDATA[Jemery Kemper recently upgraded Rails 2.3&#8217;s vendored copy of memcache-client to the 1.6.4 release.  But what do you do if you are running Rails 2.1/2.2 and want to take advantage of the massive speedup in 1.6.x?  You write some really ugly code that performs brain surgery on the Ruby environment to override ActiveSupport. [...]]]></description>
			<content:encoded><![CDATA[<p>Jemery Kemper <a href="http://github.com/rails/rails/commit/e56b3e4c0b60b2b86f5ca9c5e5a0b22fa34d37ab">recently upgraded</a> Rails 2.3&#8217;s vendored copy of memcache-client to the 1.6.4 release.  But what do you do if you are running Rails 2.1/2.2 and want to take advantage of the massive speedup in 1.6.x?  You write some really ugly code that performs brain surgery on the Ruby environment to override ActiveSupport.  Create <code>config/initializers/memcache-client-upgrade.rb</code> with this code:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Brain surgery to use our own version of memcache-client without</span>
<span style="color:#008000; font-style:italic;"># having to modify activesupport directly.</span>
<span style="color:#008000; font-style:italic;"># Unload any previous instance of the class</span>
<span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#CC00FF; font-weight:bold;">Object</span>.<span style="color:#9900CC;">const_defined</span>? <span style="color:#ff3333; font-weight:bold;">:MemCache</span>
  <span style="color:#CC00FF; font-weight:bold;">Object</span>.<span style="color:#9900CC;">instance_eval</span> <span style="color:#006600; font-weight:bold;">&#123;</span> remove_const <span style="color:#ff3333; font-weight:bold;">:MemCache</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#008000; font-style:italic;"># Pull in the exact version we want</span>
gem <span style="color:#996600;">'memcache-client'</span>, <span style="color:#996600;">'1.6.5'</span>
<span style="color:#008000; font-style:italic;"># Ensure that the memcache-client path is at the front of the loadpath</span>
<span style="color:#ff6633; font-weight:bold;">$LOAD_PATH</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>path<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#9966CC; font-weight:bold;">if</span> path =~ <span style="color:#006600; font-weight:bold;">/</span>memcache<span style="color:#006600; font-weight:bold;">-</span>client<span style="color:#006600; font-weight:bold;">/</span>
    <span style="color:#ff6633; font-weight:bold;">$LOAD_PATH</span>.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#ff6633; font-weight:bold;">$LOAD_PATH</span>.<span style="color:#9900CC;">unshift</span><span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#008000; font-style:italic;"># If Ruby thinks it's already loaded memcache.rb, force</span>
<span style="color:#008000; font-style:italic;"># a reload otherwise just require.</span>
<span style="color:#9966CC; font-weight:bold;">if</span> $<span style="color:#996600;">&quot;.find { |file| file =~ /<span style="color:#000099;">\A</span>memcache.rb<span style="color:#000099;">\Z</span>/ }
  load 'memcache.rb'
else
  require 'memcache'
end</span></pre></div></div>

<p>If someone knows of a cleaner way to do this, please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikeperham.com/2009/03/03/using-memcache-client-16x-in-rails-23/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>FiveRuns Dash, now with 100% more rimshot!</title>
		<link>http://www.mikeperham.com/2009/02/24/fiveruns-dash-now-with-100-more-rimshot/</link>
		<comments>http://www.mikeperham.com/2009/02/24/fiveruns-dash-now-with-100-more-rimshot/#comments</comments>
		<pubDate>Tue, 24 Feb 2009 20:44:36 +0000</pubDate>
		<dc:creator>Mike Perham</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.mikeperham.com/?p=190</guid>
		<description><![CDATA[I&#8217;m giving away a free copy of my iPhone app, Zinger, to every person who gets their app running with our new metrics service, Dash.  Just email me.  Steps (documented in more depth here):
1) Request an invite by signing up at https://dash.fiveruns.com
2) Log into Dash, create a new Rails application and note your [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m giving away a free copy of my iPhone app, <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=301088210&#038;mt=8">Zinger</a>, to every person who gets their app running with our new metrics service, <a href="http://dash.fiveruns.com">Dash</a>.  Just email me.  Steps (<a href="http://support.fiveruns.com/faqs/dash/rails">documented in more depth here</a>):</p>
<p>1) Request an invite by signing up at <a href="https://dash.fiveruns.com">https://dash.fiveruns.com</a><br />
2) Log into Dash, create a new Rails application and note your application token.<br />
3) Install the gem:</p>
<pre>
sudo gem install json
sudo gem install fiveruns-dash-rails -s http://gems.github.com
</pre>
<p>4) Add the gem to your <code>config/environment.rb</code></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#6666ff; font-weight:bold;">Rails::Initializer</span>.<span style="color:#9900CC;">run</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>config<span style="color:#006600; font-weight:bold;">|</span>
  config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">'json'</span> <span style="color:#008000; font-style:italic;"># needed because of a bug in json_pure</span>
  config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">'fiveruns-dash-rails'</span>,
             <span style="color:#ff3333; font-weight:bold;">:lib</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'fiveruns_dash_rails'</span>,
             <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'http://gems.github.com'</span></pre></div></div>

<p>5) Add the initializer file <code>config/initializers/dash.rb</code> to start Dash:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#9966CC; font-weight:bold;">defined</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">Fiveruns::Dash</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#6666ff; font-weight:bold;">Fiveruns::Dash::Rails</span>.<span style="color:#9900CC;">start</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:production</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'YOUR-APP-TOKEN-HERE'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This will start Dash in the production environment.  We don&#8217;t recommend using Dash in development mode.  If you have a staging environment, you can create a separate app for that environment and combine the two like so:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#9966CC; font-weight:bold;">defined</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">Fiveruns::Dash</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#6666ff; font-weight:bold;">Fiveruns::Dash::Rails</span>.<span style="color:#9900CC;">start</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:production</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'PROD-TOKEN'</span>, <span style="color:#ff3333; font-weight:bold;">:staging</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'STAGE-TOKEN'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Email me if you have problems &#8211; I&#8217;m happy to help people give Dash a test drive.  Dash is 100% free right now until we&#8217;ve worked out pricing models but rest assured there will always be a free tier so you don&#8217;t have to worry about your app costing you money in the future.  I hope your Dash test drive is full of rimshots with no sad trombones!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikeperham.com/2009/02/24/fiveruns-dash-now-with-100-more-rimshot/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
