Active Record Relationship Design Patterns
In the world of web applications, eventually you’ve seen it all, and you start to see the same relational patterns occur over and over. To help out the newbies, here’s a list of various relationships (in Ruby on Rails syntax) that we see all the time.
Can you think of any more common relationship patterns?
Customer Relationship Management
class Company < ActiveRecord::Base
has_many :contacts
end
class Contact < ActiveRecord::Base
belongs_to :company
end
E-Commerce
class Category < ActiveRecord::Base
has_many :products
end
class Product < ActiveRecord::Base
belongs_to :category
end
class Order < ActiveRecord::Base
has_many :line_items
end
class LineItem < ActiveRecord::Base
belongs_to :product
belongs_to :order
end
Roles Based Access Control
class User < ActiveRecord::Base
has_and_belongs_to_many :roles
end
class Roles < ActiveRecord::Base
has_and_belongs_to_many :users
has_and_belongs_to_many :permissions
end
class Permission < ActiveRecord::Base
has_and_belongs_to_many :roles
end
Mailing Lists:
class MailingList < ActiveRecord::Base
has_many :subscribers
end
class Subscriber < ActiveRecord::Base
belongs_to :mailing_list
end
Surveys / Questionaires / Quizzes:
class Survey < ActiveRecord::Base
has_many :questions
has_many :responses
end
class Question < ActiveRecord::Base
belongs_to :survey
has_many :choices
end
class Choice < ActiveRecord::Base
belongs_to :question
end
class Response < ActiveRecord::Base
belongs_to :survey
has_many :response_choices
end
class ResponseChoice < ActiveRecord::Base
belongs_to :response
belongs_to :question
belongs_to :choice
end
Hierarchical Content Management:
class Page < ActiveRecord::Base
acts_as_tree
acts_as_list :scope => :parent
end
Blogs:
class BlogEntry < ActiveRecord::Base
has_many :comments, :dependent => true, :order => "created_at ASC"
end
class Comment < ActiveRecord::Base
belongs_to :blog_entry
end
Social Networking:
(from: wiki.rubyonrails.com)
class User < ActiveRecord::Base
has_and_belongs_to_many :users,
:join_table => 'users_known_users',
:foreign_key => 'known_user_id',
:association_foreign_key => 'user_id',
:after_add => :create_reverse_association,
:after_remove => :remove_reverse_association
def known_users
self.users
end
private
def create_reverse_association(associated_user)
associated_user.known_users << self unless associated_user.known_users.include?(self)
end
def remove_reverse_association(associated_user)
associated_user.known_users.delete(self) if associated_user.known_users.include?(self)
end
end
Any major ones I’m missing here?