Designing Patterns

View within the Urban Jungle

Discussing nitty gritty software development details that Tony finds interesting



View within the Urban Jungle RSS FeedSite Feed

RDoc 2.2.1 Released

RDoc 2.2.1 is available! It can be downloaded here or through the gem system. We are releasing RDoc again, so soon after the RDoc 2.2.0 release, in order to fix some bugs and include some community patches that were overlooked before the 2.2.0 release. These changes needed to be checked-in immediately as RDoc 2.2.1 will be part of the upcoming Ruby 1.9.1 release. This RDoc release includes a patch by Hugh Sasse that provides basic support for parsing Perl files for POD documentation. Additionally, ri will display the values of constants again, which has been broken for a few releases. Also, ri finally should resolve methods inherited from a parent class correctly (i.e., ri File.read). The (hopefully) last bug with this was in the documentation generation system, however, so a machine’s ri documentation will need to be rebuilt in order for this to work. The RubyGems documentation can be rebuilt by running

gem rdoc --all

In order to rebuild the Ruby library documentation, download the source code and run

rdoc --all --ri --op new_ri_docs

Then, replace the Ruby system ri directory, which can be found by running

ri --no-standard-docs --system --list-doc-dirs

with the new_ri_docs directory. As this release is slated to ship with Ruby 1.9.1, we would love to hear about any issues so that we can fix them quickly.


RDoc 2.2.0 Released

RDoc 2.2.0 is available! It can be downloaded here or through the gem system. This release is the result of work by RDoc’s developers and by the community, through both making suggestions and submitting patches. It is intended to provide a very stable cut of the 2.x functionality and also to fix several bugs that have lingered since the 1.x series. This version’s unit tests cover a much larger range of functionality than any prior version’s tests, although the tests’ coverage still is far smaller than it should be. I believe that this is the most reliable version yet. In addition to bug fixes, this release includes several enhancements. While the release notes list all of these, I am going to highlight a few of them.

A number of fixes and small enhancements were made to the template system. All built-in HTML templates now generate strict, valid XHTML. All of the bugs introduced during the switch to ERB templates in RDoc 2.0.0 have been fixed. In addition, this release provides basic support for creating HTML templates that do not use frames. The built-in frameless template is an example. 3rd-party templates also now are supported more smoothly. A template can be installed as a gem, and RDoc will find it with its -T command-line option. The beautiful Hanna template is such a 3rd-party template. This template eventually might be included with RDoc but for now easily can be used instead of the built-in templates. RDoc’s own documentation uses this template.

ri has been enhanced in several ways. All of its use cases are much faster, some many times so. In addition, Daniel Choi contributed a patch that adds an interactive mode; in this mode, ri gets input from the user in order to disambiguate method lookups and allows the user to browse a class’ methods. The search directory option (-d) also has been fixed, so that ri once again can look for documentation in a user-specified directory. ri’s caching scheme, which it uses to speed up its searches, is capable of caching documentation from user-specified directories, and so using this option does not result in any performance degradation.

A number of future enhancements have been identified that hopefully will improve RDoc dramatically. We would love input on its future technical direction and would welcome any new project volunteers.


Tricking out Ruby Documentation: Picking the Right Documentation Generator Tool

In my other blog, I recently wrote a post about the characteristics of a good software documentation creation and publishing pipeline. A documentation generator is the core of such a pipeline. Designing Patterns has written several open-source Ruby gems, and in order to create a documentation pipeline for these, I evaluated the documentation generators for Ruby. I think that RDoc is the best such tool.

I previously have used Javadoc and Doxygen, but neither supports Ruby. There are multi-language tools that understand Ruby code in a basic way, such as Natural Docs and ROBODoc, but none that offers strong support for the language’s features and idioms. RDoc is the standard documentation generator used within the Ruby community. Like Doxygen, it can parse source code and, even without any comments, generate web pages documenting the code. It has a number of very impressive strengths:

  • It has very strong support for Ruby syntax and idioms, including being able to document attributes, methods that accept blocks, and metaprogramming constructs.
  • It provides a very natural markup language that can be written and read easily, even as plain text.
  • It has a powerful cross-referencing engine that automatically generates class and method cross-reference links in the text of the web pages that it produces.
  • It inlines or links to a method’s source code in the HTML documentation that it generates for the method.
  • Using graphviz, it can embed class diagrams into the web pages that it generates.
  • It can generate several different formats of documents, including HTML, XML, texinfo (which in turn can be used to create PDF documents), and Windows Help.
  • It includes ri, the standard Ruby tool for viewing documentation on the command-line, and can generate documentation for ri.
  • It can parse C code and understands the C/Ruby calling conventions, so it can generate documentation for classes written in both C and Ruby.
  • It uses a powerful templating system based on embedded Ruby to generate HTML, allowing developers to create new templates in order to customize the look of their web documentation.
  • There is tremendous support for it in the standard Ruby tools; the gem system, rake, and hoe use it to generate documentation.

Unfortunately, RDoc has some significant weaknesses, including:

  • Its markup language is not very expressive; in particular, there is no descriptive markup for programming elements, like method parameters and return values. Both Doxygen and Javadoc offer such markup. At Designing Patterns, we compensate for this to some extent by using an emacs macro to generate markup that simulates descriptive markup for programming elements (see this method documentation for example).
  • The web pages produced by the default HTML template look pretty poor. This is an example, generated for Ruby’s Core Library. It looks dated and, worse, the frames at the top make reading the pages difficult. I always find myself making the top frames taller in order to see more of the class, file, and method lists but then later making the top frames shorter in order to see more text in the central frame. At Designing Patterns, we use a beautiful 3rd party template, Hanna, to produce documentation like this.
  • Although Ruby’s standard tools support RDoc, they often offer limited ability to specify RDoc options, such as which HTML template to use. I fixed this to some extent with a patch that allows one to specify RDoc options through the RDOCOPT environment variable, similar to how the RUBYOPT environment variable allows one to specify options for the Ruby interpreter.

RDoc has many strengths, and its flaws, while significant, can be compensated for well enough to make it very suitable for our company’s purposes. Its maturity, the support for it in the standard Ruby tools, and its widespread adoption by the Ruby community make it particularly attractive for use in a production toolchain. While designing a documentation pipeline around it, I have submitted a number of patches and lately have become an RDoc developer. Active development recently has been restarted, and so I have no doubt that its flaws will be fixed and that it will continue to improve in future releases.

There are two other documentation generator tools for Ruby. The first is RDtool. This was used heavily prior to RDoc, but, unlike RDoc and Doxygen, it does not generate documentation for classes and methods automatically. In fact, it is not a source code documentation generator at all but is instead a more general formatting tool; this discusses the differences between RDTool and RDoc in greater depth. RDTool’s lack of support for source code means that much more formatting is required in order to create proper documentation, and so I immediately rejected using it. The other alternative is Yard (also called Yardoc). This is a relatively recent tool in the vein of Doxygen and RDoc. It offers the following advantages over RDoc:

  • It provides descriptive markup for programming elements, very similar to that provided by Doxygen and Javadoc.
  • It offers an API to customize the parsing of source files, allowing it to accommodate new metaprogramming constructs easily.
  • In a class’ documentation, it shows methods inherited from a parent class.
  • The default look of its generated web pages is better than RDoc’s.

Yard, however, has the following disadvantages:

  • It is not very mature. In fact, the version that I tried crashed on one of my gems.
  • It cannot parse C code, and so it can not create documentation for the Ruby Core Library or for gems written in C and Ruby.
  • There is no built-in support for it in the standard Ruby tools.
  • It only provides built-in support for generating HTML, although it was written to allow the addition of other output formats with relative ease.

Given the above Yard vs. RDoc points, I think that RDoc is the better choice for Designing Patterns as Yard does not seem ready for our production use. It does, however, have a number of interesting and exciting features. I hope that the two tools will cross-pollinate and even share code in the future.

In forthcoming posts, I will discuss how to create a documentation pipeline around RDoc that utilizes its strengths and masks its weaknesses.