Ruby, Sequel and Trees

While working on some tree structure a couple of unit tests failed, when creating some form of summary of said tree structure. First of all here’s a condensed form of the code:

require 'sequel'

DB = Sequel.sqlite
DB.create_table :items do
  primary_key :id
  String :name
  String :foo, :default => 'NOT SET'
  Integer :item_id
end

class Item < Sequel::Model
  one_to_many :items
  def summary
    if items.empty?
      return [ { self.name => self.foo } ]
    else
      items.inject( [] ){ | r, sub_res | r << sub_res.summary }
    end
  end
end

r1 = Item.create :name => 'R1'
r2 = Item.create :name => 'R2'

r1.add_item r2
r2.foo = 'Ding'
#r2.save

[ r1, r2 ].each{ |i|
  puts "Item    : #{ i.id }"
  puts "Direct Foo: #{ i.foo.inspect }"
  puts "Summary   : #{ i.summary.inspect }"
  puts
}

Notice, that I’ve commented out saving r2. The output is:

Item    : 1
Direct Foo: "NOT SET"
Summary   : [[{"R2"=>"NOT SET"}]]

Item    : 2
Direct Foo: "Ding"
Summary   : [{"R2"=>"Ding"}]

What I didn’t expect – and why the unit tests failed – is the ‘NOT SET’ in the r1 summary.

One way to end up with what I originally expected is to save r2. Another way is to set r2.foo before adding r1 to r1:

r2.foo = 'Ding'
r1.add_item r2

How ever I’m still not sure whether this is intended behaviour and why it should behave like this. (If it is, I’d like to know why.)
What do you think?

Advertisement