Modular Tables? DataMapper is Remixable.
One of my favorite things about Ruby is mixins. I love the pseudo multiple inheritance it provides. One thing that is frustrating to me though when working on developing back-ends is the amount of un-DRY code I am forced to create when working with the database.
For example, comments. Look at sites like MySpace, Facebook, and SocialGiant3.0 (sarcasm), everything is commentable. A user can comment on pictures, profiles, videos, and just about any other resource you can think of.
In this scenario you generally have one of two choices:
A.) You create a comments table for each of the resources: user_comments, profile_comments, etc.
B.) You create a giant comments table and horizontally partition it based on the comment_type.
I prefer the choice ‘A’, but the downfall, a very wet, anti-DRY set of models. This is were dm-is-remixable comes in. It gives you the ability to remix datamapper models into other models.
Whats that mean?
You write one model describing what a comment looks like and you mix it into User, Profile, etc; like magic, you’ve got a dry ‘comment’ model and a nice normalized table structure to store it in.
Here are some examples:
Create a remixable database model named Commentable
module Commentable
include DataMapper::Resource
is :remixable,
:suffix => "comment"
property :id, Integer, :key => true, :serial => true
property :comment, String
property :created_at, DateTime
end
Create a remixable image model and mix it into User
module Image
include DataMapper::Resource
is :remixable
property :id, Integer, :key => true, :serial => true
property :description, String
property :path, String
end
class User
include DataMapper::Resource
property :id, Integer,
:key => true,
:serial => true
property :first_name, String,
:nullable => false,
:length => 2..50
property :last_name, String,
:nullable => false,
:length => 2..50
remix n, :images, :as => "pics" #:as is optional and gives you an additional accessor
end
user = User.new
user.user_images
=>[] #Array of images
user.pics
=>[] #Array of images
Enhance the functionality of UserImages
class User
enhance :images do
def dimensions
# ... get the dimensions of the image
end
def resize(x,y)
# ... resize the image
end
end
end
user = User.first
user.pics.first.dimensions
=> "300x500"
user.pics.first.resize(100,300)
=> "100x300"
Remix commentables into Videos
class Video include DataMapper::Resource is :remixable property :id, Integer, :key => true, :serial => true property :description, String property :path, String remix n, :commentables, :as => "comments" # as is optional, provides add'l accessor name end video = Video.new video.comments =>[] # Array of comments video.video_comments =>[] # same array of comments
Remixing commentables into User;
class User # ... from declaration above ... # This is some of the more complex syntax # here we are remixing a module between two of the same class, so we need some sort of alias # :as => is the accessor method # :for => is the class that this class remixes the module with # :via => what we want to call the other user object remix n, :commentables, :as => "comments", :for => "User", :via => "commentor" end commentee = User.first commentor = User.get(2) comment = UserComment.new comment.comment = "Zomg! I talk non-stop, you are awesome!" comment.commentor = commentor commentee.comments << comment commentee.save
How do you get it? Well its in dm-more. If you dont know what DataMapper is, then git with the program.
From your favorite command line:
git clone git://github.com/sam/dm-more.git
Then from your source:
require ‘dm-is-remixable’
Tags: datamapper, dm-is-remixable, ruby

November 30th, 2008 at 7:22 am
Nice write up, thanks.
Quick question, can we define relationships in the remixable modules?
December 3rd, 2008 at 2:20 pm
Yeah, you can define relationships, but its kinda wonky. Since the remixable is actually a module, you have to ’send’ the relationship to the class that is remixing the module via the ‘extended’ method.
module MyRemixable
def self.extended(klass)
klass.send :has, n, :yada_yadas
end
end
October 10th, 2009 at 6:38 pm
And these new notes were not just plain bank notes. ,
August 17th, 2010 at 1:13 pm
WHAT LUCK! I I came across this site on google. this is really great stuff! I have added your site to my faves. I will be back!
September 14th, 2010 at 3:06 am
!!!..a different great article, I might count on practically nothing much less from you although :]
November 22nd, 2010 at 3:59 am
Decent reading. I like your web design also. Keep up your good work.
May 6th, 2011 at 9:13 pm
Yeah I need to agree with the guy a couple of feedback up. Indiscriminate advertising is for noobs!
June 28th, 2011 at 9:05 am
Really informative weblog right here. I could not make a much better 1 if my life depended on this.