Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Ruby: to_s vs. to_str


(The blockquote style does not look so well so I just pasted directly, but these are all quoted from the links in the bottom of this page)

You should not implement to_str unless your object acts like a string, rather than just having a string representation. The only core class that implements to_str is String itself.

[to_i and to_s] are not particularly strict: if an object has some kind of decent representation as a string, for example, it will probably have a to_s method… [to_int and to_str] are strict conversion functions: you implement them only if you object can naturally be used every place a string or an integer could be used.

to_str is used by methods such as String#concat to convert their arguments to a string. Unlike to_s, which is supported by almost all classes, to_str is normally implemented only by those classes that act like strings. Of the built-in classes, only Exception and String implement to_str

print, puts and string interpolation(#{} syntax) use to_s. Mostly everything else (glob, split, match, string concatenation) uses to_str.

Simple Summary

to_s is defined on every object and will always return something.

to_str is only defined on objects that are string-like. For example, Symbol has to_str but Array does not.

Thus, you can use obj.respond_to?(:to_str) instead of something like obj.is_a?(String) if you want to take advantage of duck typing without worrying about whether the class you're working with is a subclass of String or not.

The documentation for Exception#to_str reads: "By supplying a to_str method, exceptions are agreeing to be used where Strings are expected." So it's all about expectations.

to_s: Give me a String no matter what! to_str: I am pretty sure you are String-like. So sure, that I'd prefer to get a NoMethodException in the case where you're not.

Use case?

Borrowed from Confident Ruby.

class ArticleTitle
  def initialize(text)
    @text = text

  def slug

  def to_str
    puts 'to_str called'

title ="A Modest Proposal")
# By defining #to_str, ArticleTitle can be used in places Ruby expects
# a String:
puts "Today’s Feature: " + title 
# => "to_str called"
# => "Today’s Feature: A Modest Proposal"


Copy link

soulcutter commented Sep 29, 2015

Neither Symbol nor Exception implement #to_s - I know the pickaxe book suggests that Exception does, however that changed long, long ago.

Copy link

pinguinjkeke commented Jan 19, 2017

Thanks for nice explanation!

Copy link

xiangzhuyuan commented Apr 25, 2017


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment