Formatting strings and numbers

format and specifiers

format takes a template and the values, and returns a string. The specifiers are the C ones, so a reader coming from C or Python recognises them at once:

ruby -e 'puts format("%-10s %04d", "Ada", 42)'

Ada 0042

%-10s is a string in ten columns, left aligned; %04d is an integer in four columns padded with zeros. The percent operator does the same with the template on the left:

ruby -e 'puts "%-10s|" % "Ada"'

Ada |

A float takes a precision: %.2f prints two decimals and rounds, which is the line to use for a price or a timing. The % form and format produce the same string; pick one per project.

Width and alignment

For a table, the padding methods read better than a template: rjust and ljust take a width and an optional fill character, and center does both sides:

ruby -e 'puts "Ada".rjust(6, "."); puts "Ada".ljust(6, "."); puts "Ada".center(7, "-")'

...Ada
Ada...
--Ada--

A number pads the same way after to_s, which is the reason a column of numbers lines up only after the conversion.

A report from a heredoc

A multi-line report is a heredoc with interpolation, and the table from the previous section supplies the rows:

rows = [["Ada", 3], ["Bob", 12]] puts <<~REPORT Name Count #{rows.map { |name, count| format("%-10s %3d", name, count) }.join("\n")} REPORT

ruby report.rb

Name Count
Ada 3
Bob 12

<<~ strips the common indentation, so the heredoc can sit inside a method without leading spaces in the output. The inner format keeps the columns straight.

What to watch for

A template with the wrong number of values raises ArgumentError; a template with the wrong type raises TypeError. Both are better than a silently shifted table, and both name the line.

Widths are characters, not display columns: a string with an emoji or a wide character takes more terminal space than its length says. For a table that must align, keep the cells to plain ASCII or accept the wobble.

Next: Constants, globals and scope

Article author: Arthur Isaev