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“.