views:

230

answers:

1

I have a couple of models in my system:

  • User Reputation
  • Post Reputation
  • Response Reputation

(similar to SO).

So, they are share some basic code:

  • Incrementing and decrementing values
  • a unique_id belonging to the three object that the reputation represents (User, Post, Response)

If there were C++, I would have a superclass called "Reputation" that would encapsulate these concepts.

Currently, I have three models, separately defined but as I build the system I'm starting to realize there is a lot of code duplication,etc.

If I were to use STI then I would have to a owner_id field which would be the object_id and a owner_type.

So, what's the best way of the handling this case?

+2  A: 

Will there be any unique code in any of the reputation models?

If not you can get by with a belongs_to :owner, :polymorphic => true in a generic Reputation model.

Otherwise you should be able to get by with providing the :class_name argument in the belongs_to calls in each of the submodels.

Code for single reputation model: (Reputation needs owner_id:integer and owner_type:string columns)

class Reputation < ActiveRecord::Base
  belongs_to :owner, :polymorphic => true
  ...
end

class User < ActiveRecord::Base
  has_one :reputation, :as => :owner
end

class Post < ActiveRecord::Base
  has_one :reputation, :as => :owner
end

class Response < ActiveRecord::Base
  has_one :reputation, :as => :owner
end

Subclassing Reputation (Reputation table needs owner_id:integer and type:string columns)

class Reputation < ActiveRecord::Base
  ...
end

class UserReputation < Reputation
  belongs_to :owner, :class_name => "User"
  ...
end

class PostReputation < Reputation
  belongs_to :owner, :class_name => "Post"
  ...
end

class ResponseReputation < Reputation
  belongs_to :owner, :class_name => "Response"
  ...
end


class User < ActiveRecord::Base
  has_one :user_reputation, :foreign_key => :owner_id
  ...
end

class Post < ActiveRecord::Base
  has_one :post_reputation, :foreign_key => :owner_id
  ...
end

class Response < ActiveRecord::Base
  has_one :response_reputation, :foreign_key => :owner_id
  ...
end
EmFi