Reason #155 •
June 4th, 2026
Treating nil values as strings with to_s
One of the wonderful things about Ruby is how its nil value is an object, just like all other values. Its class is NilClass and it defines to_s to return an empty string. This can be quite handy to save us from adding explicit fallbacks in our call chains:
Ruby
ENV["SOME_ENV_VAR"].to_s.downcase.gsub(/\s+/, "_")
posts = [
{
title: "Treating nil values as strings with to_s",
body: "One of the wonderful things...",
tags: "ruby,programming,development",
},
{
title: "Draft: method_missing",
body: nil,
tags: nil,
},
]
post1_tags = posts.dig(0, :tags).to_s.split(",").map(&:upcase)
# => ["RUBY", "PROGRAMMING", "DEVELOPMENT"]
post2_tags = posts.dig(1, :tags).to_s.split(",").map(&:upcase)
# => []
post3_tags = posts.dig(2, :tags).to_s.split(",").map(&:upcase)
# => []
JavaScript
(process.env.SOME_ENV_VAR || "").toLowerCase().replace(/\s+/g, "_");
const posts = [
{
title: "Treating nil values as strings with to_s",
body: "One of the wonderful things...",
tags: "ruby,programming,development",
},
{
title: "Draft: method_missing",
body: null,
tags: null,
},
];
const post1Tags = (posts[0]?.tags?.split(",") || [])
.map(tag => tag.toUpperCase());
// => ["RUBY", "PROGRAMMING", "DEVELOPMENT"]
const post2Tags = (posts[1]?.tags?.split(",") || [])
.map(tag => tag.toUpperCase());
// => []
const post3Tags = (posts[2]?.tags?.split(",") || [])
.map(tag => tag.toUpperCase());
// => []
As you can see, using to_s can be a nice alternative to using || for fallback values and safe navigation (known as "optional chaining" in JS) to avoid errors when trying to call methods on nil. This keeps our code confident even when dealing with inconsistent data.
History
NilClass#to_s has been around since Ruby's inception.
Ruby 2.7 made it a little more efficient by returning the same frozen empty string for nil.to_s, instead of allocating a new empty string on every call.