<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>something learned comments on Plugin Conventions Redux</title>
    <link>http://somethinglearned.com/</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>something learned comments</description>
    <item>
      <title>"Plugin Conventions Redux" by trevor</title>
      <description>&lt;p&gt;Last week Jamis &lt;a href="http://article.gmane.org/gmane.comp.lang.ruby.rails/26945"&gt;responded&lt;/a&gt; to my &lt;a href="http://www.somethinglearned.com/articles/2005/10/26/rails-plugins-will-somebody-please-think-of-the-children"&gt;post&lt;/a&gt; about plugin naming conventions.&lt;/p&gt;


	&lt;p&gt;If any of the rest of this post is going to make sense you&amp;#8217;d better check out the above links first.&lt;/p&gt;


	&lt;p&gt;Anyhow, there&amp;#8217;s been a bit more mailing-list to-ing and fro-ing about the fact that Jamis&amp;#8217; suggestion has problems, which I&amp;#8217;ll write about today.&lt;/p&gt;


	&lt;h3&gt;When is this an issue?&lt;/h3&gt;


	&lt;p&gt;This is something that we should get out of the way here and now.&lt;/p&gt;


	&lt;p&gt;If your plugin is &lt;em&gt;just&lt;/em&gt; mixing-in methods for a &lt;a href="http://odeo.com/audio/306705/view"&gt;DSL&lt;/a&gt; (excellent link, by the way) like a new ActiveRecord &amp;#8216;Acts&amp;#8217; &amp;#8211; or you have some other situation where you only have have a couple of files to &amp;#8216;require&amp;#8217;, it&amp;#8217;s a lot simpler and clearer to just &lt;code&gt;require&lt;/code&gt; those files explicitly in your &lt;code&gt;init.rb&lt;/code&gt;.  For example:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
plugins/enumerations_mixin/init.rb
plugins/enumerations_mixin/lib/proto_cool/enumerations/acts_enumerated.rb
plugins/enumerations_mixin/lib/proto_cool/enumerations/has_enumerated.rb
plugins/enumerations_mixin/lib/proto_cool/enumerations/virtual_enumerations.rb
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;My &lt;code&gt;init.rb&lt;/code&gt; file will look like this:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
require 'proto_cool/enumerations/acts_enumerated'
require 'proto_cool/enumerations/has_enumerated'
require 'proto_cool/enumerations/virtual_enumerations'
ActiveRecord::Base.class_eval do
  include ProtoCool::Enumerations::ActsEnumerated
  include ProtoCool::Enumerations::HasEnumerated
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;Complex Hierarchies&lt;/h3&gt;


	&lt;p&gt;But what if your plugin has a &lt;em&gt;lot&lt;/em&gt; of files to require?  You may be tempted to organize your &lt;code&gt;require&lt;/code&gt;s as Jamis suggested in his email.  After all, it looks a &lt;em&gt;lot&lt;/em&gt; like how rails organizes its own &lt;code&gt;require&lt;/code&gt; calls.  A stripped down example of a complex hierarchy might be:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
lib/jamis
lib/jamis.rb
lib/jamis/buck
lib/jamis/buck.rb
lib/jamis/buck/my_module.rb
lib/jamis/buck/my_other_module.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;code&gt;lib/jamis.rb&lt;/code&gt; would contain:

&lt;code&gt;require 'jamis/buck'&lt;/code&gt;

	&lt;p&gt;and &lt;code&gt;lib/jamis/buck.rb&lt;/code&gt; would contain:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
require 'jamis/buck/my_module'
require 'jamis/buck/my_other_module'
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The idea is that you could simply refer to &lt;code&gt;Jamis::Buck::MyModule&lt;/code&gt; or &lt;code&gt;Jamis::Buck::MyOtherModule&lt;/code&gt; without having to do any explicit &lt;code&gt;require&lt;/code&gt; calls in the code that first references those modules.  Rails will automagically &amp;#8220;&lt;code&gt;require 'jamis'&lt;/code&gt;&amp;#8221; the first time you reference the &lt;code&gt;Jamis&lt;/code&gt; module.&lt;/p&gt;


	&lt;p&gt;The problem with this approach is that once &amp;#8220;&lt;code&gt;require 'jamis'&lt;/code&gt;&amp;#8221; has been called, all subsequent calls will have no effect, even if there are many &lt;code&gt;jamis.rb&lt;/code&gt; files in the &lt;code&gt;$LOAD_PATH&lt;/code&gt;.  If Jamis releases another plugin that relies on automagic &lt;code&gt;require&lt;/code&gt;s his full set of classes won&amp;#8217;t be loaded.&lt;/p&gt;


	&lt;h3&gt;Strategies&lt;/h3&gt;


	&lt;p&gt;There are a number of strategies you can use to work around this.  First of all, you can just use explicit requires in your &lt;code&gt;init.rb&lt;/code&gt; file.  You can still use Jamis&amp;#8217; method for everything in your module namespace that is &lt;em&gt;unique to the current plugin&lt;/em&gt; though.  Using the above example you&amp;#8217;d just get rid of  &lt;code&gt;jamis.rb&lt;/code&gt; and in your &lt;code&gt;init.rb&lt;/code&gt; file you&amp;#8217;d have a single &amp;#8220;&lt;code&gt;require 'jamis/buck'&lt;/code&gt;&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;Another strategy would be to use &lt;code&gt;load&lt;/code&gt; instead of &lt;code&gt;require&lt;/code&gt; for all files that you (as a plugin author) know will appear in many places in the &lt;code&gt;$LOAD_PATH&lt;/code&gt;.  You could keep your &lt;code&gt;jamis.rb&lt;/code&gt; file but in your &lt;code&gt;init.rb&lt;/code&gt; you would simply say &amp;#8220;&lt;code&gt;load 'jamis.rb'&lt;/code&gt;&amp;#8221;.&lt;/p&gt;


	&lt;h3&gt;Pie in the Sky&lt;/h3&gt;


	&lt;p&gt;There&amp;#8217;s something slightly non-intuitive about the above strategies though.  I had one of those &amp;#8220;wouldn&amp;#8217;t it be nice if&amp;#8230;&amp;#8221; moments and knocked together some code that allows &lt;em&gt;this&lt;/em&gt;:&lt;/p&gt;


in &lt;code&gt;lib/jamis.rb&lt;/code&gt;
&lt;pre&gt;&lt;code&gt;
module Jamis
  include Dependencies::AutoRequire
  auto_require 'buck'
end
&lt;/code&gt;&lt;/pre&gt;

in &lt;code&gt;lib/jamis/buck.rb&lt;/code&gt;
&lt;pre&gt;&lt;code&gt;
module Jamis::Buck
  include Dependencies::AutoRequire
  auto_require 'my_module'
  auto_require 'my_other_module'
end
&lt;/code&gt;&lt;/pre&gt;

in &lt;code&gt;init.rb&lt;/code&gt;
&lt;pre&gt;&lt;code&gt;
load 'jamis.rb'
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;There&amp;#8217;s a couple of &amp;#8216;nice&amp;#8217; features here.  First of all, if you &lt;code&gt;auto_require&lt;/code&gt; something, it will use the module name to construct the full &lt;code&gt;require&lt;/code&gt; call.  So &amp;#8220;&lt;code&gt;Jamis::Buck.auto_require 'my_module'&lt;/code&gt;&amp;#8221; will result in a &amp;#8220;&lt;code&gt;require 'jamis/buck/my_module'&lt;/code&gt;&amp;#8221; call.&lt;/p&gt;


	&lt;p&gt;Second, if you &amp;#8220;&lt;code&gt;auto_require 'buck'&lt;/code&gt;&amp;#8221; and there is &lt;em&gt;both&lt;/em&gt; a &lt;code&gt;buck&lt;/code&gt; directory and a &lt;code&gt;buck.rb&lt;/code&gt; file the &lt;code&gt;require&lt;/code&gt; will be treated differently.  The resulting &lt;code&gt;require&lt;/code&gt; call guarantees your particular &lt;code&gt;buck.rb&lt;/code&gt; file is loaded even if there is another &lt;code&gt;buck.rb&lt;/code&gt; file in the &lt;code&gt;$LOAD_PATH&lt;/code&gt; that has already had &amp;#8220;&lt;code&gt;require 'jamis/buck'&lt;/code&gt;&amp;#8221; called against it.&lt;/p&gt;


	&lt;p&gt;You may be wondering why I didn&amp;#8217;t just add the auto_require method to the &lt;code&gt;Module&lt;/code&gt; class.  I could have, but it makes me feel &lt;em&gt;dirty&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;The funny thing is, in order for this to be useful to me, I&amp;#8217;ll either have to ship and&amp;#8230; um&amp;#8230; &lt;code&gt;require&lt;/code&gt; a file that contains &lt;code&gt;Dependencies::AutoRequire&lt;/code&gt; with each of my plugins &amp;#8211; or I&amp;#8217;ll have to convince the rails core team that &lt;code&gt;Dependencies::AutoRequire&lt;/code&gt; would be beneficial to more than just &lt;em&gt;me&lt;/em&gt;.  Well, &lt;em&gt;I&lt;/em&gt; think it&amp;#8217;s funny&amp;#8230;&lt;/p&gt;

</description>
      <pubDate>Mon, 31 Oct 2005 13:59:00 EST</pubDate>
      <guid>&lt;a href="/articles/2005/10/31/plugin-conventions-redux"&gt;Plugin Conventions Redux&lt;/a&gt;</guid>
      <link>&lt;a href="/articles/2005/10/31/plugin-conventions-redux"&gt;Plugin Conventions Redux&lt;/a&gt;</link>
    </item>
  </channel>
</rss>
