In Ruby, a conversion function converts to the type indicated by the function name, if possible. Technically, it is a method on the Kernel class, but it starts with a capital letter and is used like a function.
Integer("1") # => 1
Float("3.14") # => 3.14Why would you use this over the more common methods such as to_i and to_f? One reason is that the conversion functions will raise an exception if the conversion cannot happen, whereas the explicit conversion methods will sometimes result in surprising behavior:
nil.to_i # => 0 "some string".to_i # => 0
The conversion functions will raise an exception when the value cannot be coerced:
Integer("foo")
# ArgumentError: invalid value for Integer(): "foo"Furthermore, the conversion functions can let you eloquently handle other cases that might require a lot more code. For example, when dealing with an array as input, you can give some flexibility by using the Array conversion function to coerce nil and single value elements in an array easily. Check it out:
def some_method(array)
array.each do |element|
puts element
end
endFor example, this won't work if you pass in nil or a string. You will get an error:
NoMethodError: undefined method `each' for an instance of String NoMethodError: undefined method `each' for nil
With a minor tweak, you can convert nil to be an empty array or a single instance of a String, Float, etc. to be wrapped inside an Array using the conversion function for Array.
def some_method(array)
Array(array).each do |element|
puts element
end
endThis works because the conversion function for Array does the following:
Array(nil) # => []
Array("foo") # => ["foo"]
Array([1,2]) # => [1, 2]You can also write your own conversion functions. Let's say we have a Duration class to represent some unit of time that we want to standardize in seconds:
def Duration(input)
case input
when Integer
input # Already in seconds
when String
if input =~ /^(\d+)m$/ # Matches "10m" for 10 minutes
$1.to_i * 60
elsif input =~ /^(\d+)h$/ # Matches "2h" for 2 hours
$1.to_i * 3600
elsif input =~ /^(\d+)s$/ # Matches "30s" for 30 seconds
$1.to_i
else
raise ArgumentError, "Invalid duration format: #{input}"
end
when Duration # when already a duration, just return it
input
else
raise TypeError, "Cannot convert #{input.class} to duration"
end
endputs Duration(120) # => 120
puts Duration("10m") # => 600
puts Duration("2h") # => 7200
puts Duration("30s") # => 30
puts Duration(Duration("10m")) # => 600
puts Duration("invalid") # Raises ArgumentErrorIn summary, conversion functions can result in safer, more eloquent code!