2009-07-10 12 views
2

Compte tenu des ressources suivantes avec leurs relations correspondantes:Rails: Polymorphes ou non?

Site 
has_many :page 
has_many :groups 
has_many :projects 

Group 
belongs_to :site 
has_many :pages 

Project 
belongs_to :site 
has_many :pages 

est-il bon de faire le modèle Page polymorphes ou laisser les clés étrangères individuelles?

**Scenario 1 (Polymorphic)** 
Page 
pageable_id 
pageable_type 
title 
body 
.... 
.... 

**Scenario 2 (Non Polymorphic)** 
Page 
site_id (always filled) 
group_id (may be empty) 
project_id (may be empty) 
title 
body 
.... 
.... 

**Scenario 3 (Combination)** 
Page 
site_id 
pageable_id (may be empty, if page belongs only to site) 
pageable_type (may be empty, if page belongs only to site) 
title 
body 
..... 
..... 

Lequel des 3 scénarios ci-dessus préférez-vous? Et pourquoi (en termes d'efficacité, etc ..)

Note: Dans mon point de vue, je vais traversais à travers toutes les relations possibles de la page pour afficher les liens pertinents (par exemple: si la page appartient pour grouper, je montre le retour au lien de groupe, ...)

Répondre

0

Je pense qu'inclure le site_id dans le modèle n'est pas une bonne idée, car il pourrait casser quand le site_id d'une page appartenant à un groupe doesn ' t correspond au site_id de ce groupe.

qui laisserait tout le scénario 1 ...

Si vous voulez avoir la possibilité de faire un site.pages et obtenir toutes les pages appartenant à ce site (aussi les pages appartenant à un groupe appartenant à ce site), vous pouvez bien sûr écrire votre propre fonction:.

class Site 
    def all_pages 
    Page.find_by_sql(["SELECT p.* FROM pages p, sites s, groups g, projects j WHERE (p.pageable_type='Site' AND p.pageable_id=?) OR (p.pageable_type='Group' AND p.pageable_id=g.id AND g.site_id=?) OR (p.pageable_type='Project' AND p.pageable_id=j.id AND j.site_id=?, self.id, self.id, self.id]) 
    end 
end 

(aussi, je nommerais la colonne pageable_id « parent_id » et pageable_type « PARENT_TYPE » dans ce cas, qui me semble plus logique ...)

+0

J'aime votre approche sur la sélection de toutes les pages, mais comment ça va t o break - "Je pense qu'inclure le site_id dans le modèle n'est pas une bonne idée, car il pourrait casser quand le site_id d'une page appartenant à un groupe ne correspond pas au site_id de ce groupe." Un groupe doit être dans un site et il ne peut pas changer d'un site à l'autre. – Dharam

+0

Dites que vous avez une page et que vous voulez trouver le site qui lui appartient. Lorsque vous incluez le site_id dans le modèle de page, il existe deux façons de le faire (cette page appartient à un groupe): page.site et page.group.site. Dans la plupart des cas, il en résultera le même objet Site, mais il ne doit pas * être * le cas (puisqu'il y a 2 sites_ids impliqués). Bien qu'il y ait une chance faible à nulle que cela se produise, j'essaierais d'empêcher de telles constructions à tout prix. –

+0

@Jongsma - merci pour le retour rapide. – Dharam