Last few days I’ve been writing ebuilds for some gems. There are a lot of problems with packed gems and many of them was discussed before. I want to talk about only one of them - evil Rakefiles.
Here’s example of evil Rakefile:
require 'rake'
require 'spec'
require 'cucumber'
require 'cucumber/rake/task'
require 'spec/rake/spectask'
spec_files = Rake::FileList["spec/**/*_spec.rb"]
desc "Run specs"
Spec::Rake::SpecTask.new do |t|
t.spec_files = spec_files
t.spec_opts = ["-c"]
end
Cucumber::Rake::Task.new(:features) do |t|
t.cucumber_opts = "features --format progress"
end
task :default => [:spec, :features]
You see those requires at the top? It means that you can not even list available tasks if you don’t have rspec and cucumber installed.
Here’s the approach I propose. Write a stubs for tasks so that people could list tasks and run tasks without forcing them to install unnecessary stuff.
Like this:
require 'rake'
desc "Run specs"
task :spec do
unless Rake.application.lookup('real_spec')
require 'spec'
require 'spec/rake/spectask'
spec_files = Rake::FileList["spec/**/*_spec.rb"]
Spec::Rake::SpecTask.new(:real_spec) do |t|
t.spec_files = spec_files
t.spec_opts = ["-c"]
end
end
Rake.application['real_spec'].invoke
end
desc "Run features"
task :features do
unless Rake.application.lookup('real_features')
require 'cucumber'
require 'cucumber/rake/task'
Cucumber::Rake::Task.new(:real_features) do |t|
t.cucumber_opts = "features --format progress"
end
end
Rake.application['real_features'].invoke
end
task :default => [:spec, :features]
This Rakfile postpones requiring stuff until it’s really needed and so creating needed tasks and calling them. Yes this is a bit longer than previous variant but it also much nicer. Note, this is rather small Rakefile and it already depends on two gems I’ve seen Rakefiles that pull half a dozen gems for tests and about the same for docs. And each of those gems has their own dependencies. So I have to install a whole bunch of gems to just see the list of available tasks or run a task that is not related to tests or docs.
Be nice.