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
"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|
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
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 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()  end Array.try_convert(o) # => 
Uppercased Kernel Methods (Special Conversion or
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:
- If there is a special conversion, apply it. See the table below for details and the exact application order (e.g.
Array()does its special conversion after it tried the two steps below).
- Unless special conversion gets applied, try to convert via the implicit convesion method
- If it does not exist, try to convert via the explicit conversion method
- Raise a TypeError if everything of the above has failed
¹ 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.
Core Classes Conversion Table
||Kernel Method||Kernel Method w/
||Kernel Method Special|
||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 ³|
² 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
When to Use What?
- Prefer explicit conversion:
.try_convertfor implicit conversion
- Use the uppercased Kernel methods for their special effects, like
Array()for wrapping single arguments in an arrays, or
Integer()for strict integer conversion