Ruby project howto
This section is a brief howto for automating some common tasks like running rdoc, unit tests and packaging.
We are assuming a project with the following directories and files:
Rantfile
README
bin/
wgrep
lib/
wgrep.rb
test/
tc_wgrep.rb
You can find this little project in test/project_rb1 directory of the Rant package. You‘ll probably have more files in your project, but we will try to write our Rantfile as generic as possible:
import %w(rubytest rubydoc rubypackage clean)
lib_files = sys["lib/**/*.rb"]
dist_files = lib_files + sys["README", "rantfile.rb", "{test,bin}/*"]
desc "Run unit tests."
gen RubyTest do |t|
t.test_dir = "test"
t.pattern = "tc_*.rb"
end
desc "Generate html documentation."
gen RubyDoc do |t|
t.opts = %w(--title wgrep --main README README)
end
desc "Create packages."
gen RubyPackage, "wgrep" do |t|
t.version = "1.0.0"
t.summary = "Simple grep program."
t.files = dist_files
t.bindir = "bin"
t.executable = "wgrep"
t.package_task
end
desc "Remove autogenerated and backup files."
gen Clean
var[:clean].include "doc", "pkg", "*~"
To verify how our tasks are named:
% rant -T
rant test # Run unit tests.
rant doc # Generate html documentation.
rant package # Create packages.
rant clean # Remove autogenerated and backup files.
Let’s examine the code by running the tasks:
% rant test
cd test
ruby -I /home/stefan/Ruby/lib/rant/test/project_rb1/lib -S testrb tc_wgrep.rb
Loaded suite tc_wgrep.rb
Started
.
Finished in 0.004588 seconds.
1 tests, 2 assertions, 0 failures, 0 errors
cd -
The RubyTest generator automatically added the lib directory to the LOAD_PATH for testing. Because we have set the test_dir to "test", it changes to the test directory, evaluates the pattern to collect the testcases and then runs the testrb command.
To format the documentation:
% rant doc
README:
wgrep.rb: mcc....
Generating HTML...
Files: 2
Classes: 2
Modules: 1
Methods: 4
Elapsed: 0.335s
All of this output originates from RDoc. The RubyDoc generator gives the lib directory and additionally the opts we have set to RDoc.
The most interesting task is the package task:
% rant package
mkdir pkg
mkdir pkg/wgrep-1.0.0
mkdir -p pkg/wgrep-1.0.0/lib
mkdir -p pkg/wgrep-1.0.0/test
mkdir -p pkg/wgrep-1.0.0/bin
ln lib/wgrep.rb pkg/wgrep-1.0.0/lib/wgrep.rb
ln rantfile.rb pkg/wgrep-1.0.0/rantfile.rb
ln README pkg/wgrep-1.0.0/README
ln test/text pkg/wgrep-1.0.0/test/text
ln test/tc_wgrep.rb pkg/wgrep-1.0.0/test/tc_wgrep.rb
ln bin/wgrep pkg/wgrep-1.0.0/bin/wgrep
touch pkg/wgrep-1.0.0
cd pkg
tar zcf wgrep-1.0.0.tar.gz wgrep-1.0.0
cd -
cd pkg
zip -yqr wgrep-1.0.0.zip wgrep-1.0.0
cd -
Successfully built RubyGem
Name: wgrep
Version: 1.0.0
File: wgrep-1.0.0.gem
mv wgrep-1.0.0.gem pkg
This is what it does:
- Link all package files to the new folder pkg/wgrep-1.0.0.
- Create a tar.gz file in the pkg directory.
- Create a .zip file in the pkg directory.
- Create a RubyGem in pkg.
The RubyGem will only be created if RubyGems is available on your system.
The gem specification also contains the RDoc options we have given to the RubyDoc generator and the has_rdoc attribute is set to true. No need to duplicate this information in our Rantfile.
And if we want to remove all autogenerated files (and backup files) we run the clean task:
% rant clean
rm -rf doc
rm -rf pkg
rm -f README~
More about the RubyPackage generator
The argument given to the RubyPackage generator is used as package name (here "wgrep"):
gen RubyPackage, "wgrep" do |t|
The line which actually creates the package task(s) is this one:
t.package_task
Optionally you may give it a task name as argument:
t.package_task :release
Now you can run rant with the argument "release" for packaging:
% rant release
If you want to change the package directory (which defaults to pkg) you can set the pkg_dir attribute:
t.pkg_dir = "packages"
t.package_task
Perhaps you want to specify explicetely what packages you want to build. To accomplish this, each of the following methods listed takes an optional task name as argument:
t.tar_task # create tar.gz archive, task name defaults to "tar"
t.zip_task # create zip archive, task name defaults to "zip"
t.gem_task # create gem, task name defaults to "gem"
An example would be:
desc "Create tar.gz package."
t.tar_task :archive
desc "Create RubyGem."
t.gem_task
# Not required: Creates a shortcut for the previously defined
# package tasks ("archive" and "gem")
desc "Create packages."
t.package_task
In our example we had only a few attributes for our package. Here are following two lists with the available attributes.
- Attributes that take a single argument:
name date description email has_rdoc homepage platform required_ruby_version rubyforge_project summary version - Attributes that take one or more values (if you give a single value it will
automatically be converted to a list):
author bindir executable extension files rdoc_options requires test_files test_suite
The attributes can also be set without the assignment operator:
t.executable "mybin"
Additionally to all this attributes you can explicitely set an attribute for the gem specification by preceding it with gem_:
t.gem_autorequire = "myproject"
More about the RubyDoc generator
If an argument is given to the RubyDoc generator, it will be used as task name. The output directory for the html files defaults to doc. To change this set the dir attribute:
desc "Generate html documentation."
gen RubyDoc, :html do |t|
t.dir = "doc/html"
As rant invokes RDoc programmatically, no command is printed when the task is run. If you want to see one, set the verbose attribute to true:
t.verbose = true
Installation
Since we get a RubyGem from the RubyPackage generator, our package is ready for distribution and installation. But probably you also want to provide a "normal" zip/tar archive. In this case you can use a conventional install.rb or setup.rb script for installation.
If we install the "wgrep" script on Windows, it won’t run out of the box, because Windows doesn’t know that it has to run it with the Ruby interpreter. This problem can be solved with Rant. Add the following lines to your Rantfile:
import "win32/rubycmdwrapper"
desc "Install wgrep."
task :install do
# Run setup.rb with the Ruby interpreter.
sys.ruby "setup.rb"
end
if Env.on_windows?
# Create .cmd files for all scripts in the bin/ directory and
# make the install task dependent on them.
enhance :install => (gen Win32::RubyCmdWrapper, sys["bin/*"])
end
See also
| Rant Overview: | README |
| Writing an Rantfile: | doc/rantfile.rdoc |
| Advanced Rantfiles: | doc/advanced.rdoc |