String#reverse
String#reverse returns a new string with the characters in reverse order. The reverse! variant modifies the string in place.
This is one of those methods that reads exactly like the result you want. It often appears in quick checks, display formatting, and small text experiments where you want the output to look different without altering the source.
When you are reading code, reverse is usually a tiny helper instead of a big algorithm. That is part of its appeal: it lets you flip text without adding extra state or mutating the original value.
Basic Usage
"hello".reverse
# => "olleh"
"Ruby".reverse
# => "ybuR"
These examples show the method at its simplest: a single call on a short string produces the reversed result without any extra setup. The method is non-destructive by default, which means the original string stays available if other code still references it. That makes reverse safe to inline inside expressions, comparisons, or display helpers where you want the flipped version without changing the variable underneath.
In-place Reversal
reverse! modifies the string directly. Returns nil if the string is unchanged (empty or single character).
str = "hello"
str.reverse!
str # => "olleh"
The in-place version is useful when the same object will be reused right after the reversal. If the original string is still needed elsewhere, the non-bang version is the safer choice because it leaves the source untouched and avoids a second pass over the same data.
Palindrome Check
A common pattern for checking if a string reads the same forwards and backwards:
def palindrome?(word)
word == word.reverse
end
palindrome?("racecar") # => true
palindrome?("hello") # => false
A palindrome check is one of the most common patterns you will see with reverse, because the logic is a direct translation of the definition: a string reads the same forward and backward. The method compresses that idea into a single comparison, which is why it shows up so often in coding exercises and quick validation helpers. The pattern also generalizes to any situation where you need to compare a string against its mirrored form.
character vs byte reversal
reverse operates on characters, not bytes. This matters for multi-byte encodings like UTF-8:
"héllo".reverse
# => "olléh"
"日本語".reverse
# => "語本日"
For byte-level reversal, convert to raw bytes first using encode('ASCII-8BIT').
That distinction matters because text data is not always just a list of bytes. When the string contains multibyte characters, character-aware reversal keeps those characters together instead of tearing them apart.
This matters most in user-facing text, where the code should preserve what the reader sees instead of what the byte stream happens to look like. If you are dealing with protocol data or raw binary content, pick a representation first and then reverse it with that goal in mind.
Performance
For very long strings, reverse allocates a new string of equal size. The reverse! variant avoids one allocation but still copies all characters. Both are O(n) where n is the string length.
That cost is usually fine for short labels, names, and small buffers. If you are reversing large chunks of text repeatedly, it helps to keep the operation close to the point where you actually need the result.
Common Mistakes
- Thinking
reverse!always returnsself: It returnsnilwhen no change occurs.s = "abc" s.reverse! # => "cba" s.reverse! # => nil (unchanged — empty or single char strings)
The bang method’s nil-return behaviour on unchanged strings is a subtle Ruby convention worth internalising. When a string is empty or contains only one character, reversing it produces the same value, so reverse! returns nil to signal that nothing changed. If your code assigns the return value, check for nil before using it.
- Using
reverseon non-string types: Callto_sfirst —reverseonly works on strings.123.reverse # => undefined method error 123.to_s.reverse # => "321"
The fix is straightforward: call to_s before reverse. This applies to any object that responds to to_s, including numbers, symbols, and custom classes. The conversion step is cheap and keeps the code from breaking when the input type is not exactly what you expected.
- Assuming Unicode normalization:
reversedoes not decompose combined characters."é".reverse # => "é" — but depends on how the character is stored
For everyday use, the main rule is to treat reverse as a display or comparison helper instead of a text-normalization tool. If you need canonical Unicode handling, perform that step first and reverse only after the string is in the shape you want.
See Also
- /reference/string-methods/string-strip/ — remove leading and trailing whitespace
- /reference/string-methods/string-scan/ — find all occurrences matching a pattern