bnjmn.

implicit conversions in ruby

2025-02-08

Say you’re working with a directory:

dirpath = '.'
dir = Dir.open(dirpath)

And you want to do something with the files in that directory:

dir.each do |filename|
  filepath = "#{dirpath}/#{filename}"
  p File.read(filepath) if File.file?(filepath)
end

But you don’t want to keep having to interpolate strings, so you create a class to make your life easier:

class MyFile
  attr_reader :path

  def initialize(dirpath, filename)
    @path = "#{dirpath}/#{filename}"
  end
end

dir.each do |filename|
  f = MyFile.new(dirpath, filename)
  p File.read(f.path) if File.file?(f.path)
end

Ruby has a built-in feature called “implicit conversion”, where it will try to perform a conversion if certain methods on the class exist. Which means we can do this instead:

class MyFile
  def to_str
    @path
  end
end

dir.each do |filename|
  f = MyFile.new(dirpath, filename)
  p File.read(f) if File.file?(f) # no need to call #path anymore
end

File.read expects a string, but we pass it an instance of MyFile, which has a to_str method - so Ruby performs an implicit conversion and treats it like a string.

I think I like this, but I’m sure there’s a ton of reasons why you wouldn’t want this kind of implicit behaviour.