Phil Mok
Phil Mok

Reputation: 4050

Rails 4 Sort Users by Rating Parameter

In the app I am building, users answer poll questions. Users have these two parametes:

correct_count
incorrect_count 

When a user answers a question correctly, he/she gets +1 added to their correct_count. When a user answers incorrectly, he/she gets +1 added to their incorrect_count.

I use these two parameters to calculate the user's rating with the following equation:

(((user.correct_count / (user.correct_count + user.incorrect_count))**2)
  *(user.correct_count))

I want to sort the users from highest rating to lowest rating on a leaderboard page. I've added a column to my user called 'rating' and added it to my user_params.

def user_params
  params.require(:user).permit(:name, :email, :password,
                               :password_confirmation, :correct_count,
                               :incorrect_count, :rating)

In my User model I've added:

def rating
  if user.correct_count == 0
    user.rating = 0.0
  else
    user.rating = (((user.correct_count.to_f / (user.correct_count.to_f + 
      user.incorrect_count.to_f))**2)*(user.correct_count.to_f)).round(2)
    end
end 

and

scope :highest_rating, -> {order("rating DESC")}

In my Users Controller I have:

def index
  @users = User.highest_rating.paginate(page: params[:page])
end

So far, this is not working. What am I missing?

Upvotes: 1

Views: 58

Answers (1)

aash
aash

Reputation: 1323

Your solution is not working because you are not storing the rating in the User table in the database. If you store the users rating before saving it, then your defined scope will work as expected.

First, you need to generate and run the migration adding a column 'rating' in the users table.

Next, In User model:

before_save do
  if self.correct_count == 0
    self.rating = 0.0
  else
    self.rating = (((self.correct_count.to_f / (self.correct_count.to_f + 
      self.incorrect_count.to_f))**2)*(self.correct_count.to_f)).round(2)
   end
end

Now, you need to run save on all users so that you can populate their rating in the users table

User.all.each {|u| u.save}

Now, when you execute User.highest_rating, you should be getting the users sorted by their ratings.

Upvotes: 1

Related Questions