Sören Titze
Sören Titze

Reputation: 1005

ActiveRecord Associations

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 ActiveRecords? 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

Answers (1)

PinnyM
PinnyM

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

Related Questions