Feb 082012
 

Often Array(arg) is used for this, but is flawed. Note the last result when applied to a Hash:

> Array(42)
 => [42] 
> Array([1,2,3])
 => [1, 2, 3] 
> Array(nil)
 => [] 
> Array("foo")
 => ["foo"] 
> Array({"foo" => "bar", "biz" => "baz"})
 => [["foo", "bar"], ["biz", "baz"]]

What went wrong is that Array() calls the (now deprecated) to_a on each of its arguments. Hash has a custom to_a implementation with different semantics. Instead, do  this:

class Array
  def self.wrap(args)
    return [] unless args
    args.is_a?(Array) ? args : [args]
  end
end

That yields the expected results, even for Hashes:

> Array.wrap(42)
 => [42] 
> Array.wrap([1,2,3])
 => [1, 2, 3] 
> Array.wrap(nil)
 => [] 
> Array.wrap("foo")
 => ["foo"] 
> Array.wrap({"foo" => "bar", "biz" => "baz"})
 => [{"foo"=>"bar", "biz"=>"baz"}]

Use of is_a? is deliberate; duck-typing in this situation ([:[], :each].all? { |m| args.respond_to? m }) yields unexpected surprises since e.g. String is Enumerable and would not get wrapped.

For further discussion see Ruby-forum thread “shortcut for x = [x] unless x.is_a?(Array)” and StackOverflow “Ruby: Object.to_a replacement“.

 Tagged with:

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)