
== 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:
1. Link all package files to the new folder <tt>pkg/wgrep-1.0.0</tt>.
2. Create a tar.gz file in the +pkg+ directory.
3. Create a .zip file in the +pkg+ directory.
4. 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[link:files/README.html]
Writing an Rantfile::
    doc/rantfile.rdoc[link:files/doc/rantfile_rdoc.html]
Advanced Rantfiles::
    doc/advanced.rdoc[link:files/doc/advanced_rdoc.html]
