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