Implicit vs explicit type conversions in Ruby (to_h/to_hash and others)
Just a quick reference post.
There are several pairs of type coercions methods in Ruby:
to_i
andto_int
;to_s
andto_str
;to_a
andto_ary
;to_h
andto_hash
.
What’s the difference and when to use/implement each of pair?
Shorter version is explicit conversion:
- your type should implement if it can be somehow converted into target type (integer, string, array and so on);
- you should call those method on incoming data, if you expect it to have some means of converting to target type.
Longer version is implicit conversion:
- your type should implement it only if it sees itself as “kind of” target type (“better” or “specialized” number, string, array, hash);
- you should call those methods on incoming data, if you have strict requirement for it being of target type, but want to check it in Ruby way, with duck typing, not class comparison;
- you should not implement and use this methods in other cases!
Most of Ruby operators and core methods use implicit conversions on data:
"string" + other
will call#to_str
onother
,[1,2,3] + other
will call#to_ary
and so on (and will raiseTypeError: no implicit conversion
if object not responds to this methods);"string" * other
and[1,2,3] * other
will call#to_int
onother
;a, b, c = *other
will callother#to_ary
(and, therefore, can be used to “unpack” custom collection objects—but also can cause unintended behavior, ifother
implementsto_ary
but was not thought as a collection);some_method(*other)
—same as above, usesother#to_ary
;some_method(**other)
—new in Ruby 2, usesother#to_hash
.
I should repeat: never implement implicit conversion methods unless
you sure know what you are doing! It is widely seen, for example, the
#to_hash
method being implemented (maybe because of “prettier name”
than #to_h
?) and causing strangest effects.
Practical example:
See also: