Sunday, November 23, 2008

Ruby: Treat object and collection uniformly

Problem: You write a method that takes a collection and iterates over it. However, you also want to accept a single object parameter as well.

Solutions: Convert a single object into an array so that we can manipulate the parameter uniformly. As always, there are many ways to do this in Ruby. However, I prefer the last one.

1. Make sure it is an array by using Object#to_a. However, to_a is deprecated and not recommended.

def f(a)
a = a.to_a
a.each { |item| ... }
...
end


2. Check the parameter type and wrap it into an array if it is not an array already.

def f(a)
a = [a] if a.is_a? Array
...
end


3. Duck-type check whether it responds to :each method

def f(a)
a = [a] unless a.respond_to? :each
...
end


4. Use splat operator. This also does the job. It is concise but less readable.

def f(a)
a = [*a]
...
end


5. Use Array#flatten. I prefer this one. It is readable.

def f(a)
a = [a].flatten
...
end


Is there any other more way?

No comments: