Try Converting

Similar to metaprogramming, Ruby's type conversion system has evolved over time. While the result functions, it is also a little inconsistent and suffers from poor naming. Let's put things in perspective:

Implicit and Explicit Conversion

Ruby objects are usually converted to other classes/types using to_* functions. For example, converting the String "42" to a Float is done with to_f:

"42".to_f # => 42.0

This process is called explicit conversion (you want the object converted).

Some classes provide a second way to convert an object: implicit conversion (you expect the object to be of some type).

The following table shows the defined conversion methods of Ruby's important core classes:

Class Explicit Conversion Implicit Conversion
Array to_a to_ary
Hash to_h to_hash
String to_s to_str
Integer to_i to_int
Float to_f -
Complex to_c -
Rational to_r -
Regexp - to_regexp
IO - to_io

In most cases you should just go with the explicit conversion method and you are good.

Expecting a Specific Type

However, things are more complicated in real life. You might, and many of Ruby's core methods do, expect a compatible type that you can deal with. That is where two kinds of indirect conversion methods come into play:

.try_convert Class Methods (Implicit Conversion or nil)

Some of Ruby's core classes have a try_convert class method. Although its not obvious, which classes have one, and which do not have one (Array has one, Integer does not), its semantics are pretty clear: It will convert the object into an instance of the class via the implicit conversion method (e.g. to_ary), or, if no implicit conversion method is defined, will just return nil. It will also return nil, if the result of the conversion is nil, or nil was given as argument:

Array.try_convert(42) # => nil
Array.try_convert(42..43) # => nil
Array.try_convert([42, 43]) # => [42, 43]
Array.try_convert(nil) # => nil

o = Object.new
def o.to_ary() [42] end
Array.try_convert(o) # => [42]

Uppercased Kernel Methods (Special Conversion or TypeError)

Idiosyncratically, there is a third way of converting values: Uppercased Kernel methods, like Array().¹ The objects you pass in will be converted to the corresponding class, following the following rules:

¹ Although defining uppercased methods for your custom classes to create instances of it looks like an interesting idea at first glance, it is rather confusing. Consider defining class.[] instead, which enables a very similar syntax, but uses the real constant it belongs to. An example of such usage is Set.
² Since Ruby 2.6, you can pass in a exception: false keyword argument to return nil instead of raising an error

Core Classes Conversion Table

Class .try_convert Kernel Method Kernel Method w/ nil Kernel Method Special
Array Array.try_convert Array() Array(nil) # => [] If :to_ary and :to_a did not return an array, it will create single-element array which contains the given value
Hash Hash.try_convert Hash() Hash(nil) # => {} Hash([]) # => {}. Also remember that you can convert arrays to hashes with Hash.[].
String String.try_convert String() String(nil) # => "" -
Integer Integer.try_convert Integer() Integer(nil) # TypeError Special behavior for strings: Instead of calling String#to_i, it will be more rigid². Takes a second argument defining the numerical base. Also see ³
Float - Float() Float(nil) # TypeError - ³
Complex - Complex() Complex(nil) # TypeError -
Rational - Rational() Rational(nil) # TypeError -
Regexp Regexp.try_convert - - -
IO IO.try_convert - - -

.

² It will only convert strings that contain exactly an integer. It would not accept "42A", which String#to_i would happily take. It also accepts radix prefixes and numbers that contain underscores, so basically it accepts the same format that is valid for direct integer literals in Ruby. Will raise an ArgumentError if an invalid string is passed in.
³ It will convert to other low-level numerical types (such as integers and floats) directly, so Float(4) will not call 4.to_f
⁴ Added in Ruby 3.1

When to Use What?

More Idiosyncratic Ruby