Liaison de 3 tables SQL

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 M.

Le 26/05/07, Cyril M. [email protected] a écrit :

Bonjour,

Bonjour,

Dans une application Rails que je suis en train de créer, j’ai un
blocage.

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

nouveau
moyen pourrait peut-être me résoudre mon problème.

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 :wink:

Je suis ouvert à toutes propositions.

On May 26, 2007, at 10:30 AM, Cyril M. wrote:

  • Films
    acteur_id INTEGER,
    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.

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

On 5/26/07, Bastien Q. [email protected] wrote:

ne sais pas trop si ce blocage est une limitation de mon esprit ou de
tables entre elle mais de façon unique. Ainsi en réfléchissant de manière
un nouvel objet model qui schématisera cette nouvelle table composé de

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.

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ôleet 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 :wink:

Merci à toi, j’ai répondu


Cyril M.

Des Acteurs avec plusieurs roles, pour moi cela revient à un Has_many
dans le model acteurs etc…

On 5/26/07, Fabien J. [email protected] wrote:

belongs_to et has_many Mais cela m’imposera de créer cette objet à
chaque fois pour faire une liaison. Car en effet, le

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

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
:frowning:


Cyril M.

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…

On 5/26/07, Differenthink [email protected] 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.

Le 26/05/07, Cyril M. [email protected] a �crit :

J’ai 3 tables :
id INTEGER,
de faire la liaison avec une base interm�diaire que de deux champs, pas
Ensuite passer par une relation :througth sur les models acteur et film qui


Cyril M.

On 5/26/07, Jean-François [email protected] wrote:

nouvelle table composé de
class Film < AR::B
end

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.

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


Cyril M.

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 B. : 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.

On 5/26/07, thegnou [email protected] wrote:

CREATE TABLE acteur_film_role {
Oui et c’est une bonne solution àmha.
has_many :acteurs, :through => :compositions

champs, pas trois.
Cyril M.
donc:
plusieurs films ont le des acteurs qui joue le role de james bond.
à l’aide de l’option :finder_sql.
donc on peut creer une association entre films et acteurs à l’aide
d’une requete sql.

Dans ton exemple tu as tout à fait raison. Mais dans mon cas, le
rôlen’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 M.

On May 26, 3:58 pm, “Cyril M.” [email protected] wrote:

role_id INTEGER

has_many :films, :through => :compositions
class Personnage < AR::B
belongs_to :personnage
Composition.create :acteur => acteur, :film => film, :personnage => personnage

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.

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


Cyril M.

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.