Text, and the methods it brings
Strings are objects with a large vocabulary: strip, split, join, gsub, the word-list literal, and format for lining numbers up in columns.
A string knows a lot
Because a string is an object, everything you might want to do to text is a method hanging off it: strip removes spaces from both ends, upcase and downcase change case, length counts characters, include? answers a question with true or false, start_with? and end_with? test the edges, reverse turns it around, and center, ljust and rjust pad it with spaces to a width.
Methods chain, because each one hands back another string: line.strip.downcase first trims, then lowercases. Reading a chain left to right is the same as following the value through each step, which is why Ruby code is often a sentence about the data rather than a set of instructions.
Splitting and joining
split cuts a string into an array, and join glues an array back into a string. 'oak,desk,lamp'.split(',') gives three pieces; parts.join(' | ') puts them back together with a separator you choose. Between those two methods is where most text processing lives, and split with no argument is the convenient shorthand for whitespace.
gsub replaces every occurrence of one piece of text with another — 'desk lamp'.gsub('lamp', 'light') — and sub replaces only the first. The g stands for global, and both take plain text or a pattern; the plain form is enough for most tidy-up work.
Small literals, and tidy columns
%w[red green blue] is a word list in one breath: it builds an array of three strings without a quote or a comma in sight. The parentheses, brackets or braces all work as delimiters, and the habit saves both noise and typos when a list is long.
For columns of numbers, format is the answer. A format string has placeholders — %s for text, %d for an integer, %.2f for a float with two decimals — and widths can be given: format('%-16s %8.2f', name, price) left-aligns a name in sixteen characters and right-aligns a price in eight. There is a shorter spelling too, '%.2f' % price, for when one placeholder is all you need.
Strings are values you can rebuild
A string is mutable, and most of its methods return a new string rather than changing the one you called them on. line.strip hands back a trimmed copy; line still has its spaces. The bang versions — strip!, gsub!, upcase! — change the receiver and return nil when nothing changed, which is a surprising answer to receive in the middle of a chain.
That copy-first habit is what makes chains safe: each step receives the previous answer, and nothing you did earlier is quietly rewritten. It also means the result has to be used. line.strip on a line by itself trims a copy and throws it away, so assign it or call the next method on it.
The characters you cannot see
Text from a file or a form often carries characters that do not show: a newline at the end, a tab in the middle, a non-breaking space that looks exactly like a space. strip removes whitespace at the edges, and p shows the value with its escapes visible, which is how you discover that the string you compared was never equal.
A comparison that fails for no visible reason is almost always this. Print both sides with p, compare their lengths, and the difference appears. inspect gives the same representation as a string, which is useful when the value has to go into a message.
Building text in a loop
A common job is to collect lines and join them once at the end. Appending to an array and calling join("\n") is faster and clearer than adding to a string with +=, because each += builds a new string and copies the old one. << avoids the copy but changes the receiver, so use it when the string is yours alone.
gsub replaces every match but leaves the original alone — note.gsub('a', 'b') is a new string unless you write gsub!. + and << also differ: + builds a new string, while << appends to the one on the left and can change a string another name is also holding. And a format string must match its arguments: two placeholders need two values, or Ruby raises.
Tidying text
line = ' Ada Lovelace '
puts line.strip
puts line.strip.downcase
puts line.strip.length
csv = 'oak,desk,lamp,mat'
parts = csv.split(',')
p parts
puts parts.join(' | ')
puts parts.include?('lamp')
words = %w[red green blue]
puts words.length
puts words.sort.join(', ')
price = 12.5
puts format('%.2f', price)
puts format('%-10s|', 'left')
puts format('%8.2f', price)
puts '%.2f' % price
puts 'desk lamp'.gsub('lamp', 'light')
puts 'ruby'.start_with?('ru')
puts 'ruby'.center(10, '.')A receipt, lined up
Run it and see the columns. Then add a third item, compute the total, and print it on a line of its own using format with a width of sixteen for the label.
p and puts disagree about what to show: puts prints a string as itself, while p prints it the way the code would — with quotes. When a strip is not stripping what you expect, print the value around it with p and look at the ends.
Try these next
- Turn a sentence into a slug: strip it, downcase it, then replace spaces with dashes.
- Split a comma-separated line, sort the pieces, and join them with
|. - Print a three-row table with
format, giving the name twelve columns and the price eight.
From a title to a slug
Run it and compare the original title with the slug. Then add a second title, give it the same treatment, and print both slugs one per line.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
What does strip remove?
