String#prepend
Overview
String#prepend adds the given string or strings to the beginning of the target string. Unlike string concatenation methods that produce a new string, prepend mutates the receiver. The method returns self — the modified string, not a new one.
That makes it useful when the original object needs to stay in place, such as when other parts of your code already hold a reference to the same string. If you are composing a final message or prefixing a label before storage, prepend keeps the intent explicit.
Because the method updates the receiver directly, it fits cases where you want the same variable to keep pointing at the same string object. If you need a fresh string for later comparison or reuse, build one with + instead. When the same string object needs to grow at the front across several method calls, prepend avoids the repeated allocation that + would cause, which can matter inside loops or request handlers where object churn adds up.
Signature
prepend(*other_strings) -> str
Parameters:
*other_strings— One or more string arguments to prepend. Each argument must be a string. Numeric arguments are not accepted and will raise anArgumentError.
Return value: The modified string (the same object as self).
The signature tells you that prepend takes one or more strings and returns the modified receiver. Because the return value is the same object, you can chain another method call after prepend or assign the result to a new variable without losing the connection to the original. This is a common pattern with mutating methods in Ruby: the return value is self, so the method fits naturally into pipelines while still doing its in-place work.
Basic Usage
str = "world"
str.prepend("hello ")
# => "hello world"
This first example shows the return value, but the more important detail is what happens to the original string object. When prepend runs, it changes the receiver in place and also returns that same object. That dual behavior means you can use the return value for chaining or assignment while still counting on the original variable to reflect the change. The next example makes that mutation explicit by inspecting the variable after the call.
Note that prepend modifies the original string:
str = "world"
str.prepend("hello ")
str
# => "hello world"
Notice that the variable str now holds the modified value. After prepend returns, the same string object contains the combined content. If other parts of the program hold a reference to that same string via a different variable or data structure, they will see the change too. That shared-visibility behavior is the main reason to choose prepend over +: you want the mutation to be visible everywhere the original object is referenced, not just in the local scope.
Calling prepend without arguments raises an error:
str = "world"
str.prepend
# => ArgumentError: wrong number of arguments (given 0, expected 1)
The ArgumentError is raised because the method signature requires at least one string argument. This differs from methods like concat that also accept integers, and it is worth remembering if you are dynamically building a list of arguments. A quick check that the argument array is not empty before the call can prevent the error in code that assembles prefixes from user input or configuration data at runtime.
Prepending an empty string
Prepending an empty string leaves the original unchanged:
str = "hello"
str.prepend("")
# => "hello"
Prepending an empty string is a no-op that returns the original string unchanged without raising an error or producing any side effect. While this is rarely a deliberate operation, it can happen when the prepended value comes from a variable that might be empty, such as a user-supplied prefix or a configuration field that was left blank. In those cases the method behaves safely without needing an explicit guard clause around the call.
Multiple arguments (Ruby 2.4+)
Ruby 2.4 introduced the ability to pass multiple arguments to prepend. Each argument is prepended in order, so the first argument appears closest to the original string content, and the last argument appears at the very beginning.
str = "end"
str.prepend("middle ", "start ")
# => "start middle end"
When you pass multiple arguments, prepend processes them in the order they appear. The first argument ends up closest to the original content, and the last argument becomes the new beginning of the string. This ordering matches what you would see if you called prepend repeatedly with a single argument each time, so the multi-argument form is just a convenient shorthand for chaining several calls in one expression.
Comparison with the + operator
The + operator creates and returns a new string, leaving the original unchanged:
original = "world"
result = original + " hello"
# original is still "world"
# result is "world hello"
In contrast, prepend alters the original in place and returns the same modified object. The original variable now points to a string with “hello ” at the front, and the return value is that same string object. This dual behavior — mutate and return self — is what makes prepend convenient for chaining and pipeline-style code where each step works on the same receiver without creating intermediate copies. When you want the original string to stay intact for later comparison or reuse, the + operator is the better choice because it never touches the receiver.
original = "world"
original.prepend("hello ")
# original is now "hello world"
# returns "hello world"
The two code examples above show the key difference in approach. With +, the original string survives unchanged and the result is a brand-new object. With prepend, the same object is modified in place and returned for convenience. Choosing between them comes down to whether the surrounding code expects the original to stay intact. When it does, + is the safer pick. When mutation is acceptable and you want to avoid extra allocations, prepend is the right tool.
Choose prepend when you want to modify an existing string without creating intermediate objects. Use + when you prefer immutable semantics or need to preserve the original string.
Comparison with insert
String#insert offers another way to prepend content:
str = "world"
str.insert(0, "hello ")
# => "hello world"
Use insert(0, ...) when you need position flexibility, or prepend for straightforward prepending. The two methods produce the same result when inserting at index zero, but prepend makes the front-insertion intent obvious at a glance while insert can place content anywhere in the string.
Integer arguments
prepend does not accept integers, unlike concat, which accepts integers as a workaround (treating them as ASCII character codes).
"str".prepend(65)
# => ArgumentError: no implicit conversion of Integer into String
"str".concat(65)
# => "Astr" (65 is ASCII for 'A')
The difference in argument handling between concat and prepend is worth remembering. concat accepts an integer and treats it as an ASCII character code, which can be a surprise if you expect the same strict type checking that prepend enforces. Use concat when building strings from byte values, and reach for prepend only when you already have full strings ready to insert at the front.
Frozen string error
Calling prepend on a frozen string raises a TypeError:
str = "hello".freeze
str.prepend("world ")
# => TypeError: can't modify frozen string: "hello"
This behavior is consistent with other mutating methods in Ruby. Always check frozen? before attempting mutation if the string may be frozen.
See Also
- String#concat — concatenates strings at the end of a string; accepts integers as arguments
- String#replace — replaces the entire contents of a string in place