>> a = StringIO.new("abcd")
=> #<StringIO:0xb6e1b354>
>> b = a
=> #<StringIO:0xb6e1b354>
>> b.read
=> "abcd"
>> b = a
=> #<StringIO:0xb6e1b354>
>> b.read
=> ""


Notice the hash signature for b is the same as the hash signature for a. Which is why even though you re-assign it to point to a it's already read the contents of the StringIO you created and hence nils out.

Now see this.


>> a = StringIO.new("abcd")
=> #<StringIO:0xb70570a0>
>> b = a.clone
=> #<StringIO:0xb7055994>
>> b.read
=> "abcd"
>> b = a.clone
=> #<StringIO:0xb7053464>
>> b.read
=> ""


The first time you clone a and point it to b, it creates the hash signature as "#<StringIO:0xb6d968ac>" and the second time you clone it it creates a different hash signature "#<StringIO:0xb7053464>". Hence, multiple clone calls actually still point to different memory space, but it's still the same variable?

Now see this.

>> a = StringIO.new("abcd")
=> #<StringIO:0xb7042240>
>> b = a.clone
=> #<StringIO:0xb7040bfc>
>> b.read
=> "abcd"
>> b.rewind
=> 0
>> b = a.clone
=> #<StringIO:0xb703d1dc>
>> b.read
=> "abcd"
>> b
=> #<StringIO:0xb703d1dc>


Apparently when I clone an object, it still retains the property that StringIO has been read. Which behaves uniquely for StringIO considering the read pointer concept. But yes, somethings amiss.

"I came in with my word,
I will leave with my word intact."
Al Pacino - The Insider