To populate an array I could write [*2..10], which gives [2, 3, 4, 5, 6, 7, 8, 9, 10].
How does this work?
To populate an array I could write [*2..10], which gives [2, 3, 4, 5, 6, 7, 8, 9, 10].
How does this work?
The expression 2..10 uses the .. operator to create a Range object.
In general, * flattens arrays, in order to convert a single object into a list of individual arguments to a method.  When applied to a non-array object, it will attempt to convert the object into an Array first by calling to_a on it. So applying * to the Range first calls to_a on it, which returns an array of the values that lie in the range.  That array is then flattened into a list of values by the *.
Finally, putting that list of values inside square brackets [...] generates a new Array.  It's the same result as just calling to_a on the Range, but it's gone through a couple extra steps along the way (flattening by * and unflattening by []).
Note that on the right hand side of an assignment, you can do without the square brackets, whether literal (x=1,2,3 yields the same result as x=[1,2,3]) or splatted (x=*2..10 yields the same result as x=[*2..10]).
The splat operator * unpacks the receiver's elements in place if the receiver is an array. If the receiver is not an array, implicit class conversion is attempted in advance, using the method to_a. 
In your case, range 2..10 is not an array, so to_a is attempted, which succeeds because Range#to_a is defined, and gives [2, 3, 4, 5, 6, 7, 8, 9, 10]. The splat operator unpacks the elements of that array within the outer [], resulting in [2, 3, 4, 5, 6, 7, 8, 9, 10].
Or (1..5).to_a.
Also keep in mind that x..y includes y in the range, but x...y includes up until the y, i.e:
(1...5).to_a
yields [1,2,3,4].