Skip to content
hassox edited this page Sep 14, 2010 · 15 revisions

Welcome to the discussion on implementing polymorphism for DataMapper. Please comment, update, edit if you’d like to add stuff.

Example

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.

Schema

A table that implements polymorphism should have 2 additional fields to facilitate the polymorphism.

property :<interface_name>_class, Class  #=> requires a custom setu
property :<interface_name>_id,        Integer

API

class Post include DataMapper::Resource

has_polymorphic :comments, :via => :commentable

end

class Comment
include DataMapper::Resource

is_polymorphic :commentable

end

is_polymorphic

is_polymorphic(interface_name, opts)
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

has_polymorphic

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_polymorphic method would set these up on each class. In our comment example, when
has_polymorphic :comments, :via => :commentable
is called in the Post class these associations would be set up.
Post.has n, :comments, :child_key => [:commentable_id], :conditions => {:commentable_class => User}

Comment.belongs_to :post, :child_key => [:commentable_id], :local_conditions => { :commentable_class => User }

By implementing polymorphism using existing associations, a great deal of flexibility should result.

Comment.commentables

Comment#commentable

Through assocaitions

Example

In addition to the Post class above.

#Reopen Post from before
class Post
has_polymorphic :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.

Clone this wiki locally