<?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>Virtuous Code &#187; rubygems</title>
	<atom:link href="http://devblog.avdi.org/tag/rubygems/feed/" rel="self" type="application/rss+xml" />
	<link>http://devblog.avdi.org</link>
	<description>&#34;The three virtues of a programmer: laziness, impatience, and hubris&#34; -- Larry Wall</description>
	<lastBuildDate>Tue, 21 May 2013 18:19:00 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Loading plugins with Rubygems</title>
		<link>http://devblog.avdi.org/2011/08/10/loading-plugins-with-rubygems/</link>
		<comments>http://devblog.avdi.org/2011/08/10/loading-plugins-with-rubygems/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 13:00:04 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rubygems]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=1526</guid>
		<description><![CDATA[Let&#8217;s say you have a Rubygem named &#8220;blorf&#8221;. You want to enable other developers to write plugins in the forms of Rubygems of their own. For the end user, loading the plugins should be as simple as writing: require 'blorf' &#8230; <a href="http://devblog.avdi.org/2011/08/10/loading-plugins-with-rubygems/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Let&#8217;s say you have a Rubygem named &#8220;blorf&#8221;. You want to enable other developers to write plugins in the forms of Rubygems of their own. For the end user, loading the plugins should be as simple as writing:</p>
<pre name="code" class="ruby">
require 'blorf'
require 'blorf-git'
require 'blorf-twitter'
require 'blorf-cowsay'
# ...
Blorf.activate! # activate any loaded plugins
</pre>
<p>In order to make this work, blorf needs to look for files matching a certain path pattern inside other loaded gems. If a gem contains a file matching &#8216;lib/blorf/plugins/**/*/rb&#8217;, it should be loaded when blorf is loaded.</p>
<p>Rubygems provides <a href="http://rubygems.rubyforge.org/rubygems-update/Gem.html#method-c-find_files">a method</a> <em>which</em> almost fits the bill. The only problem with <a href="http://rubygems.rubyforge.org/rubygems-update/Gem.html#method-c-find_files">Gem#find_files</a> is that it will find files matching that pattern in <em>all</em> installed gems&#8211;not just in the gems that have been loaded. If you have multiple versions of a Gem installed it will find paths in all the installed versions. We want the end user to control gem versions, so this method doesn&#8217;t help us.</p>
<p>Here&#8217;s some code which will look in only loaded gems for files matching a given globbing pattern. It&#8217;s complicated by the fact that the Rubygems API for this changed (for the better) at version 1.8.0. This code has been tried on Rubygems versions 1.8.7 and 1.6.2.</p>
<pre name="code"  class="ruby">
  def find_files_in_active_gems(glob)
    rubygems_version = Gem::Version.new(Gem::VERSION)
    if rubygems_version >= Gem::Version.new("1.8.0")
      # somewhat messy new version
      Gem.loaded_specs.values.inject([]){|ps,s|
        ps.concat(s.matches_for_glob(glob))
      }
     else
      # even messier old version
      Gem.loaded_specs.values.  # get the gemspecs for active gems
        map{|s|                 # find the lib glob pattern for each gem
          Gem.searcher.lib_dirs_for(s)
        }.flatten.map{|d|       # append the glob pattern and look for matches
          Dir.glob(File.join(d, glob))
        }.flatten
    end
  end
</pre>
<p>Yes, this is messy first-working-version exploratory code. It could stand to be cleaned up.</p>
<p>At Eric Hodel&#8217;s encouragement I&#8217;ve <a href="https://github.com/rubygems/rubygems/issues/150">submitted a ticket</a> which, if accepted, would reduce this to a one-liner.</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2011/08/10/loading-plugins-with-rubygems/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>
