Permalink
Browse files

Initial implementation

  • Loading branch information...
1 parent f64750b commit b0497f66e471e104c8e0a466906bb4ee4c37d724 Tony Arcieri committed Jun 8, 2009
View
@@ -0,0 +1,12 @@
+require 'rake'
+require 'rake/clean'
+
+Dir['tasks/**/*.rake'].each { |task| load task }
+
+task :default => :spec
+
+task :clean do
+ %w[pkg coverage].each do |dir|
+ rm_rf dir
+ end
+end
View
@@ -0,0 +1,53 @@
+module LoadGlob
+ # Load all files matching the given glob, handling dependencies between
+ # the files gracefully
+ def load_glob(glob)
+ files = Dir[glob].map { |file| File.expand_path file }
+
+ begin
+ failed = []
+ first_name_error = nil
+
+ # Attempt to load each file, rescuing which ones raise NameError for
+ # undefined constants. Keep trying to successively reload files that
+ # previously caused NameErrors until they've all been loaded or no new
+ # files can be loaded, indicating unresolvable dependencies.
+ files.each do |file|
+ begin
+ require file
+ rescue NameError => ex
+ failed << file
+ first_name_error ||= ex
+ rescue ArgumentError => ex
+ # Work around ActiveSuport freaking out... *sigh*
+ #
+ # ActiveSupport sometimes throws these exceptions and I really
+ # have no idea why. Code loading will work successfully if these
+ # exceptions are swallowed, although I've run into strange
+ # nondeterministic behaviors with constants mysteriously vanishing.
+ # I've gone spelunking through dependencies.rb looking for what
+ # exactly is going on, but all I ended up doing was making my eyes
+ # bleed.
+ #
+ # FIXME: If you can understand ActiveSupport's dependencies.rb
+ # better than I do I would *love* to find a better solution
+ raise ex unless ex["is not missing constant"]
+ STDERR.puts "Warning: load_glob swallowed ActiveSupport 'is not missing constant' error"
+ STDERR.puts ex.backtrace[0..9]
+ end
+ end
+
+ # If this pass didn't resolve any NameErrors, we've hit an unresolvable
+ # dependency, so raise one of the exceptions we encountered.
+ if failed.size == files.size
+ raise first_name_error
+ else
+ files = failed
+ end
+ end until failed.empty?
+
+ true
+ end
+end
+
+include LoadGlob
@@ -0,0 +1 @@
+class A < C; end
@@ -0,0 +1 @@
+class B < A; end
@@ -0,0 +1 @@
+class C; end
@@ -0,0 +1 @@
+class D < C; end
@@ -0,0 +1 @@
+class A < C; end
@@ -0,0 +1 @@
+class B < A; end
@@ -0,0 +1 @@
+class C < Nonexistent; end
@@ -0,0 +1 @@
+class D < C; end
@@ -0,0 +1,18 @@
+require File.dirname(__FILE__) + '/../lib/load_glob.rb'
+
+describe "load_glob" do
+ it "handles load ordering when dependencies are resolvable" do
+ load_glob File.dirname(__FILE__) + '/fixtures/resolvable/*.rb'
+
+ defined?(A).should == "constant"
+ defined?(B).should == "constant"
+ defined?(C).should == "constant"
+ defined?(D).should == "constant"
+ end
+
+ it "raises NameError if dependencies can't be resolved" do
+ proc do
+ load_glob File.dirname(__FILE__) + '/fixtures/unresolvable/*.rb'
+ end.should raise_error(NameError)
+ end
+end
View
@@ -0,0 +1,16 @@
+require 'spec/rake/spectask'
+
+FILES = Dir['spec/*_spec.rb']
+
+desc "Run RSpec against the package's specs"
+Spec::Rake::SpecTask.new(:spec) do |t|
+ t.spec_opts = %w(-fs -c)
+ t.spec_files = FILES
+end
+
+desc "Run RSpec generate a code coverage report"
+Spec::Rake::SpecTask.new(:coverage) do |t|
+ t.spec_files = FILES
+ t.rcov = true
+ t.rcov_opts = %w[--rails --exclude gems,spec]
+end

0 comments on commit b0497f6

Please sign in to comment.