From: Peter Vandenabeele Date: 2012-02-08T07:22:52+09:00 Subject: Re: Appending to an Array --485b397dd2fd2be06d04b86738b1 Content-Type: text/plain; charset=UTF-8 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] Peter --485b397dd2fd2be06d04b86738b1--