skip to content

Documentation Markup

RDoc comment markup and the ri command document Ruby, and YARD adds tags such as @param, @return and @example. Interviewers ask how you document a gem's public API next to its code.

on this pageshow

explore

questions

5

In Ruby, which comment does RDoc attach to a method, and how do you write it in RDoc markup or in Markdown?

level: juniorimportance: must knowfreq 42%

answer

  1. comment right above the definition
  2. *bold* _italic_ +code+
  3. = Heading, indented code block
  4. # :markup: markdown per file
  5. .rdoc_options or rdoc --markup

basics

~20 s

RDoc documents a class, module, method, constant or attribute with the comment block directly above its definition. That comment is RDoc markup by default (bold, italic, +code+); a # :markup: markdown line switches the file to Markdown.

solid answer

~40 s

RDoc parses the source and gives each `class`, `module`, `def`, `alias`, constant and `attr_*` the comment block that **immediately precedes** it. By default that comment is **RDoc markup**: `*bold*`, `_italic_`, `+monospace+`, `= Heading`, a code block made by indenting, and `{text}[url]` links, while names such as `GeoLookup::Client#geocode` link automatically. To write **Markdown** instead, put `# :markup: markdown` at the top of the file, set `markup: markdown` in the project's `.rdoc_options`, or run `rdoc --markup markdown`; then you use `**bold**`, backticks and fenced code. `rdoc lib` writes HTML to `doc/`. In Ruby 4.0 rdoc is a **bundled gem**, so a Rakefile that does `require "rdoc/task"` under Bundler needs rdoc in the Gemfile.

code

ruby · 13 lines
ruby
# :markup: markdown

module GeoLookup
  # Resolves a free-text address to a `GeoLookup::Place`.
  #
  # ```ruby
  # GeoLookup::Client.new(api_key: "k").geocode("Brandenburger Tor")
  # ```
  #
  # Returns **nil** when nothing matched.
  class Client
  end
end

go deeper

for a junior

Recall the positional rule: the comment directly above a def or class documents it. Know the RDoc markup basics, bold, italic, +code+, and that # :markup: markdown switches a file to Markdown.

for a middle

Explain the three places the markup format is chosen: the per-file directive, .rdoc_options and the --markup flag. Mention automatic cross-links for names like Client#geocode and where rdoc writes its output.

for a senior

Show you know the tooling around it: rdoc as a bundled gem in Ruby 4.0 and the Gemfile entry that implies, RDoc::Task in the Rakefile, and rdoc -C for a coverage report.

for a principal

Frame the format choice for a team: RDoc markup is still the default but slated to give way to Markdown, so a new gem standardising on Markdown now avoids a later migration of every comment.

## What RDoc does **RDoc** is the documentation generator that ships with Ruby. It reads `.rb` and `.c` sources plus stand-alone `.rdoc` and `.md` pages, builds a model of your classes, modules and methods, and renders it as HTML (the `rdoc` command) or as data for the `ri` terminal viewer. It does not execute your code: everything it knows comes from parsing the files and reading the comments next to the definitions. Since **Ruby 4.0** rdoc is a **bundled gem** rather than a default gem. The `rdoc` and `ri` commands are still installed with Ruby (Ruby 4.0.7 ships rdoc 7.0.4), but a program that does `require "rdoc"` or `require "rdoc/task"` while running under Bundler fails unless the Gemfile lists `rdoc`. ## Which comment documents which object The rule is positional: - The comment block that **immediately precedes** a `class`, `module`, `def`, `alias`, constant assignment or `attr_reader`/`attr_writer`/`attr_accessor` becomes that object's documentation. - A trailing comment on the same line as the definition is where **directives** such as `:nodoc:` go, not prose. - In a C extension, the comment above the C function that implements a method documents that method. - A whole `.rdoc` or `.md` file becomes a separate page that is not tied to any code object. For a geocoding gem, that means the explanation of `geocode` sits directly on top of `def geocode`, and the overview of the gem sits on top of `module GeoLookup`. ## RDoc markup versus Markdown RDoc's own format, **RDoc markup**, is the default for `.rb` and `.c` files. Markdown is supported and is the recommended format for stand-alone pages; the RDoc project states it plans to retire RDoc markup in favour of Markdown once Markdown reaches feature parity. | Element | RDoc markup | Markdown | |---|---|---| | Heading | `= Heading`, `== Sub` | `# Heading`, `## Sub` | | Bold | `*word*` | `**word**` | | Italic | `_word_` | `*word*` | | Monospace | `+word+` or `<tt>words</tt>` | `` `word` `` | | Link | `{text}[url]` | `[text](url)` | | Code block | indent the lines | fenced with backticks | | Tables | not supported | supported | In both formats RDoc **cross-links names automatically**: writing `GeoLookup::Place` or `GeoLookup::Client#geocode` in a comment produces a link when that object is documented. ## Switching a project to Markdown There are three places to choose the format, from narrowest to widest: 1. **Per file:** a `# :markup: markdown` line at the top of the Ruby file. 2. **Per project:** `markup: markdown` in a `.rdoc_options` YAML file at the project root (`rdoc --write-options` writes one from the options you pass). 3. **Per run:** `rdoc --markup markdown lib`. The accepted formats are `rdoc` (the default), `markdown`, `rd` and `tomdoc`; the last two are legacy and discouraged. ## Building and previewing - `rdoc lib` parses `lib/` and writes HTML into `doc/` by default (`--op` changes it). - `rdoc --ri` writes `ri` data instead, under your home directory, so `ri` can show your own code in the terminal. - `rdoc -C lib` prints a coverage report of undocumented items instead of generating files. - In a Rakefile, `require "rdoc/task"` and `RDoc::Task.new` define `rdoc`, `rerdoc`, `clobber_rdoc` and `rdoc:coverage` tasks. ## A worked example In RDoc markup, a geocoding client might read: ```ruby module GeoLookup # Resolves free-text addresses to coordinates. # # = Usage # # client = GeoLookup::Client.new(api_key: "...") # client.geocode("Brandenburger Tor") # # Returns a GeoLookup::Place, or +nil+ when *nothing* matched. class Client end end ``` The indented lines become a code block, `+nil+` renders as code, `*nothing*` as bold, and `GeoLookup::Place` becomes a link. The same comment in Markdown would use a fenced block, backticks and `**nothing**`, preceded by `# :markup: markdown` at the top of the file. ## Common mistakes - Writing Markdown in a file RDoc still treats as RDoc markup, so `**bold**` renders literally. - Using the shorthand on several words: `*two words*` does not render bold, because the `*`, `_` and `+` shorthands cover a single word; longer spans need `<b>`, `<i>` or `<tt>` tags. - Putting YARD `@param` tags in a project built with plain `rdoc`: RDoc renders them as ordinary text, it does not understand them as structured tags.

  • Does RDoc understand YARD tags such as @param and @return?
    No. RDoc has no tag model; `@param address [String]` is just a line of text in the comment. RDoc's own structured hooks are directives like `:call-seq:`, `:args:` and `:yields:`. If you want tags parsed into parameter tables and type lists, you run YARD over the same comments instead.
  • Why can `require "rdoc/task"` in a Rakefile fail on Ruby 4.0 when it worked on 3.4?
    Ruby 4.0 turned rdoc from a default gem into a **bundled gem**. Under `bundle exec`, Bundler only exposes gems the Gemfile resolves, so a bundled gem that is not listed raises `LoadError`. Adding `gem "rdoc"` to the Gemfile (usually in a development group) fixes it.

saying these in an interview costs you the question

  • RDoc reads docstrings from a string placed inside the method body.
  • Any comment anywhere in the class documents the next method RDoc sees.
  • RDoc markup uses **double asterisks** for bold, just like Markdown.
  • Markdown in comments needs no declaration; RDoc detects it automatically.
  • RDoc renders YARD @param tags as a structured parameter table.
  • In Ruby 4.0, rdoc is a default gem and needs no Gemfile entry.
open as a page

In a Ruby gem documented with YARD, how do you describe a public method's parameters, return value, exceptions and usage with tags?

level: middleimportance: must knowfreq 45%

basics

~20 s

YARD reads @tags from the comment above a method: @param name [Type] for each positional or keyword argument, @return [Type] for the result, @raise [ErrorClass] for exceptions and @example for indented usage code. yard doc renders them as structured HTML.

open as a page

With Ruby's ri command, how do ri Array#sort, ri IO::readlines and ri IO.readlines differ, and why can ri know nothing about a gem?

level: juniorimportance: should knowfreq 26%

basics

~20 s

ri prints installed Ruby documentation in the terminal: Array#sort names an instance method, IO::readlines a class method, and IO.readlines matches both. A gem installed with --no-document has no ri data, so ri reports Nothing known about it.

open as a page

In a Ruby gem, how do RDoc's :nodoc: and :doc: directives and YARD's @api private tag control which methods appear in the documentation?

level: middleimportance: should knowfreq 30%

basics

~20 s

RDoc documents public and protected methods by default; a trailing # :nodoc: hides a definition and # :doc: forces one in, such as a private method. YARD ignores those directives and uses @api private or @private with --hide-api private or --no-private.

open as a page

For a Ruby gem's CI, how would you use yard stats --list-undoc and yard doc --fail-on-warning to stop the public API documentation from rotting?

level: seniorimportance: nice to knowfreq 18%

basics

~20 s

yard stats --list-undoc prints a % documented figure and lists each undocumented public object with its file and line; it does not fail on gaps by itself. yard doc --fail-on-warning exits non-zero on warnings such as an unknown @param name.

open as a page