Ruby Datamapper table inheritance with associations
I started learning Datamapper and what I liked about it was that I can write my models with real inheritance.
Now I wonder, if it is possible to be more advanced about this:
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
That code fails to create the :title
column for the 开发者_高级运维Talk
and obviously, the discriminator column is of little value here, because from a database view, there should be separate tables for both Talk
and Meeting
.
So, in the end, I want Talk
and Meeting
to share the same properties as defined in Event
but with possible additional properties and with a 0..1:n relation (A meeting can have several talks but there are talks without a meeting.) Is there a way to accomplish this without either repeating the column definitions and/or abandoning inheritance?
Edit
To give another example: The part that I like about the inheritance thing is, that general Event
s can be queried separately. So, when I want to know, if there is something at a certain :begin
date, I don’t need to look in two or more tables but could just query the Event
table. In a way, the following structure could fit my needs.
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
However, in order to use this, I would need to manually create an Event
every time, I want to create or edit a Talk
. That is, I can’t do talk.begin
or Talk.create(:begin => Time.now)
. Is there a way around this without patching all functions and merging the properties? I don’t want to be reminded of the underlying structure when using the model.
If you want to replicate the attributes of Event into Talk and Meeting then you could move it into a 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
This will give you different tables but means duplication is reduced.
精彩评论