Kernel#String
String(object) → new_string Signature
String(object) → new_string
String() takes exactly one argument. Calling it with zero arguments raises ArgumentError, as does calling it with two or more. Other Kernel converters such as Float(), Integer(), Complex(), and Rational() all accept an exception: keyword, but String() does not. To opt out of raising, rescue the resulting error or convert the value yourself first.
What it does
String is a module function on Kernel, mixed into every Object. You usually call it without a receiver, which makes it handy inside class bodies and DSLs, where you do not have a self to send a method to. The dispatch order is fixed:
- If the argument already responds to
to_str, return itsto_strresult. This is the “I really am a string” branch and is trusted without rechecking the type. - Otherwise, call
to_sand return the result.Object#to_sis always defined, so this branch almost always succeeds. - If neither method exists, raise
TypeError: no implicit conversion of <Class> into String.
The result is a fresh, mutable String. The source object is not modified.
Examples
# Strings pass through
String("hello")
# => "hello"
# Numerics call to_s
String(42)
# => "42"
String(3.14)
# => "3.14"
# nil, true, and false have to_s defined on Object
String(nil)
# => ""
String(true)
# => "true"
# Collections use their inspect-style to_s
String([1, 2, 3])
# => "[1, 2, 3]"
String({ name: "Ada" })
# => "{:name=>\"Ada\"}"
# Symbol#to_s returns a frozen, cached String in MRI
String(:ok)
# => "ok"
String(:ok).frozen?
# => true
# A class that defines to_str wins over to_s
class Money
def initialize(cents) = @cents = cents
def to_str = "$#{@cents / 100}.#{'%02d' % (@cents % 100)}"
def to_s = "Money(#{@cents})"
end
String(Money.new(199))
# => "$1.99"
String() vs to_s vs String.new
You have three overlapping tools for “make a string out of this”:
obj.to_sis an instance method. It is always available, but a class can override it to return anything, including non-strings.String(obj)is the Kernel function. It triesto_strfirst and falls back toto_s. AStringalways comes back.String.new(obj)is the class constructor. It copies the argument and does not callto_sorto_str.String.new(42)raisesTypeError, whileString(42)returns"42".
Reach for String() when you have no receiver (in a DSL, for example), when you want to_str to win, or when you want a return-type guarantee that plain to_s does not give you.
# Same input, three different results
obj = 42
obj.to_s # => "42" (instance method; subclasses can override the return)
String(obj) # => "42" (Kernel function; honors to_str, then to_s)
String.new(obj) # TypeError: no implicit conversion of Integer into String
Gotchas
String(nil)returns"", not aTypeError. Compare toInteger(nil), which raises. This catches people who assume the Kernel converters are uniformly strict, and it is the most common surprise with this method.- The result is a new String, not the original.
String("foo").equal?("foo")isfalse, so do not rely on object identity for caching or deduplication. String()has strict arity.def to_str(x = "") = String(x)is the common workaround when you need a default.- With
# frozen_string_literal: true, source literals are frozen, butString("foo")returns a mutable copy. That makes it a useful thaw idiom when you need to mutate a string you got from elsewhere. String()does not change the encoding of its result. If you need a specific encoding, follow it up withString(arg).force_encoding("UTF-8").
See also
- Kernel#Float — the sibling converter for floats, with its own
exception:keyword. - Kernel#Integer — strict numeric conversion; raises where
String()returns"". - Kernel#Array — the matching converter for turning objects into arrays.