Define Conversion Protocols in Ruby

This article is an excerpt from my in-progress book, "Confident Ruby".

The problem

You need to ensure inputs are of a core type with context-specific extra semantics.

The approach

Define new implicit conversion protocols mimicking Ruby’s native protocols such as #to_path.


Ruby defines a number of protocols for converting objects into core types such as String, Array, and Integer. But there may come a time when the core protocols don’t capture the conversion semantics your apps or libraries need.

Consider a 2D drawing library. Points on the canvas are identified by X/Y pairs. For simplicity, these pairs are simply two-element arrays of integers.

Ruby defines #to_a and #to_ary for converting to =Array=s. But that doesn’t really capture intent of converting to an X/Y pair. Just like the #to_path conversion used by, even though we are converting to a core type we’d like to add a little more meaning to the conversion call. We’d also like to make it possible for an object to have a coordinate conversion even if otherwise it doesn’t really make sense for it to have a general Array conversion.

In order to capture this input requirement, we define the #to_coords conversion protocol. Here’s a method which uses the protocol:

Later, we decide to encapsulate coordinate points in their own Point class, enabling us to attach extra information like the name of the point. We define a #to_coords method on this class:

We can now use either raw X/Y pairs or Point objects interchangeably:

But the #to_coords protocol isn’t limited to classes defined in our own library. Client code which defines classes with coordinates can also define #to_coords conversions. By documenting the protocol, we open up our methods to interoperate with client objects which we had no inkling of at the time of writing.

If you enjoyed this excerpt from Confident Ruby, why not get the whole book? Early access is available now!