You’re working with an integer but you would like to use string methods (like gsub
) instead.
What can you do?
Convert it into a string (with to_s
) then convert it back to an integer (with to_i
).
For example:
You can convert the Integer
1 to the String
“1”.
Then you can use methods from the new class, which helps you do something that wasn’t possible before.
Remember that in Ruby…
Every object is associated with a class, and every class has a specific set of methods.
In this article, you’re going to learn about:
- What conversion methods are available in Ruby
- What are the differences between them!
- How to choose the right one in different situations
Let’s do this!
Short Conversion Methods (to_s, to_i)
You’re probably familiar with this first group of conversion methods.
Methods like:
- to_i
- to_s
- to_a
These methods return a new object of a specific class that represents the current object.
For example:
(1..10).to_a # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
This says:
“I want to convert the
Range
1..10 into anArray
that represents that range.”
There are ways in which Ruby calls these conversion methods for you implicitly.
Like in string interpolation:
"#{1}"
This calls 1.to_s
for you, even if you don’t see it.
You can check yourself with this code:
module Log def to_s puts "to_s called" super end end class Integer prepend Log end puts "#{1}" # "to_s called"
Note: You have to use
Fixnum
instead ofInteger
if you’re on Ruby 2.3 or older. Or better yet, update your Ruby version 🙂
These methods are pretty permissive & they’re not supposed to raise an exception.
For example:
"aaaaaa".to_i # 0
This 0
may surprise you.
But that’s what you get when you call to_i
on a string without integers on it.
As you’ll see later in this article there is a more strict version of this method.
Long Conversion Methods (to_str, to_int)
Now:
If we have those short conversion methods, why do we need methods like to_str
, or to_int
?
What’s the difference?
The difference is in their intent.
Every Ruby class (with the exception of BasicObject
) implements the to_s
method to return itself as some type of string representation.
But just because a class returns a string doesn’t mean it behaves like a string!
Let’s look at an example:
"" + 1 # TypeError: no implicit conversion of Fixnum into String
Think about this:
What should an empty string plus integer return?
I don’t know.
You could say “1” (a string with the number one).
But why?
That’s not what most people expect in this case.
It doesn’t make sense to add them up… that’s why we get this TypeError
.
And even if that was allowed.
What about this:
"" + {}
That’s an empty string plus an empty hash.
Doesn’t make sense either!
So Ruby instead of checking if the other object is a string, which wouldn’t be good for Polymorphism, it checks if it ACTS like a string.
That’s where the to_str
method comes in.
The only classes that implement to_str in Ruby 2.5:
String
NameError::message
Warning::buffer
How to Implement Your Own Conversion Methods
You can implement to_str
on any class.
Then you’ll be able to use it like a string.
Here’s an example:
class Cat def to_str "meow" end end "" + Cat.new # "meow"
But unless your class is equivalent to a string you shouldn’t do this.
Use to_s
instead.
Btw, this is not only for the +
method.
It’s also used on other places where only a string-like object makes sense.
Like:
[1,2,3].join(",")
The other long conversion methods like to_int
& to_hash
follow the same logic.
That’s why we have these different methods.
How to Use Conversion Wrappers
If you haven’t had enough conversion methods yet… don’t worry because I have a few more for you!
I like to call these “Conversion Wrappers”.
They are:
- Array()
- Integer()
- Hash[]
That’s some unusually-looking methods right there!
Notice the parenthesis & square brackets…
…it’s the only thing separating these methods from their class names.
What’s the purpose of these?
Array() will convert ANYTHING into an array.
Here’s some examples for you:
Array(nil) # [] Array([]) # [] Array(1) # [1] Array("") # [""]
What kind of logic is this???
Well, this method follows a very specific set of rules:
- If the object responds to
to_ary
, orto_a
it’ll call that & return the value - Otherwise, it will put the object inside an empty array & return that
That explains the behavior shown above.
This is useful if you’re writing a method that expects an array but it could get anything else & make your method crash the whole application. You can make sure it’s an array by passing it to Array()
first to avoid that.
Now Integer()
.
It has some special rules:
- If the object is a string & the contents of the string strictly conform to a valid numeric representation in Ruby this method will return an Integer. Raises
ArgumentError
if invalid format. - If the object isn’t a string it will try to call
to_int
, thento_i
. - It’ll raise a
TypeError
if the object can’t be converted into a validInteger
using a conversion method.
Example:
Integer(1) # 1 Integer("25") # 25 Integer("abc123") # ArgumentError (invalid value for Integer(): "abc123") Integer([]) # TypeError (can't convert Array into Integer)
This Integer()
method is useful if you want to make 100% sure you’re working with a valid Integer
.
Now Hash[]
.
You can pass an array of even elements to get a new hash:
Hash[[["a", 1], ["b", 2], ["c", 3]]] # {"a"=>1, "b"=>2, "c"=>3}
Useful if you are building your hash by merging the elements of two arrays, or using a method like map.
Summary
You’ve learned about the different conversion methods in Ruby, why they exist & how to use them!
I hope you found this helpful 🙂
If you enjoyed this article you’ll also love my book, Ruby Deep Dive, check it out.