Array.unwrap

Hi,

I thought it’d be useful to have a method that is the opposite of Array.wrap.

I’ve got this simple change drafted introducing Array.unwrap.

https://github.com/carnesmedia/rails/compare/unwrap

I’ve found this useful in situations where I know I’ll get a one-element array, and I just want the element, such as an api request that always returns an array even though I asked for a single result, or when I’m not sure I’ll get an array or single element (the same situation as Array.wrap except I want the single element of an array containing that element).

Anyway, I’m looking for feedback. Does anyone have thoughts before I make this a pull-request?

-Amiel http://carnesmedia.com

I've found this useful in situations where I know I'll get a one-element array, and I just want the element, such as an api request that always returns an array even though I asked for a single result, or when I'm not sure I'll get an array or single element

$ irb irb(main):001:0> a = 1 => 1 irb(main):002:0> Array(a) => [1] irb(main):003:0> a = [1,2,3] => [1, 2, 3] irb(main):004:0> Array(a) => [1, 2, 3]

I think, sadly, I have to -1 on this one. It does not clear when I see this method what would happen when you pass in array with multiple elements, or when the array unexpextedly have moret than one element. Assume that that array will always has 1 element is … Not a good idea.

I think it’s already clear and make sense to just call .first or [0] on it. Since you would be like “I don’t care how many things it has in it, I want the first one.”

-Prem

Actually, I guess it'd be

$ irb irb(main):001:0> a = 1 => 1 irb(main):002:0> Array(a)[0] => 1 irb(main):003:0> a = [1,2,3] => [1, 2, 3] irb(main):004:0> Array(a)[0] => 1

Steve and Prem,

I guess I thought Array.unwrap made more sense semantically in some situations, and that it’d be nice to have an opposite for Array.wrap.

I can see that it doesn’t make sense to add to ActiveSupport.

Thanks for reviewing,

-Amiel

I’ve been on a project where we had added a method something like the following

class Array

def only_element

raise ‘array has too many elements’ if length > 1

first

end

end

and so we used to get the only element out of arrays that way.

Having an array in which you are sure there is only a single element is something that many would call a smell.

However, I think this is off topic for Rails core now.

Not meaning to be a thread necromancer here, but I literally am in a pairing session right now where I said “I really want a method that does the inverse of Array.wrap, like Array.unwrap…wait a minute, does it exist already” and then I found this thread.

Your original code change is long gone, but I wanted to revive this discussion, on these grounds:

  1. Array.wrap is new Array behavior that is introduced in ActiveSupport; therefore an enhancement like this would also belong in ActiveSupport
  2. Array.wrap provides a new simple behavior for Array
  3. Array.unwrap would provide inverse-parity with Array.wrap and is named in a fashion that suggests the behavior intuitively, if you already know the behavior of .wrap (bonus if we can have an instance-level method, Array#wrap)

The use-case my coworker and I encountered was:

CGI::parse('foo=bar&baz=bat')
=> { "foo" => ['bar'], "baz" => ['bat'] }

It puts all the parameters into individual arrays which is fine as a default behavior, but like the OP, we wanted the elements to be singular strings instead of arrays. So something like this:

CGI::parse('foo=bar&baz=bat&array_param[]=one&array_param[]=two').transform_values!(&:unwrap)
=> { "foo" => 'bar', "baz" => 'bat', "array_param" => ['one', 'two'] }

The default behavior should cleanly invert:

a = Array.wrap('b')
=> ['b']
Array.unwrap(a)
=> 'b'

Anyways, no idea if it’s possible to add this still, but I would also love to see it and wanted OP to know they weren’t alone in thinking of this. :slight_smile: GMTA!