<?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>Technical Ramblings &#187; rails 3</title>
	<atom:link href="http://jonswope.com/tag/rails-3/feed/" rel="self" type="application/rss+xml" />
	<link>http://jonswope.com</link>
	<description>More information than you cared to know about whatever I find cool</description>
	<lastBuildDate>Fri, 07 Jan 2011 04:58:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Rails 3 Engines/Plugins and Static Assets</title>
		<link>http://jonswope.com/2010/07/25/rails-3-engines-plugins-and-static-assets/</link>
		<comments>http://jonswope.com/2010/07/25/rails-3-engines-plugins-and-static-assets/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 21:58:12 +0000</pubDate>
		<dc:creator>Jon Swope</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[middleware]]></category>
		<category><![CDATA[rails 3]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://jonswope.com/?p=68</guid>
		<description><![CDATA[Engine-ish One of the big changes in Rails 3 is the move to &#8220;everything is an engine&#8221;.  You end up reading a lot about this in relation to plugins, mentioning how this architecture makes it so you can easily embed entire rails applications into others since they&#8217;re all just derivatives of Railties.  While this holds [...]]]></description>
			<content:encoded><![CDATA[<h3>Engine-ish</h3>
<p>One of the big changes in Rails 3 is the move to &#8220;everything is an engine&#8221;.  You end up reading a lot about this in relation to plugins, mentioning how this architecture makes it so you can easily embed entire rails applications into others since they&#8217;re all just derivatives of Railties.  While this holds true for very simple cases, you&#8217;ll quickly find simply creating a rails app, and sticking it in vendor/plugins doesn&#8217;t work the way you&#8217;d expect from reading about it.  You really do need to create your plugin in a certain way to actually make it work.  <a href="http://www.themodestrubyist.com/2010/03/05/rails-3-plugins---part-2---writing-an-engine/" target="_blank">Over here</a> is a good writeup on creating a Rails Engine based plugin installed as a gem.</p>
<h3>Serving Static Assets</h3>
<p>Now, serving static assets from your plugin is a bit on the unintuitive side, and likely for a good reason.  <span style="color: #ff0000;">You generally do not want to do this for any kind of production system.</span> However, like most rules, there are times when breaking them makes pragmatic sense.  In this use case we have an internal tool that we want to be able to easily extend.  The maximum number of concurrent users will likely be in low teens, and serving static assets through the rails app is a non-issue.  Extending the app includes providing views, controllers, models, routes, and images.  The first three are extremely straightforward and intuitive, routes use a slightly different enclosing syntax in an Engine, but are otherwise identical.  Images, however are a bit tricky.</p>
<p>There are two ways to create an Engine based plugin, and they are a bit incompatible with each other.  You can either install your plugin as a gem, or as a plugin in the app.  In both cases, you are going to use the ActionDispatch::Static middleware to serve your content.  I am also assuming that you are placing your content in the &#8220;public&#8221; directory in the root of your plugin&#8217;s file structure.</p>
<h4>Gem Based Plugin</h4>
<p>A gem based plugin is initialized via the definition of itself in your plugin&#8217;s lib directory.  You can see an example of this below.  In order to set it up correctly you should put your middleware line in an initializer in your declaration:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> MyEngine
  <span style="color:#9966CC; font-weight:bold;">class</span> Engine <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Rails::Engine</span>
    initializer <span style="color:#996600;">&quot;static assets&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>app<span style="color:#006600; font-weight:bold;">|</span>
      app.<span style="color:#9900CC;">middleware</span>.<span style="color:#9900CC;">use</span> ::<span style="color:#6666ff; font-weight:bold;">ActionDispatch::Static</span>, <span style="color:#996600;">&quot;#{root}/public&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h4>In App Plugin</h4>
<p>Unfortunately, if the above file exists in a plugin installed to vendor/plugins your app will fail to load.  This is because rails automatically assumes all plugins are Engines, and initializes them as instances of the Plugin class which inherits from Engine.  It will autoload everything in lib, see the declaration, and then fail out with the incredible error message &#8220;[Your Plugin] is a Railtie/Engine and cannot be installed as plugin&#8221;.  Which is somewhat misleading since a plugin <em>is</em> an Engine, just not explicitly.</p>
<p>To get around this issue, you just have to move where you do your initialization and setup. Inside your plugin&#8217;s init.rb (which should be in the root of your plugin&#8217;s file structure) is where you can do this kind of stuff.  Rails boots your Plugin, and then loads this file with the variable &#8220;config&#8221; set for you to do your work.  So it&#8217;s simply:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">config.<span style="color:#9900CC;">middleware</span>.<span style="color:#9900CC;">use</span> ::<span style="color:#6666ff; font-weight:bold;">ActionDispatch::Static</span>, <span style="color:#996600;">&quot;#{root}/public&quot;</span></pre></div></div>

<h4>Load Order</h4>
<p>I strongly recommend using middleware.use as it will place your middleware after the parent app, and therefore will cause your plugins assets to be of lower priority than everything else in the stack.  This means that files in the parent app&#8217;s public directory will load instead of the plugin&#8217;s in the case of a conflicting name.  You still have options though.  To give your plugin&#8217;s static files priority over everything except the parent app&#8217;s static files, use:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">middleware.<span style="color:#9900CC;">insert_after</span> ::<span style="color:#6666ff; font-weight:bold;">ActionDispatch::Static</span>, ::<span style="color:#6666ff; font-weight:bold;">ActionDispatch::Static</span>, <span style="color:#996600;">&quot;#{root}/public&quot;</span></pre></div></div>

<p>To give your plugin top priority in static asset serving use:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">middleware.<span style="color:#9900CC;">insert_before</span> ::<span style="color:#6666ff; font-weight:bold;">ActionDispatch::Static</span>, ::<span style="color:#6666ff; font-weight:bold;">ActionDispatch::Static</span>, <span style="color:#996600;">&quot;#{root}/public&quot;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://jonswope.com/2010/07/25/rails-3-engines-plugins-and-static-assets/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
	</channel>
</rss>

