Topic: Drying up model duplication by subclassing?

Hi,

I have an app that requires login authentication by 2 different types of users (Tutors and tutees) The models are not identical but they share a lot of common methods. My first thought was to have a parent model and create a subclass for each of the 2 types of user

class User < ActiveRecord::Base
# Lots of code to do authentication etc
end

class Tutor < User
# Code specific to tutor model
end

class Tutee < User
# Code specific to tutee model
end


This doesn't work as I anticipated. There needs to be a "users" table in the database and I don't want that, just tables for tutor and tutee.
Is this approach possible or do I need to resort to an include instead?

Iain

Last edited by soulflyer (2009-06-08 00:55:13)

Re: Drying up model duplication by subclassing?

abstract_class is what you are looking for to complete the puzzle wink

Re: Drying up model duplication by subclassing?

Either that or instead of having it as a subclass of user, make the User stuff a module and include it in both. I think that's a better idea than the abstract_class in this case.

module User
  ## Stuff in here for both models
end

class Tutor < ActiveRecord::Base
  include User
end

class Tutee < ActiveRecord::Base
  include User
end

Re: Drying up model duplication by subclassing?

Thanks for the pointers.
Using modules was getting a little untidy ( I have class methods as well as instance methods so that means including one file and extending another) so I'm going with the abstract_class method for now. It seems neater in this case.

Iain

Re: Drying up model duplication by subclassing?

Personally, I would go with the module approach.  Perhaps you're already up on this, but with some basic metaprogramming it doesn't have to be messy.  Check out this pattern:

module MyNiftyModule
 
  def self.included(base)
    base.send :include, InstanceMethods
    base.extend ClassMethods
  end
 
  module ClassMethods
   
    # def my_class_method
    #   
    # end
   
  end
 
  module InstanceMethods
   
    # def my_instance_method
    #   
    # end
   
  end
 
end

With this, you only need to include the module to get both class and instance methods.  I guess I'm also a little fond of this approach because there is just something kind of Railsy about it.  It seems like a good portion of Rails plugins I've checked out follow this pattern.