[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Bidirectionnal relation

dohzya

7/24/2007 6:38:00 PM

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 !

--
Etienne Vallette d'Osia


5 Answers

Gavin Kistner

7/24/2007 7:30:00 PM

0

dohzya wrote:
> Hi everyone,
> I have a problem with bidirectional relations : how to implements it ?

How about:
class Female
attr_accessor :mother
def initialize( name )
@name = name
@daughters = []
end
def daughters
@daughters.dup.freeze
end
def mother=( mom )
@mother = mom
unless mom.daughters.include?( self )
mom.add_daughter( self )
end
end
def add_daughter( girl )
@daughters << girl unless @daughters.include?( girl )
girl.mother = self
end
def inspect
"<Female '#{@name}'>"
end
end

a = Female.new( 'Strami' )
b = Female.new( 'Lisa' )
c = Female.new( 'Imogen' )

b.mother = a
p a.daughters.include?( b )
#=> true

b.daughters << c
#=> Error: can't modify frozen array (TypeError)

b.add_daughter c

p a.daughters
#=> [<Female 'Lisa'>]

p b.daughters
#=> [<Female 'Imogen'>]

p c.mother
#=> <Female 'Lisa'>
--
Posted via http://www.ruby-....

Pit Capitain

7/25/2007 4:26:00 PM

0

2007/7/24, dohzya <dohzya@gmail.com>:
> I have a problem with bidirectional relations : how to implements it ?
> (...)
> If anyone has a suggestion (solution or link or anything) to implement
> transparent bidirectional relation... :)

Hi Etienne,

in ruby-talk:121602 I posted a little library to implement this.
Here's your example:

require "relation"

class Entity
end

Relation.new Entity, :one, :mother, Entity, :many, :daughters

a = Entity.new
b = Entity.new

a.mother = b
puts(b.daughters.include?(a)) # => true

a.daughters << b
puts(b.mother == a) # => true


If you find nothing else maybe I should create my first gem...

Regards,
Pit

dohzya

7/25/2007 6:04:00 PM

0

Le jeudi 26 juillet 2007 à 01:25 +0900, Pit Capitain a écrit :
> 2007/7/24, dohzya <dohzya@gmail.com>:
> > I have a problem with bidirectional relations : how to implements it ?
> > (...)
> > If anyone has a suggestion (solution or link or anything) to implement
> > transparent bidirectional relation... :)
>
> Hi Etienne,
>
> in ruby-talk:121602 I posted a little library to implement this.
> Here's your example:
>
> require "relation"
>
> class Entity
> end
>
> Relation.new Entity, :one, :mother, Entity, :many, :daughters
>
> a = Entity.new
> b = Entity.new
>
> a.mother = b
> puts(b.daughters.include?(a)) # => true
>
> a.daughters << b
> puts(b.mother == a) # => true
>
>
> If you find nothing else maybe I should create my first gem...
>
> Regards,
> Pit
>

Why find again ? it's exactly what I want !

I wait for your gem, thanks :)

--
Etienne


dohzya

7/25/2007 6:55:00 PM

0

Le jeudi 26 juillet 2007 à 01:25 +0900, Pit Capitain a écrit :
> 2007/7/24, dohzya <dohzya@gmail.com>:
> > I have a problem with bidirectional relations : how to implements
it ?
> > (...)
> > If anyone has a suggestion (solution or link or anything) to
implement
> > transparent bidirectional relation... :)
>
> Hi Etienne,
>
> in ruby-talk:121602 I posted a little library to implement this.
> Here's your example:
>
> require "relation"
>
> class Entity
> end
>
> Relation.new Entity, :one, :mother, Entity, :many, :daughters
>
> a = Entity.new
> b = Entity.new
>
> a.mother = b
> puts(b.daughters.include?(a)) # => true
>
> a.daughters << b
> puts(b.mother == a) # => true
>
>
> If you find nothing else maybe I should create my first gem...
>
> Regards,
> Pit
>

Why find again ? it's exactly what I want !

I wait for your gem, thanks :)

--
Etienne


dohzya

7/26/2007 8:08:00 AM

0

Le jeudi 26 juillet 2007 à 01:25 +0900, Pit Capitain a écrit :
> 2007/7/24, dohzya <dohzya@gmail.com>:
> > I have a problem with bidirectional relations : how to implements
it ?
> > (...)
> > If anyone has a suggestion (solution or link or anything) to
implement
> > transparent bidirectional relation... :)
>
> Hi Etienne,
>
> in ruby-talk:121602 I posted a little library to implement this.
> Here's your example:
>
> require "relation"
>
> class Entity
> end
>
> Relation.new Entity, :one, :mother, Entity, :many, :daughters
>
> a = Entity.new
> b = Entity.new
>
> a.mother = b
> puts(b.daughters.include?(a)) # => true
>
> a.daughters << b
> puts(b.mother == a) # => true
>
>
> If you find nothing else maybe I should create my first gem...
>
> Regards,
> Pit
>

Why find again ? it's exactly what I want !

I wait for your gem, thanks :)

(and I hate my mail client...)

--
Etienne