-
Notifications
You must be signed in to change notification settings - Fork 8
Home
Welcome to the discussion on implementing polymorphism for DataMapper. Please comment, update, edit if you’d like to add stuff.
As an example, we’ll use the old blog articles with comments and tags. Comments is the basic case for polymorphism. Tags is the complex via through.
A table that implements polymorphism should have 2 additional fields to facilitate the polymorphism.
property :<interface_name>_class, Class #=> requires a custom Data type
property :<interface_name>_id, Integer
class Post
include DataMapper::Resource
has n, :comments, :via => :commentable
end
class Comment
include DataMapper::Resource
is :polymorphic, :commentable
end
Sets up the interface and attaches it to the class. The interface attaches the required two properties to the class class_id and id.
It also registers itself as an available polymorphic interface to the class.
Installs the Klass.commentables and Klass#commentable methods
This is where the real work is done. Currently the idea for polymorphism is to setup a belong_to association on the polymorphic side, and a has n on the owning side. The has with :as option would set these up on each class. In our comment example, when
has n, :comments, :as => :commentable
is called in the Post class these associations would be set up.
Post.has n, :comments, :child_key => [:commentable_id], :conditions => {:commentable_class => Post}
Comment.belongs_to :post, :child_key => [:commentable_id], :local_conditions => { :commentable_class => Post }
By implementing polymorphism using existing associations, a great deal of flexibility should result.
What goes here
What goes here
In addition to the Post class above.
#Reopen Post from before
class Post
has n, :taggings, :via => :taggable
has n, :tags => :taggings
end
class Tagging
include DataMapper::Resource
is :polymorphic, :taggable
belongs_to :tag
end
class Tag
include DataMapper::Resource
has n, :taggings
end
The basic polymorphic stuff is setup on on the Tagging model. Then tags are associated through taggings.
So in posts you can have post.tags and get all the tags assocaited with the post.
The tricky part is when going the other way. For example. How does loading work with something like this:
tag.taggings.each{|t| puts t.taggable }
Need a PolymorphicCollection that is a collection of collections.