logo{ :from => Delhi, :about => everything }


Polymorphic Association in Rails

Posted in ruby on rails, rails by manik on the June 15th, 2006


Here is an account of my first use of Rails 1.1’s polymorphism in Model associations.

I had looked at all the examples at the wiki and a couple of other blogs but still wasn’t clear.

You appreciate most, the problems that you solve yourselves :-)

Here is the problem I solved using Polymorphic associations.

Consider the scenario where there are Users of an application; who can act as both buyers and providers. Each user can infact have multiple buyer and provider profiles.
The application also has a messaging system for users to contact each other.
As a part of the application requirement, we need to keep track of the profiles of the message sender and receiver.

A user logs in using the login name and password present in the User model. I am omitting details so please assume for this example that each logged in user, has either a buyer profile or a provider profile associated to it, when they use the messaging system.

Here are the model files

A user can have many buyer_profiles and many provider_profiles

class User < ActiveRecord::Base
  has_many :buyer_profiles
  has_many :provider_profiles
end

A buyer profile belongs to a user and can have many messages associated to it as a sender and as a receiver.

class BuyerProfile < ActiveRecord::Base
  belongs_to :user
  has_many :messages, :as => :sender
  has_many :messages, :as => :receiver
end

A provider profile also belongs to a user, and can have many messages associated to it as a sender and as a receiver.

class ProviderProfile < ActiveRecord::Base
  belongs_to :user
  has_many :messages, :as => :sender
  has_many :messages, :as => :receiver
end

The message model holds the polymorphic magic, via the two interfaces sender and receiver. A message belongs to sender which can be polymorphic,either a buyer or a provider. And also a message belongs to a receiver, which again is polymorphic, either a provider or a buyer.

class Message < ActiveRecord::Base
  belongs_to :sender, :polymorphic => true
  belongs_to :receiver, :polymorphic => true
end

The code above requires that I have these four special fields in my messages table to handle polymorphism. Here is the migration for messages

class CreateMessagesTable < ActiveRecord::Migration
  def self.up
    create_table :messages do |t|
      t.column :sender_id, :integer
      t.column :sender_type, :string
      t.column :receiver_id, :integer
      t.column :receiver_type, :string
      t.column :subject, :string
      t.column :message, :string
    end
  end

  def self.down
    drop_table :messages
  end
end

I ran the following code on the console to check if everything is working as expected.

r = BuyerProfile.find(1)
s = ProviderProfile.find(1)
m = Message.new
m.sender = s
m.receiver = r
m.subject = "test subject"
m.message = "test message"
m.save!

And it worked :-)

I could access profles and users from the message object like this.

m = Message.find(1)
m.receiver                 # refer to the receivers profile object
m.receiver.class          # get receiver type, where BuyerProfile or SellerProfile
m.sender                   # refers to the sender profile object
m.sender.class            # get sender type, where BuyerProfile or SellerProfile
m.receiver.user           # refer the User object of the message receiver
m.sender.user             # refer the User object of the message sender

Polymorphism saved me a lot of time and also a whole new table which I was thinking of adding to handle this functionality prior to polymorphism.

Added : And yes, now I am thinking about what I would need to write to get all the messages sent or received by a User.

Tags: , ,

`

5 Responses to 'Polymorphic Association in Rails'

Subscribe to comments with RSS or TrackBack to 'Polymorphic Association in Rails'.


  1. on September 13th, 2006 at 8:22 pm

    Hi Manik, this is very informative post and cleared couple of doubts I had.

  2. LVR said,

    on October 14th, 2006 at 11:14 pm

    >> Added : And yes, now I am thinking about what I would need to write to get all the messages sent or received by a User.

    Hi, have you already found out how to do this?

  3. Tal said,

    on February 13th, 2007 at 8:54 am

    Thanks for this great post Manik! I’m going to try and run with it and see what happens.

    Tal

  4. Chris said,

    on April 11th, 2007 at 5:05 am

    Incredibly helpful. Thanks for taking the time to write this up - it took all of five minutes to get this sort of thing working in my project. Much appreciated.

  5. manik said,

    on August 7th, 2008 at 3:48 pm

    Checking spam

Leave a Reply