In Ruby, = takes a list of variables on the left, and a list of expressions on the right. It assigns the the first variable to the value of the first expression, the second variable the value of the second expression, and so on. If there are more variables than expressions, the leftover variables get assigned the value nil.
> a, b, c, d = "foo", 2+3, Array.new(2, 3), [:c, :d]
> a # => "foo"
> b # => 5
> c # => [3, 3]
> d # => [:c, :d]
> e # => nil
There are two exceptions:
Left side has only one variable, right side has multiple expressions
In this case, the above rule would say that the variable just gets set to the value of the first expression on the right. Instead, the variable gets set to the Array consisting of the values of the expression on the right. In the example below, we see a gets the value [:b, :c], instead of just :b:
> a = :b, :c
> a # => [:b, :c]
This is equivalent to:
> *a = :b , :c
> a # => [:b, :c]
The other exception:
The left side has multiple variables, the right side has only one expression and it's an Array
Again, the original rule would imply that the first variable gets set to that whole Array, and the rest of the variables would be nil. However, that Array effectively ends up getting replaced with the list of its elements, and then = reverts to the "default" behaviour described in the beginning:
> a, b, c = [:d, [:e, :f]]
> a # => :d
> b # => [:e, :f]
> c # => nil
This is equivalent to a, b, c = *[:d, [:e, :f]], or just a, b, c = :d, [:e, :f]