I am still learning Rails and the relationships are still a little
confusion. So I apologize in advance for the repetition of this
question.
I am building a user rating system for words and quotes. If I wanted a
user to be able to rate a word or quote only once, how can I set up
the ratings table so it will have the appropriate relationships. Since
the rating model is a bit polymorphic (rate words or quotes), I am not
sure if I need a “bridge table”. I want to be able to do things like
Any direction is greatly appreciated, and if you can throw in some
comments behind the code, even better. Also, would you suggest putting
the only one rating per user constraint in the db or as a
validate_unique…
To quickly answer your second question, you need both. The reason for
that is that validates_uniqueness_of does not guarantee fully unique
column values, since it’s at the application level. The unique
constraint in the db schema can be viewed as a backup.
The unique
constraint in the db schema can be viewed as a backup.
I’ll answer your main question shortly.
A philosophical quibble: in my opinion, it is the unique constraint in
the DB that should be considered primary. The validation in the
application layer is only there to prevent the DB from throwing
duplicate key errors. Application-level validation cannot replace a
properly constructed database schema.
I’ll get off my soapbox now…I just want to make it clear that the
database layer is the only place where it is possible to have airtight
integrity checking.
I am building a user rating system for words and quotes. If I wanted a
user to be able to rate a word or quote only once, how can I set up
the ratings table so it will have the appropriate relationships. Since
the rating model is a bit polymorphic (rate words or quotes), I am not
sure if I need a “bridge table”.
A bridge table has to do with many-to-many relationships, not
polymorphic relationships, unless I’m misunderstanding.
You should probably have a model called Rating which is the many side
of one-to-many with the User model. The Rating model should be
polymorphic so that you can use it to rate both Word and Quote
objects.
So, it would most likely look like this:
class User
:has_many => :ratings
end
class Rating
:belongs_to => :user
:belongs_to => :rated, :polymorphic => true
end
class Word
:has_one :rating, :as => :rated
end
class Quote
:has_one :rating, :as => :rated
end
The ratings table needs to have rated_id (integer) and rated_owner
(string) as columns in order to support the polymorphic behaviour.
What this will give you is a collection of ratings for a user (the
logic of adding this is something you need to figure out), and each
Rating instance will have a property called rated. That will reach
in and grab either the Quote or the Word being rated. The score, or
however you’re rating them, needs to be in the Rating model.
Let me know if you need more clarification.
On Apr 16, 1:08 am, Marnen Laibow-Koser <rails-mailing-l…@andreas-
On second thought, you’re absolutely right. I don’t know what the heck
I was thinking.
You should probably have a model called Rating which is the many side
of one-to-many with the User model. The Rating model should be
polymorphic so that you can use it to rate both Word and Quote
objects.
[…]
Yeah, this is what I was trying for. I just introduced STI in an
inappropriate place.
Note, though, that not using STI makes foreign-key validation somewhat
harder.
So, it would most likely look like this:
class User
:has_many => :ratings
end
class Rating
:belongs_to => :user
:belongs_to => :rated, :polymorphic => true
end
You should probably have a model called Rating which is the many side
of one-to-many with the User model. The Rating model should be
polymorphic so that you can use it to rate both Word and Quote
objects.
So, it would most likely look like this:
class User
:has_many => :ratings
end
class Rating
:belongs_to => :user
:belongs_to => :rated, :polymorphic => true
end
class Word
:has_one :rating, :as => :rated
end
class Quote
:has_one :rating, :as => :rated
end
The ratings table needs to have rated_id (integer) and rated_owner
(string) as columns in order to support the polymorphic behaviour.
What this will give you is a collection of ratings for a user (the
logic of adding this is something you need to figure out), and each
Rating instance will have a property called rated. That will reach
in and grab either the Quote or the Word being rated. The score, or
however you’re rating them, needs to be in the Rating model.
Let me know if you need more clarification.
On Apr 16, 1:08 am, Marnen Laibow-Koser <rails-mailing-l…@andreas-