<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -5,6 +5,8 @@ Plow::Dependencies.warn_at_exit
 ###################################################################################################
 
 begin
+  # TODO experiment with how rubygems activates gems by version requirement in ruby 1.9.1.
+  # gem 'jeweler', '1.3.0'
   require 'jeweler'
   Jeweler::Tasks.new do |gem|
     # The gem object is a kind of Gem::Specification </diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -1,20 +1,45 @@
 # encoding: UTF-8
 
 class Plow
-  # In order to load without a syntax error, this file needs to be compatible with ruby &gt;= 1.8.6
-  # Dependencies are a snapshot in time
+  # `Plow::Dependencies` is a class-methods-only **singleton** class that performs both strict
+  # parse-time dependency checking and simple, elegant run-time dependency warning.
+  #
+  # My preferred mental model is to consider software library dependencies as a snapshot in time.
+  # I also make the assumption, sometimes incorrectly, that a newer version of a software library
+  # is not always a better version.
+  #
+  # `Plow::Dependencies` automatically enforces a strict parse-time check for the
+  # `REQUIRED_RUBY_VERSION` on both application and development processes for the `Plow` library.
+  # (i.e. `bin/plow`, `rake`, `spec`, etc)  Because of this, I've ensured this file is
+  # syntactically compatible with Ruby 1.8.6 or higher.
+  #
+  # Currently, `Plow` does **not** enforce strict parse-time version checking on `DEVELOPMENT_GEMS`.
+  # In the future, I would like to experiment with using RubyGems and the `Kernel#gem` method to
+  # this end.  For now, each developer is responsible for ensuring the correct versions of their
+  # necessary development gems are located in the `$LOAD_PATH` on their system.
+  #
+  # When a gem is required, but a `LoadError` is raised, and rescued, `Plow::Dependencies` can be
+  # incorporated into the process to warn a developer of missing development features.  Even with a
+  # few methods --  `.create_warning_for` and `.warn_at_exit` --  users are automatically warned, in
+  # this case at the moment of termination, about gems that could not found be in the `$LOAD_PATH`.
+  #  Using `Plow::Dependencies` is **not** a mandatory inclusion for all gem requirements, merely a
+  # guide to help developers quickly see obstacles in their path.
+  #
+  # @example Simple usage with the Jeweler gem
+  #   Plow::Dependencies.warn_at_exit
+  #   begin
+  #     require 'jeweler'
+  #     # work with the Jeweler gem
+  #   rescue LoadError =&gt; e
+  #     Plow::Dependencies.create_warning_for(e)
+  #   end
+  #
+  # @see Plow::Dependencies.create_warning_for
+  # @see Plow::Dependencies.warn_at_exit  
   class Dependencies
-    # for now, starting with 1.9.1 but would like to ensure compatibility for &gt;= 1.9.1
+    # For now, starting with Ruby 1.9.1 but I would like to experiment with compatibility with Ruby &gt;= 1.9.1 in the future.
     REQUIRED_RUBY_VERSION = '1.9.1'
     
-    # parse-time guard
-    unless RUBY_VERSION &gt;= REQUIRED_RUBY_VERSION
-      abort &lt;&lt;-ERROR
-This library requires at least Ruby #{REQUIRED_RUBY_VERSION}, but you're using #{RUBY_VERSION}.
-Please see http://www.ruby-lang.org/
-      ERROR
-    end
-    
     # bluecloth is a hidden yard dependency for markdown support
     DEVELOPMENT_GEMS = {
       :jeweler   =&gt; '1.3.0',
@@ -28,17 +53,17 @@ Please see http://www.ruby-lang.org/
       :spec =&gt; :rspec
     }
     
-    @@warnings_cache = []
-    
-    # Empties the warnings cache
+    # Empties the warnings cache.  This method is called when the class is required.
     def self.destroy_warnings
       @@warnings_cache = []
     end
+    destroy_warnings
     
-    # Creates and caches a warning from a `LoadError` exception.  Warnings are only created for known development gem dependencies.
+    # Creates and caches a warning from a `LoadError` exception.  Warnings are only created for
+    # known development gem dependencies.
     #
-    # @param error LoadError The error object
-    # @raise RuntimeError something
+    # @param [LoadError] error A rescued exception
+    # @raise [RuntimeError] Raised when the `LoadError` argument is an unknown development gem.
     def self.create_warning_for(error)
       error.message.match(/no such file to load -- (\w*)/) do |match_data|
         file_name = match_data[1].to_sym
@@ -54,7 +79,15 @@ Please see http://www.ruby-lang.org/
       end
     end
     
-    # Displays a warning message to the user on the standard output channel
+    # Displays a warning message to the user on the standard output channel if there are warnings
+    # to render.
+    #
+    # @example Sample warning message
+    #   The following development gem dependencies could not be found. Without them, some available development features are missing:
+    #   jeweler --version '1.3.0'
+    #   rspec --version '1.2.9'
+    #   yard --version '0.2.3.5'
+    #   bluecloth --version '2.0.5'
     def self.render_warnings
       unless @@warnings_cache.empty?
         message = []
@@ -64,9 +97,27 @@ Please see http://www.ruby-lang.org/
       end
     end
     
-    # Renders a warning message at exit
+    # Attaches a call to `render_warnings` to `Kernel#at_exit`
     def self.warn_at_exit
       at_exit { render_warnings }
     end
+    
+    private
+    
+    # Checks that the version of the current Ruby process matches the `REQUIRED_RUBY_VERSION`.
+    # This method is automatically invoked at the first time this class is required, ensuring the
+    # correct Ruby version at parse-time.
+    #
+    # @param [String] ruby_version Useful for automated specifications.  Defaults to `RUBY_VERSION`.
+    # @raise [SystemExit] Raised, with a message, when the process is using an incorrect version of Ruby.
+    def self.check_ruby_version(ruby_version = RUBY_VERSION)
+      unless ruby_version == REQUIRED_RUBY_VERSION
+        abort &lt;&lt;-ERROR
+This library requires Ruby #{REQUIRED_RUBY_VERSION}, but you're using #{ruby_version}.
+Please visit http://www.ruby-lang.org/ for installation instructions.
+        ERROR
+      end
+    end
+    check_ruby_version
   end
 end</diff>
      <filename>lib/plow/dependencies.rb</filename>
    </modified>
    <modified>
      <diff>@@ -35,6 +35,50 @@ describe Plow::Dependencies do
   
   ##################################################################################################
   
+  describe '.check_ruby_version (private)' do
+    before(:each) do
+      $stderr = StringIO.new
+    end
+    
+    after(:each) do
+      $stderr = STDERR
+    end
+    
+    def expected_message(version)
+      @expected_message = &lt;&lt;-ERROR
+This library requires Ruby 1.9.1, but you're using #{version}.
+Please visit http://www.ruby-lang.org/ for installation instructions.
+      ERROR
+    end
+    
+    it &quot;should abort for ruby 1.8.6&quot; do
+      version = '1.8.6'
+      lambda { Plow::Dependencies.send(:check_ruby_version, version) }.should raise_error(SystemExit, expected_message(version))
+    end
+    
+    it &quot;should abort for ruby 1.8.7&quot; do
+      version = '1.8.7'
+      lambda { Plow::Dependencies.send(:check_ruby_version, version) }.should raise_error(SystemExit, expected_message(version))
+    end
+    
+    it &quot;should abort for ruby 1.9.0&quot; do
+      version = '1.9.0'
+      lambda { Plow::Dependencies.send(:check_ruby_version, version) }.should raise_error(SystemExit, expected_message(version))
+    end
+    
+    it &quot;should not abort for ruby 1.9.1&quot; do
+      version = '1.9.1'
+      lambda { Plow::Dependencies.send(:check_ruby_version, version) }.should_not raise_error(SystemExit, expected_message(version))
+    end
+    
+    it &quot;should abort for ruby 1.9.2&quot; do
+      version = '1.9.2'
+      lambda { Plow::Dependencies.send(:check_ruby_version, version) }.should raise_error(SystemExit, expected_message(version))
+    end
+  end
+  
+  ##################################################################################################
+  
   describe '.destroy_warnings' do
     it &quot;should empty the warnings cache&quot; do
       Plow::Dependencies.class_variable_get(:@@warnings_cache).should be_empty
@@ -110,6 +154,12 @@ yard --version '0.2.3.5'
 bluecloth --version '2.0.5'
       MESSAGE
     end
+    
+    it &quot;should not display a warning message to the user if there are no warnings in the cache&quot; do
+      Plow::Dependencies.destroy_warnings
+      Plow::Dependencies.render_warnings
+      $stdout.string.should == ''
+    end
   end
   
   ##################################################################################################
@@ -117,7 +167,8 @@ bluecloth --version '2.0.5'
   describe '.warn_at_exit' do
     it &quot;I'm not aware of a technique to test Kernel#at_exit&quot; do
       Plow::Dependencies.should_receive(:at_exit)
-      # how to specify that #at_exit receives a block?
+      # TODO how to specify that #at_exit receives a block?
+      # maybe i can intercept the block, execute it and test the output?
       Plow::Dependencies.warn_at_exit
     end
   end</diff>
      <filename>spec/plow/dependencies_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>4b445b24c05bba59235c5581ebd3ea1c2af84821</id>
    </parent>
  </parents>
  <author>
    <name>Ryan Sobol</name>
    <email>code@ryansobol.com</email>
  </author>
  <url>http://github.com/ryansobol/plow/commit/35ada7cd1a66948622a472e24ef89279d455c2f2</url>
  <id>35ada7cd1a66948622a472e24ef89279d455c2f2</id>
  <committed-date>2009-11-05T17:22:40-08:00</committed-date>
  <authored-date>2009-11-05T17:22:40-08:00</authored-date>
  <message>* Rakefile
  * added a TODO about experimenting with Kernel#gem in the future
* lib/plow/dependencies.rb
  * significant improvements to the yardoc
  * self.check_ruby_version
    * a private method that encapsulates the parse-time checking for the correct ruby version
    * called when the class is loaded (no change in implementation)
  * .destroy_warnings is called when the class is loaded (no change in implementation)
* spec/plow/dependencies_spec.rb
  * added a series of specs describing .check_ruby_version
  * added a spec that describes &quot;should not display a warning message to the user if there are no warnings in the cache&quot;
  * added few more comments to the spec that describes &quot;I'm not aware of a technique to test Kernel#at_exit&quot;</message>
  <tree>ed2ec719a36a08b8c891078a656df2bf82366083</tree>
  <committer>
    <name>Ryan Sobol</name>
    <email>code@ryansobol.com</email>
  </committer>
</commit>
