-
Notifications
You must be signed in to change notification settings - Fork 0
Les associations en Rails: Partie 07
polymorphic
est utilisé pour regrouper les associations d'un modèle vers plusieurs autre modèles en une seule association polymorphique. Prenons par exemple le cas d'un simple réseau social: les utilisateurs dans ce réseau peuvent publier:
- Soit des messages (courts, à la twitter)
- Soit des articles (formatés)
- Soit des images
Bien sûr, chaque forme de publication aura son propre modèle. Supposons aussi que les autres utilisateurs peuvent commenter les trois genres de publications, les commentaires auront aussi leur propre modèle.
On va oublier le modèle User
bien qu'il soit nécessaire dans un tel cas, car ce qui nous intéresse sont les relations entre les publications et les commentaires.
On se retrouve donc avec quatre modèles: Messages
, Articles
, Images
et Comments
, ce dernier devra appartenir à chacun des trois autres modèles.
L'ERD est:
On voit qu'il y a redondance dans la déclaration de belongs_to
dans le modèleComment
, et qu'il y a trop de clés étrangères dans la table Comments, s'il y avait plus d'entités qui peuvent être commentées ce nombre n'en sera que plus grand.
L'idée est de remarquer que les trois modèles auxquels appartient Comment
partagent la même propriété vis-à-vis de leur lien à Comment
, à savoir, ils sont commentables! L'idée donc est d'imaginer une classe virtuelle appelée Commentable
et de faire en sorte que le belongs_to
pointe vers cette classe de façon polymorphique. Voyons comment on peut le faire:
En console cela donne:
2.4.0 :001 > a = Article.new
=> #<Article id: nil, title: nil, content: nil, user_id: nil, created_at: nil, updated_at: nil>
2.4.0 :002 > c = Comment.new
=> #<Comment id: nil, content: nil, commentable_type: nil, commentable_id: nil, created_at: nil, updated_at: nil>
2.4.0 :003 > c.commentable = a
=> #<Article id: nil, title: nil, content: nil, user_id: nil, created_at: nil, updated_at: nil>
2.4.0 :004 > c.save
(0.3ms) begin transaction
SQL (0.5ms) INSERT INTO "articles" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2017-07-14 18:08:49.067969"], ["updated_at", "2017-07-14 18:08:49.067969"]]
SQL (0.2ms) INSERT INTO "comments" ("commentable_type", "commentable_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["commentable_type", "Article"], ["commentable_id", 2], ["created_at", "2017-07-14 18:08:49.083467"], ["updated_at", "2017-07-14 18:08:49.083467"]]
(361.3ms) commit transaction
=> true
2.4.0 :005 > a.reload.comments.count
Article Load (0.6ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
(0.2ms) SELECT COUNT(*) FROM "comments" WHERE "comments"."commentable_id" = ? AND "comments"."commentable_type" = ? [["commentable_id", 2], ["commentable_type", "Article"]]
=> 1