2009-12-01 15 views
5

J'ai commencé à apprendre Datamapper et ce que j'ai aimé c'est que je peux écrire mes modèles avec un héritage réel.Ruby Datamapper héritage de la table avec les associations

Maintenant, je me demande s'il est possible d'être plus avancé à ce sujet:

class Event 
    include DataMapper::Resource 
    property :id, Serial 
    property :begin, DateTime 
    property :type, Discriminator 
end 

class Talk<Event 
    property :title, String 
    belongs_to :meeting 
end 

class Meeting<Event 
    has n, :talks 
end 

que le code ne crée pas la colonne :title pour la Talk et évidemment, la colonne discriminante est de peu de valeur ici, parce que à partir d'une vue de base de données, il doit y avoir des tables distinctes pour Talk et Meeting.

Ainsi, à la fin, je veux Talk et Meeting partager les mêmes propriétés que définies dans Event mais avec des propriétés supplémentaires possibles et avec un 0..1: n relation (Une réunion peut avoir plusieurs entretiens, mais il y a des pourparlers sans réunion.) Existe-t-il un moyen d'accomplir ceci sans répéter les définitions de colonnes et/ou abandonner l'héritage?

Modifier

Pour donner un autre exemple: La partie que j'aime la chose est l'héritage que Event général s peuvent être interrogés séparément. Donc, quand je veux savoir, s'il y a quelque chose à une certaine date, je n'ai pas besoin de regarder dans deux tables ou plus, mais je pourrais juste interroger la table Event. D'une certaine manière, la structure suivante pourrait répondre à mes besoins.

class Event 
    include DataMapper::Resource 
    property :id, Serial 
    property :begin, DateTime 
end 

class Talk 
    include DataMapper::Resource 
    property :id, Serial 
    property :title, String 
    belongs_to :event 
    belongs_to :meeting 
end 

class Meeting 
    include DataMapper::Resource 
    property :id, Serial 
    belongs_to :event 
    has n, :talks 
end 

Cependant, pour l'utiliser, je besoin de créer manuellement un Event chaque fois, je veux créer ou modifier un Talk. Autrement dit, je ne peux pas faire talk.begin ou Talk.create(:begin => Time.now). Y at-il un moyen de contourner cela sans patcher toutes les fonctions et fusionner les propriétés? Je ne veux pas être rappelé de la structure sous-jacente lors de l'utilisation du modèle.

+0

De quel type d'héritage voulez-vous parler par héritage réel - Héritage de table unique, héritage de table de classes ou héritage de table concrète? http://martinfowler.com/eaaCatalog/ – MattMcKnight

+0

Je veux dire l'héritage de la classe Ruby. – Debilski

+0

Peu importe ce que cela signifie sur le plan de la table, je m'en fous - tant que je peux utiliser chaque modèle Ruby séparément et lancer/assigner de la sous-classe au parent et vice versa. – Debilski

Répondre

8

Si vous souhaitez répliquer les attributs de l'événement dans Talk et Réunion vous pouvez le déplacer dans un module:

module EventFields 
    def self.included(base) 
    base.class_eval do 
     include DataMapper::Resource 
     property :id, DataMapper::Types::Serial 
     property :begin, DateTime 
     # other fields here 
    end 
    end 
end 

class Talk 
    include EventFields 
    property :title, String 
    belongs_to :meeting 
end 

class Meeting 
    include EventFields 
    has n, :talks 
end 

Cela vous donnera différentes tables, mais signifie la duplication est réduite.

+0

Mais malheureusement, il n'y a pas de moyen transparent d'interroger tous les événements en même temps, donc je devrais dupliquer pour tous les types d'événements. – Debilski

+0

True, mais l'héritage de table unique est seulement raisonnablement approprié pour les objets qui se comportent différemment mais qui ont la même structure/table sous-jacente. Vous aurez besoin de prendre le hit de stocker tous les attributs (par exemple dans la classe Event) et de construire la logique pour les relations à l'intérieur de chaque classe enfant. Malheureusement, STI suggère qu'il existe une solution de données flexible et magique, mais c'est rarement le cas. Au fur et à mesure que les modèles se sépareront, ils deviendront trop étroitement couplés et le STI n'aura plus de sens. – JamesAlmond

+0

Vous avez raison, je vais devoir faire un compromis de toute façon pour de telles structures. Heureusement, à un certain point, DataMapper :: EmbeddedValue sera disponible pour faciliter votre suggestion. – Debilski