#1013 ✓resolved
Jerry West

Is:Tree does not play with STI

Reported by Jerry West | August 19th, 2009 @ 09:39 AM

(This is probably a symptom of the various associations/STI bugs already reported)

Is::Tree does not play with STI. The tree expects parents and children to be of the same type if sub classes derive directly from the main STI class (but will 'know' about children (but not parents) if told explicitly or if sub-classes are derived heirarchically from each other).

In practice this means either children() or parent() or both are wrong.

reproduce by...

require 'dm-core'
require 'dm-types'
require 'dm-aggregates'
require 'dm-is-tree'

DataMapper.setup(:default, 'sqlite3::memory:')
class Caption
  include DataMapper::Resource

  property :id,         Serial
  property :type,       Discriminator
  property :caption,    String, :null => false
  property :parent_id,  Integer

  is :tree

class Competency < Caption; end
class Indicator < Caption;  end 
class Behaviour < Caption; end

# where a Competency has many Indicators each of which have many Behaviours.

r=Caption.create(:caption => 'root')
# r.children.create creates a Caption, we want a Competency
c=Competency.create(:caption => 'C1', :parent_id => r.id)
# I'm happy using this form, children.create is nice but not essential
i=Indicator.create(:caption => 'I1', :parent_id => c.id)
b=Behaviour.create(:caption => 'B1', :parent_id => i.id)

Caption.count # => 4

# it works for root (why?)
r.children.first == c

# but nothing else
c.children == [] # !!
c.parent == nil # !!
Indicator.first == i; i.parent_id == 2; c.id == 2 # as expected
i.parent == nil # !!

# You can give Is::Tree a workaround

# tell Competency about Indicators (or declare class Indicator < Competency)
class Competency < Caption
  is :tree, :class_name => 'Indicator' 

Competency.first.children.first == Indicator.first # as expected

Indicator.first.parent != Competency.first # (it's nil)
#i.e. Competency.first.children.first.parent != Competency.first

It may be that Is::Tree cannot be expected to work out both child and parent classes, but why does it need to? Surely STI should take care of record retrieval, Is::Tree simply has to ask for the correct (id == parent_id)... Or am I being naive?


PS: I suppose its too late to apply the Law of Demeter to these !$^&%*! rails-inspired associations (why does the caller need to know the internal properties of another table...?)

Comments and changes to this ticket

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »