Liaison de 3 tables SQL

3 views
Skip to first unread message

Cyril Mougel

unread,
May 26, 2007, 4:30:48 AM5/26/07
to ML Rails France
Bonjour,

Dans une application Rails que je suis en train de créer, j'ai un blocage. Je
ne sais pas trop si ce blocage est une limitation de mon esprit ou de rails.
Voici donc mon problème.

J'ai 3 tables :
- Acteurs
- Films
- Roles

Dans chacune d'elle, il y a un champs nom. Mais voilà, je voudrais lier ces 3
tables entre elle mais de façon unique. Ainsi en réfléchissant de manière
purement SQL, je voulais créer une table comme suit :

CREATE TABLE acteur_film_role {
id INTEGER,
acteur_id INTEGER,
film_id INTEGER,
role_id INTEGER
}

Mais avec Rails, impossible de voir comment le schématiser à part en créant
un nouvel objet model qui schématisera cette nouvelle table composé de
belongs_to et has_many Mais cela m'imposera de créer cette objet à
chaque fois pour faire une liaison. Car en effet, le
has_and_belongs_to_many, ne me permet
de faire la liaison avec une base intermédiaire que de deux champs, pas
trois.

En réfléchissant au problème, je n'ai pas non plus vu d'autre moyen conceptuel
pour faire cette liaison à part comme je l'ai fait précédemment. Ce nouveau
moyen pourrait peut-être me résoudre mon problème.

Je suis ouvert à toutes propositions.

Merci


--
Cyril Mougel

Bastien Quelen

unread,
May 26, 2007, 5:10:34 AM5/26/07
to rails...@googlegroups.com


Le 26/05/07, Cyril Mougel <cyril....@gmail.com> a écrit :
Bonjour,


En fait dans la logique rails la méthode est plutôt d'avoir dans la table roles un acteur_id et film_id.
Ensuite passer par une relation :througth sur les models acteur et film qui permettra de faire des film.roles et des acteur.films sans passé par cette table triple relation.
Pour la syntaxe de :througth tu trouvera facilement de la doc dans les archives de la ML et sur le net.

PS: J'ai répondu sur ton blog pour le probéme d'ipv6 ;)
 

Fabien Jakimowicz

unread,
May 26, 2007, 5:59:37 AM5/26/07
to rails...@googlegroups.com

regarde du coté du plugin composite primary keys : http://
compositekeys.rubyforge.org

Differenthink

unread,
May 26, 2007, 6:03:57 AM5/26/07
to Railsfrance
Juste par curiosité, a quoi cela sert d'utilise ce type de shéma... ?
perso je n'utilise que des liaisons avec des foreign key de type
has_many etc....

Je ne vois pas l'interet conceptuel du ::through ..

Merci d'éclairer ma lanterne....

Cyril Mougel

unread,
May 26, 2007, 6:22:27 AM5/26/07
to rails...@googlegroups.com

Le problème est que faire ce système implique qu'un rôle n'a qu'un
seul acteur et film. Hors, il se trouve qu'un acteur peux avoir
plusieurs rôle dans un film, qu'un film a plusieurs acteurs par rôle
et qu'un film plusieurs acteurs. Donc, j'ai pas le choix, cette
possibilité ne pourra pas être utilisé à mon avis.

>
> PS: J'ai répondu sur ton blog pour le probéme d'ipv6 ;)

Merci à toi, j'ai répondu


--
Cyril Mougel

Differenthink

unread,
May 26, 2007, 6:28:42 AM5/26/07
to Railsfrance
Des Acteurs avec plusieurs roles, pour moi cela revient à un Has_many
dans le model acteurs etc....

On 26 mai, 12:22, "Cyril Mougel" <cyril.mou...@gmail.com> wrote:
> On 5/26/07, Bastien Quelen <bastien.que...@gmail.com> wrote:
>
>
>
>
>
> > Le 26/05/07, Cyril Mougel <cyril.mou...@gmail.com> a écrit :

Cyril Mougel

unread,
May 26, 2007, 6:31:57 AM5/26/07
to rails...@googlegroups.com

Je ne suis vraiment pas fan des clé composite. De plus dans mon cas là
clé composite serait composé de 3 champs, ce qui est encore moins bien
:(

--
Cyril Mougel

Cyril Mougel

unread,
May 26, 2007, 6:36:21 AM5/26/07
to rails...@googlegroups.com
On 5/26/07, Differenthink <guillaum...@gmail.com> wrote:
>
> Des Acteurs avec plusieurs roles, pour moi cela revient à un Has_many
> dans le model acteurs etc....

Oui, mais il faut définir un rôle sur tel ou tel film. Je ne peux donc
pas faire de liaison directe sur une des trois tables.


--
Cyril Mougel

Jean-François

unread,
May 26, 2007, 9:50:51 AM5/26/07
to rails...@googlegroups.com
Cyril :

> CREATE TABLE acteur_film_role {
> id INTEGER,
> acteur_id INTEGER,
> film_id INTEGER,
> role_id INTEGER
> }
>
> Mais avec Rails, impossible de voir comment le schématiser à
> part en créant un nouvel objet model qui schématisera cette
> nouvelle table composé de
> belongs_to et has_many

Oui et c'est une bonne solution àmha.

class Acteur < AR::B
has_many :compositions
has_many :films, :through => :compositions
has_many :personnages, :through => :compositions
end

class Film < AR::B

has_many :compositions
has_many :acteurs, :through => :compositions
has_many :personnages, :through => :compositions
end

class Personnage < AR::B
has_many :compositions
has_many :acteurs, :through => :compositions
has_many :films, :through => :compositions
end

Et le "join model" :

class Composition < AR::B
belongs_to :acteur
belongs_to :film
belongs_to :personnage

validates_uniqueness_of :acteur_id, :scope => [ :film_id, :personnage_id ]
end

Pour avoir la liste des films d'un acteur : acteur.films.uniq
tous les personnages qu'il a joués : acteur.personnages.uniq

tous les acteurs qui ont joué James Bond : james_bond.acteurs.uniq

pour créer une composition :
Composition.create :acteur => acteur, :film => film, :personnage => personnage
ou
Composition.create :acteur_id => acteur_id, :film_id => film_id,
:personnage_id => personnage_id

ou sean_connery.compositions.create(:personnage => james_bond,
:film => docteur_no)

etc.

donc on peut manipuler dans tous les sens.

> Mais cela m'imposera de créer cette objet à
> chaque fois pour faire une liaison.

C'est pas la mer à boire.

> Car en effet, le has_and_belongs_to_many, ne me permet
> de faire la liaison avec une base intermédiaire que de deux
> champs, pas trois.

L'autre avantage est que tu peux rajouter des champs
supplémentaire à la table compositions, genre 'doublage_voix'
pour préciser le rôle (j'ai préféré le terme personnage,
mais tu fais comme tu veux) par exemple d'Eddy Murphy
dans Shrek.

-- Jean-François.

--
À la renverse.

Cyril Mougel

unread,
May 26, 2007, 9:58:45 AM5/26/07
to rails...@googlegroups.com


Merci beaucoup Jean-François. Très bonne explication. Je comprend tout.

--
Cyril Mougel

thegnou

unread,
May 26, 2007, 12:36:36 PM5/26/07
to Railsfrance

On May 26, 3:58 pm, "Cyril Mougel" <cyril.mou...@gmail.com> wrote:

je trouve que vous vous compliquez la vie.

un role a 0,n acteurs.
un acteur a 0,n roles.
donc il faut 3 tables:
acteurs 0,n->joue<-0,n roles

un film a 0,n roles
un role a a un seul film
donc:
films 0,n->roles

un film a plusieurs acteurs

ceci est trouvable par nos associations définis ci dessus
films->roles->joues->acteurs
de meme pour un acteur a plusieurs films
acteurs->joue->roles->films

certains pourraient me repliquer que mon modele ne fonctionne pas avec
l'exemple suivant.
plusieurs films ont le des acteurs qui joue le role de james bond.
je reponds que le role de james bon n'est pas le meme dans casino
royal que dans docteur no.
plusieurs roles peuvent avoir le meme nom de personnage.
on peut donc eventuellement rajouter une table pour lever toute
ambiguité:
roles 0,1<->0,n personnages.

il faut noter que les associations de rails ont un sens bcp plus
larges que dans merise ou UML.
on peut tres bien definir une association entre 2 modeles non pas par
une clé etrangere mais par une requete SQL
à l'aide de l'option :finder_sql.
donc on peut creer une association entre films et acteurs à l'aide
d'une requete sql.

Cyril Mougel

unread,
May 26, 2007, 12:48:35 PM5/26/07
to rails...@googlegroups.com

Dans ton exemple tu as tout à fait raison. Mais dans mon cas, le rôle
n'est pas le personnage jouer sur le film, mais le rôle de la personne
dans la réalisation du film. Ainsi une même personne peux donc être
Réalisateur et comédien sur le même film comme l'est par exemple
Sophie Marceaux dans son dernier film.

J'ai implémenté la méthode de Jean-Francois et Bastien, car c'était
lui le premier qui avait parler des through et ca marche
impeccablement. Encore merci.

--
Cyril Mougel

Reply all
Reply to author
Forward
0 new messages