Reputation: 1005
I got the following use-case:
I got three types of Users
: Advertisers
, Publishers
and Administrators
. Each user has some common properties (like name or surname) but also several unique associations. The advertiser has an association with Ad
(verttisement)s and Campaigns
. Each of with is another model of its own.
My question is how would I go about and model that using ActiveRecord
s? What would the migration code look like?
Here are the model classes:
User:
class User < ActiveRecord :: Base
require 'pbkdf2'
require 'date'
has_many :messages
attribute :name, :surname, :email, :password_hash, :password_salt
attr_accessor :password, :password_confirmation, :type
attribute :user_since, :default => lambda{ Date.today.to_s }
[...]
end
Publisher:
class Publisher < User
has_many :websites
end
Advertiser:
class Advertiser < User
has_many :campaigns
has_many :ads
end
I got the following migration file to create the User
:
class AddUser < ActiveRecord::Migration
def up
create_table :users do |t|
t.string :name
t.string :surname
t.string :email
t.string :password_hash
t.string :password_salt
t.date :user_since
t.string :type
end
create_table :messages do |t|
t.belongs_to :user
t.string :account_number
t.timestamps
end
end
def down
drop_table :user
end
end
How do I modify this file in order to incorporate the aforementioned associations?
Edit: Corrected the associations to use plural form.
Upvotes: 0
Views: 121
Reputation: 35533
Polymorphic relationships is one way to solve this, while another way would be to use Single Table Inheritance (STI). Each approach has its benefits and drawbacks, and your decision would probably depend in how different the subclasses of User
would tend to be. The more drastically they would differ, the more the decision would tend toward polymorphic relationships.
Using STI approach:
# a single :users table
# one table for each of the other (non-user) models
class User < ActiveRecord::Base
has_many :messages
end
class Publisher < User
has_many :websites
end
class Advertiser < User
# if :campaign supports multiple user-types (polymorphic)
has_many :campaigns, :as => :user
# otherwise
has_many :campaigns
has_many :ads
end
class Message < ActiveRecord::Base
belongs_to :user
end
class Campaign < ActiveRecord::Base
# if multiple user-types will have campaigns
belongs_to :user # referential column should be :user_id
# otherwise
belongs_to :advertiser # referential column should be :advertiser_id
end
Using Polymorphic approach:
# there should be no :users table, as User will be an abstract model class
# instead make a table for each of all the other models
class User < ActiveRecord::Base
self.abstract_class = true
has_many :messages, :as => :messageable
end
class Publisher < User
has_many :websites
end
class Advertiser < User
has_many :campaigns
has_many :ads
end
class Message < ActiveRecord::Base
belongs_to :messageable, polymorphic: true # referential columns should be :messageable_id and :messageable_type
end
class Campaign < ActiveRecord::Base
# if multiple user-types will have campaigns
belongs_to :user, polymorphic: true # referential columns should be :user_id and :user_type
# otherwise
belongs_to :advertiser # referential column should be :advertiser_id
end
Upvotes: 1