views:

63

answers:

2

Right now I'm building a social media app, where i want an user to have a rating per category, how would the association go? The way it needs to be setup it's Each user will have a different rating in each category.

I'm think that

belongs_to :user
belongs_to :category

in the UserCategoryRating model.

and

has_many :user_category_ratings, through => :category

on the User model, Is this the correct approach?

The UserCategoryRating table has the User_id column, Category_id column, and the rating column, that updates each time an user gets votes (The rating it's just the AVG between votes and the score based on 1-5)

+1  A: 

I will use the following data model:

class User
  has_many :user_categories
  has_many :categories, :through => :user_categories
end

class UserCategory
  belongs_to :user
  belongs_to :category
  # this model stores the average score also.
end

class Category
  has_many :user_categories
  has_many :users, :through => :user_categories
end

Now when you want to update the score of a user for a category

uc = u.user_categories.find_by_category_id(id)
uc.score = score
uc.save
KandadaBoggu
I don't think that's what I'm looking for, Users don't need to have categories, Articles need to have categories and i already got that working. What i need is a Score/Rating for Each User in Each Category.
Gotjosh
I have updated my answer. I am quite sure you will be able to store the score for a user and category combination using the suggested models.
KandadaBoggu
I'm trying this solution and it doesn't seems to be working on my rails console, I've created an UserCategory object, then retrived a category from the DB, followed by an User, and try attaching them to the UC object and it's not working.
Gotjosh
nvm, i got it working :)
Gotjosh
This reponse was also nice! But the other one it's nice :)
Gotjosh
+2  A: 

UPDATE: If I'm understanding you correctly, here is a diagram of the simple design you'd like:

UML Diagram

And this would be the basic skeleton of your classes:

class User < ActiveRecord::Base
   has_many :ratings
   # has_many :categories, :through => :ratings
end

class Category < ActiveRecord::Base
   has_many :ratings
   # has_many :users, :through => :ratings
end

class Rating < ActiveRecord::Base
    belongs_to :user
    belongs_to :category
    validates_uniqueness_of :user_id, :scope => [:category_id]
end

Will allow for these query:

@category_ratings_by_user = Rating.where("ratings.user_id = ? AND ratings.category_id = ?", user_id, category_id)
@specific_rating = user.ratings.where("ratings.category_id = ?", category_id)
# make nice model methods, you know the deal

# ... if you added the has_many :through,
@john = User.find_by_name("john")
# Two ways to collect all categories that john's ratings belong to:
@johns_categories_1 = @john.ratings.collect { |rating| rating.category }
@johns_categories_2 = @john.categories

@categories_john_likes = @john.categories.where("categories.rating >= ?", 7)

I'm just unsure as to why you want this has_many, :through (this doesn't seem like a many to many -- a rating only belongs to one user, correct?).

tjko
Yes, a rating only belongs to one user, but an user can have multiple ratings (One per Category), so wouldn't be a many to many relationship?
Gotjosh
Even tho the other solution worked, your seems a lot cleaner, I'm interested in hearing back from you :D
Gotjosh
@Gotjosh, I'm not sure I perfectly understood your question then... are the multiple ratings that one user has for one category distinguishable aside from their ~'score' value? I assumed they were of different types, which is why I added the `:type_of_rating` field and added a scoped uniqueness validator. Otherwise, if the ratings aren't really distinguishable from each other, you could just remove that line and make a validator that allows user_ratings to not need to be unique. Do you understand what I'm trying to say?
tjko
tjko, Thanks a lot for taking the time to answer my questions. The answer to your first question it's no. One user will have many ratings but only ONE rating per category. Meaning that what i need to be unique it's the User_id/Category_id combo (Which it's what I'm guessing that the validate line it's doing). I didn't fully understand what you were trying to say on the second sentence, but perhaps this comment can help you understand what I'm trying to do here. Again, One user will only have one rating per category, Meaning that if i have 3 categories, The user will have 3 ratings.
Gotjosh
Okay, well in that case, if I edit my answer on the `validates_uniqueness_of` line to be `user_id` scoped with `category_id`, it will cause Ratings to be uniquely valid between user_id and category_id like you want. But still, there is no need for `has_many :through` here... You should diagram your models to see this (I will update my answer in a minute).
tjko
Thanks a lot tjko, i see i thought there was a need for that! I haven't really added the relationships to the models, that's why i went in here first, in order to get the correct approach.
Gotjosh
The reason you'd want `has_many :through` is if you wanted the `User` s and `Category` s to have some sort of ownership of each other -- in this case they don't. While they both have a 1-* relationship to `Rating` s, that relationship is fully maintained by `Rating` s' two foreign keys to those models in the database and some nice Rails' methods. Now, you could want to go `:through` the `Rating` model, but it also doesn't seem necessary with your requirements (if you wanted to do `User.find(1).categories` -- to get all categories a user voted on).
tjko
Thanks a lot for all your help! One last question though, Later on i might want to get all the categories an user has voted one, where do i add the :through method to get this nice method?
Gotjosh
I will update my answer, let me know if you still have questions. PS: Have you tried this out? Are you getting what you were expecting?
tjko
THANK YOU SO MUCH! I haven't coded it yet, but i will once i get home and try it out! (Tonight) But this looks REALLY REALLY nice, and it's exactly what i needed, because I do know that at some point I'll need to collect all the ratings on all the categories, from all the users! I really appreciate your help.
Gotjosh
Yeah, no problem. I hope it works out for you, if not, I'm happy to follow this up, just let me know.
tjko