inheriting models in rails
I have 2 similar models:
liked_image_user
loved_image_user
I have put the common methods in a module Rating.rb, that I include in each class methods are:
update_score
notify
notify is accessing
self.image
self.user
member of liked_image_user/loved_image_user
I have 2 problems:
- Is that the right design? It seems to me that I am doing an ugly side-effect, considering Rating as the base-class, but it's actually only a module
- I am writing 开发者_JAVA百科 rating_test.rb right now, and have problem testing notify because self.image refers to the fixture and not the member of the class, is there a way I can ignore the fixture and override self.image?
Using inheritance with model classes is how Rails does STI, so that would likely not do what you expect.
This is probably becoming a mess because you have the relationships set up wrong. I think this is a more appropriate case for a has_many :through
relation.
class User < ActiveRecord::Base
has_many :ratings
has_many :images, :through => :ratings do
def liked
where(:ratings => { :like => true })
end
def loved
where(:ratings => { :love => true })
end
end
end
class Rating < ActiveRecord::Base
belongs_to :user
belongs_to :image
attr_accessible :like, :love
validates_with RatingValidator
end
class Image < ActiveRecord::Base
has_many :ratings
has_many :users, :through => :ratings
end
class RatingValidator < ActiveModel::Validator
def validate(record)
record.errors[:base] << "only one rating per image is allowed" unless record[:like] ^ record[:love]
end
end
With a little validation and a couple simple scopes, you can get the liked/loved images of any user with user.images.liked
or user.images.loved
.
This might be cleaner if you combined the two ratings into a string column and created scopes for the rating type; that depends on how your application is going to work exactly.
精彩评论