How to model has_many with polymorphism?

Posted by Daniel Abrahamsson on Stack Overflow See other posts from Stack Overflow or by Daniel Abrahamsson
Published on 2010-06-02T10:15:28Z Indexed on 2010/06/02 10:44 UTC
Read the original article Hit count: 280

I've run into a situation that I am not quite sure how to model.

Suppose I have a User class, and a user has many services. However, these services are quite different, for example a MailService and a BackupService, so single table inheritance won't do. Instead, I am thinking of using polymorphic associations together with an abstract base class:

class User < ActiveRecord::Base
    has_many :services
end

class Service < ActiveRecord::Base
    validates_presence_of :user_id, :implementation_id, :implementation_type

    belongs_to :user
    belongs_to :implementation, :polymorphic = true
    delegate :common_service_method, :name, :to => :implementation
end

#Base class for service implementations
class ServiceImplementation < ActiveRecord::Base
    validates_presence_of :user_id, :on => :create 

    has_one :service, :as => :implementation
    has_one :user, :through => :service

    after_create :create_service_record

    #Tell Rails this class does not use a table.
    def self.abstract_class?
        true
    end

    #Default name implementation.
    def name
        self.class.name
    end

    protected

    #Sets up a service object
    def create_service_record
        service = Service.new(:user_id => user_id)
        service.implementation = self
        service.save!
    end
end

class MailService < ServiceImplementation
   #validations, etc...
   def common_service_method
     puts "MailService implementation of common service method"
   end
end

#Example usage
MailService.create(..., :user_id => user.id)
BackupService.create(...., :user_id => user.id)

user.services.each do |s|
    puts "#{user.name} is using #{s.name}"
end #Daniel is using MailService, Daniel is using BackupService

So, is this the best solution? Or even a good one? How have you solved this kind of problem?

© Stack Overflow or respective owner

Related posts about ruby-on-rails

Related posts about inheritance