From: Rob Biedenharn Date: 2010-09-23T04:43:23+09:00 Subject: Re: Odd behavior when << hash On Sep 22, 2010, at 3:33 PM, Alex Stahl wrote: > Hi Folks - Using Ruby 1.8.7, I found this oddity: > > require 'rubygems' > require 'json' > > setup = [] > ids = ["12345", "54321", "21345", "548752", "3215", "50203"] > > doIt = { > "action" => "do something", > "result" => "true" > } > # so here, doIt is referencing an object which is a hash > cnt = rand(10) > 1.upto(cnt) do > > doIt['params'] = ids[rand(6)] > p "Pushing step: #{doIt.inspect}" > setup << doIt # this puts that reference into the setup array # NOTE: it is always referring to the same hash > end > > p "Final steps list: #{setup.inspect}" > > ************************************** > > When I inspect my final steps list at the end, the values of > 'doIt['params']' is always the same - set to the last value of the > last > run of the upto loop. But when I inspect doIt prior to pushing it, I > can see that it has its own value, acquired randomly. > > So my question is, why is the hash not being pushed onto the array > properly? What side effect am I encountering here and how do I get > around it? > > (I've already tried declaring "params" => "" in the initial hash > creation; that didn't help). > > Thanks, > Alex > > PS - You'd be correct in noting this code doesn't do anything useful. > I've stripped away other parts to isolate the questionable behavior > for > demonstration purposes. > > Try creating the hash object inside the loop (i.e., creating a new object each time) rand(10).times do setup << { "action" => "do something", "result" => "true", "params" => ids[rand(6)].dup } end puts "Final steps list: #{setup.inspect}" Note that I'm also calling .dup on the element taken from the ids array so there's a separate string object. You can apply this to your real code, I hope. -Rob Rob Biedenharn Rob@AgileConsultingLLC.com http://AgileConsultingLLC.com/ rab@GaslightSoftware.com http://GaslightSoftware.com/