开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜