Question

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?

Was it helpful?

Solution

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top