I often need to convert some kind of data into other data (usually strings, arrays and hashes). For example:
- input:
"a;simple;list"
expected_output
:[ { content: "a", length: 1 }, { content: "simple", length: 6 }, { content: "list", length: 4 } ]
This can be done by:
input.split(";").map{|s| { content: s, length: s.size } }
but I want to use conversion at different places. So I need to provide encapsulated logic to achieve and reuse this. Three ways pop into mind:
Use a helper method (put a single method into a module):
module Converter extend self def convert(input) input.split(";").map{|s| { content: s, length: s.size } } end end module Caller Converter.convert(input) end
Use a dedicated class with parameters:
class Converter def initialize(input) @input = input end def convert @input.split(";").map{|s| { content: s, length: s.size } } end end module Caller Converter.new(input).convert end
Use refinements, using monkey patching to create a method on the data object but letting a caller decide if it should be included.
module Converter refine String do def convert self.split(";").map{|s| { content: s, length: s.size } } end end end module Caller using Converter input.convert end
I'm not satisfied with any of them, but the third option seems the cleanest because that is usually what you would do if you deal with custom objects. But it also feels wrong because it's monkey patching light. What are your thoughts?