2009-12-01 10 views
5

Ich begann zu lernen Datamapper und was ich daran mochte war, dass ich meine Modelle mit echter Vererbung schreiben kann.Ruby Datamapper Tabellenvererbung mit Assoziationen

Jetzt frage ich mich, wenn es möglich ist, über diese weiter fortgeschritten zu sein:

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 

Diesen Code die :title Spalt für die Talk erstellen schlägt fehl, und offensichtlich die Diskriminator Spalte von geringen Wert ist hier, weil Aus einer Datenbanksicht sollten separate Tabellen sowohl für als auch für Meeting vorhanden sein.

So, am Ende mag ich Talk und Meeting die gleichen Eigenschaften zu teilen, wie in Event definiert, aber mit möglichen zusätzlichen Eigenschaften und mit einem 0..1: n-Beziehung (ein Treffen mehr Gespräche haben kann, aber es gibt Gespräche ohne ein Treffen.) Gibt es eine Möglichkeit, dies zu erreichen, ohne entweder die Spaltendefinitionen zu wiederholen und/oder die Vererbung aufzugeben?

bearbeiten

ein weiteres Beispiel zu geben: Der Teil, den ich über das Erbe, was gefällt, ist, dass allgemeine Event s separat abgefragt werden können. Also, wenn ich wissen will, ob es etwas bei einem bestimmten :begin Datum gibt, muss ich nicht in zwei oder mehr Tabellen suchen, sondern könnte einfach die Event Tabelle abfragen. In gewisser Weise könnte die folgende Struktur meinen Bedürfnissen entsprechen.

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 

Um jedoch diese zu verwenden, würde ich brauchen, um manuell eine Event jedes Mal zu erstellen, ich möchte eine Talk erstellen oder zu bearbeiten. Das heißt, ich kann talk.begin oder Talk.create(:begin => Time.now) nicht tun. Gibt es einen Weg darum, ohne alle Funktionen zu patchen und die Eigenschaften zusammenzuführen? Ich möchte nicht an die zugrunde liegende Struktur erinnert werden, wenn ich das Modell verwende.

+0

Welchen Typ der Vererbung meinen Sie mit echter Vererbung - Vererbung einzelner Tabellen, Vererbung von Klassentabelle oder Vererbung von konkreten Tabellen? http://martinfowler.com/eaaCatalog/ – MattMcKnight

+0

Ich meine Ruby-Klasse Vererbung. – Debilski

+0

Was auch immer das für Tabellen bedeutet, ist mir egal - solange ich jedes Ruby-Modell separat verwenden und von Unterklasse zu Eltern und zurück umwandeln kann. – Debilski

Antwort

8

Wenn Sie die Attribute des Events in Google Talk und Meeting replizieren möchten, dann können Sie es in ein Modul verschieben:

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 

Dies wird Ihnen verschiedene Tabellen geben aber bedeutet Duplizierung reduziert.

+0

Aber das bedeutet unglücklicherweise, dass es keinen transparenten Weg gibt, alle Ereignisse gleichzeitig abzufragen, also müsste ich für alle Arten von Ereignissen duplizieren. – Debilski

+0

Wahr, aber die Vererbung einzelner Tabellen ist nur angemessen für Objekte geeignet, die sich unterschiedlich verhalten, aber dieselbe zugrunde liegende Struktur/Tabelle haben. Sie müssen alle Attribute (z. B. in der Event-Klasse) speichern und die Logik für die Beziehungen in jeder untergeordneten Klasse erstellen. Leider schlägt STI vor, dass es eine magisch flexible Datenlösung gibt, aber das ist selten der Fall. Wenn die Modelle auseinander wachsen, werden sie zu eng miteinander verbunden und STI wird keinen Sinn mehr ergeben. – JamesAlmond

+0

Sie haben Recht, ich werde sowieso einen Kompromiss für solche Strukturen machen müssen. Hoffentlich wird DataMapper :: EmbeddedValue irgendwann verfügbar sein, um Ihren Vorschlag zu vereinfachen. – Debilski