Hi everyone,
I have a problem with bidirectional relations : how to implements it ?
I can’t implements it with 2 relations without synchronize them :
no synchronization
class Entity
attr_accessor :mother
attr_reader :daughters
def initialize
@daughters = []
end
end
a = Entity.new
b = Entity.new
a.mother = b
puts (b.daughters.include? a) # false
a.daughters << b
puts (b.mother == a) # false
too bad…
Try with a simple synchronization :
simple synchronization
class Entity
attr_reader :mother, :daughters
def initialize
@daughters = []
end
def mother= m
@mother.daughters.delete self unless @mother.nil?
@mother = m
@mother.daughters << self unless @mother.nil?
end
def add_daughter d
unless d.nil?
@daughters << d
d.mother = self
end
end
end
a = Entity.new
b = Entity.new
a.mother = b
puts (b.daughters.include? a) # true
a.daughters << b # it’s possible so why not use it ?
puts (b.mother == a) # false
ok for some operations, but not exhaustive.
The problem seems to come from @daughters which is a simple Array.
Let’s fix it :
better synchronization
class Entity
attr_reader :mother, :daughters
def initialize
@daughters = []
class << @daughters
attr_accessor :mother
alias old_add <<
def << d, recc=false
old_add d
d.mother = @mother unless recc
end
alias old_delete delete
def delete d
if include? d
d.mother = nil
old_delete d
end
end
end
@daughters.mother = self
end
def mother= m
@mother.daughters.delete self unless @mother.nil?
@mother = m
@mother.daughters.<<(self, true) unless @mother.nil?
end
def add_daughter d
unless d.nil?
@daughters << d
d.mother = self
end
end
end
a = Entity.new
b = Entity.new
a.mother = b
puts (b.daughters.include? a) # true
a.daughters << b
puts (b.mother == a) # true
ok it works (I think), but I need to redefine all methods from
@daughters…
26 lines more than the first (and natural) solution, for a really simple
problem… I don’t think I’ll often use it.
I tried to implement a solution with a real relation, but I had too many
problems.
If anyone has a suggestion (solution or link or anything) to implement
transparent bidirectional relation…
Thanks !