From: Robert Klemme Date: 2012-02-08T17:52:10+09:00 Subject: Re: Appending to an Array On Tue, Feb 7, 2012 at 11:22 PM, Peter Vandenabeele wrote: > On Tue, Feb 7, 2012 at 11:04 PM, Robert Klemme > wrote: > >> On Tue, Feb 7, 2012 at 10:27 PM, Anthony Simonelli >> wrote: >> > I am querying a database using DBI and ODBC.  After I run the execute, I >> > want to grab each row as an array, and add it to another array, >> essentially >> > creating an Array of Arrays.  I've tried this two ways with the same >> result: >> > >> > sth = dbh.execute("SELECT * FROM SOMETABLE") >> > rows = sth.fetch_all >> > >> > and >> > >> > rows = sth.fetch do |row| >> >    rows << row >> > end >> > >> > The result for both is that the last row is repeated in the array however >> > many times there are rows.  Why isn't it appending correctly? >> >> Probably because the DB driver optimizes object allocation and reuses >> the same instance.  Then this is what happens: >> >> irb(main):006:0> rows = [] >> => [] >> irb(main):007:0> a = %w{a b c d} >> => ["a", "b", "c", "d"] >> irb(main):008:0> rows << a >> => [["a", "b", "c", "d"]] >> irb(main):009:0> a[2] = 99 >> => 99 >> irb(main):010:0> rows << a >> => [["a", "b", 99, "d"], ["a", "b", 99, "d"]] >> >> The phenomenon is called "aliasing". >> >> You can solve it by copying row Arrays. >> >> rows = [] >> >> sth.fetch do |row| >>   rows << row.to_a # if rows is not an Array >>  rows << row.dup # if rows is an Array >> end >> > > Would `Array(row)` not be a clean implementation of this ? > > peterv@ASUS:~$ irb > 001:0> row = "a string" > => "a string" > 002:0> Array(row) > => ["a string"] > 003:0> row = [:array_entry] > => [:array_entry] > 004:0> Array(row) > => [:array_entry] Judge for yourself: irb(main):001:0> a = [:x] => [:x] irb(main):002:0> b = Array(a) => [:x] irb(main):003:0> b.equal? a => true irb(main):004:0> a.object_id == b.object_id => true Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/