---
title: "to_str in ruby"
description:
  "to_str has a special meaning in ruby. This blog discusses that in detail and
  contrats it with to_s."
canonical_url: "https://www.bigbinary.com/blog/to_str-in-ruby"
markdown_url: "https://www.bigbinary.com/blog/to_str-in-ruby.md"
---

# to_str in ruby

to_str has a special meaning in ruby. This blog discusses that in detail and
contrats it with to_s.

- Author: Neeraj Singh
- Published: June 26, 2012
- Categories: Ruby

_Following code was tested with ruby 1.9.3 ._

## All objects have to_s method

`to_s` method is define in `Object` class and hence all ruby objects have method
`to_s`.

Certain methods always call `to_s` method. For example when we do string
interpolation then `to_s` method is called. `puts` invokes `to_s` method too.

```ruby
class Lab
 def to_s
  'to_s'
 end
 def to_str
  'to_str'
 end
end

l = Lab.new
puts "#{l}" #=> to_s
puts l #=> to_s
```

`to_s` is simply the string representation of the object.

Before we look at `to_str` let's see a case where ruby raises error.

```ruby
e = Exception.new('not sufficient fund')

# case 1
puts e

# case 2
puts "notice: #{e}"

# case 3
puts "Notice: " + e
```

Here is the result

```text
not sufficient fund
Notice: not sufficient fund
`+': can't convert Exception into String (TypeError)
```

In the first two cases the `to_s` method of object `e` was printed.

However in case '3' ruby raised an error.

Let's read the error message again.

```text
`+': can't convert Exception into String (TypeError)
```

In this case on the left hand side we have a string object. To this string
object we are trying to add object `e`. Ruby could have called `to_s` method on
`e` and could have produced the result. But ruby refused to do so.

Ruby refused to do so because it found that the object we are trying to add to
string is not of type String. When we call `to_s` we get the string
representation of the string. But the object might or might not be behaving like
a string.

Here we are not looking for the string representation of `e`. What we want is
for `e` to behave a like string. And that is where `to_str` comes in picture. I
have a few more examples to clear this thing so hang in there.

## What is to_str

If an object implements `to_str` method then it is telling the world that my
class might not be `String` but for all practical purposes treat me like a
string.

So if we want to make exception object behave like a string then we can add
`to_str` method to it like this.

```ruby
e = Exception.new('not sufficient fund')

def e.to_str
  to_s
end

puts "Notice: " + e #=> Notice: not sufficient fund
```

Now when we run the code we do not get any exception.

## What would happen if Fixnum has to_str method

Here is an example where ruby raises exception.

```ruby
i = 10
puts '7' + i #=> can't convert Fixnum into String (TypeError)
```

Here Ruby is saying that Fixnum is not like a string and it should not be added
to String.

We can make Fixnum to behave like a string by adding a `to_str` method.

```ruby
class Fixnum
  def to_str
    to_s
  end
end
i = 10
puts '7' + i #=> 710
```

The practical usage of this example can be seen here.

```text
irb(main):002:0> ["hello", "world"].join(1)
TypeError: no implicit conversion of Fixnum into String
```

In the above case ruby is refusing to invoke `to_s` on "1" because it knows that
adding "1" to a string does not feel right.

However we can add method `to_str` to Fixnum as shown in the last section and
then we will not get any error. In this case the result will be as shown below.

```text
irb(main):008:0> ["hello", "world"].join(1)
=> "hello1world"
```

## A real practical example of defining to_str

I [tweeted](https://twitter.com/neerajsingh0101/status/217128187489042432) about
[a quick lesson in to_s vs to_str](https://github.com/rails/rails/commit/188cc90af9b29d5520564af7bd7bbcdc647953ca)
and a few people asked me to expand on that. Lets see what is happening here.

Before the refactoring was done `Path` is a subclass of `String`. So it is
String and it has all the methods of a string.

As part of refactoring `Path` is no longer extending from `String`. However for
all practical purposes it acts like a string. This line is important and I am
going to repeat it. For all practical purposes `Path` here is like a `String`.

Here we are not talking about the string representation of `Path`. Here `Path`
is so close to `String` that practically it can be replaced for a string.

So in order to be like a `String` class `Path` should have `to_str` method and
that's exactly what was done as part of refactoring.

During discussion with my friends someone suggested instead of defining `to_str`
tenderlove could have just defined `to_s` and the result would have been same.

Yes the result would be same whether you have defined `to_s` or `to_str` if you
doing `puts`.

```ruby
puts Path.new('world')
```

However in the following case just defining `to_s` will cause error. Only by
having `to_str` following case will work.

```ruby
puts 'hello ' + Path.new('world')
```

So the difference between defining `to_s` and `to_str` is not just what you see
in the output.

## Conclusion

If a class defines `to_str` then that class is telling the world that although
my class is not `String` you can treat me like a `String`.

## Links

- [Human page](https://www.bigbinary.com/blog/to_str-in-ruby)
