Calculating total karma for a user
What would be the best way to calculate the total number of votes a user has received? (ie: tally all votes from posts a user created).
Would the best approach be to create a counter that increments everytime a vote is cast? Or is there a built in method that can tally the total?
To sum all votes for posts for a particular user:
User.find(...).posts.map(&:votes_for).sum
To sum all votes for subtracted from votes against for a particular user,
who created posts: User.find(...).posts.map(&:plusminus).sum
If you're doing this often, it would be worthwhile to denormalize this to the User model.
Thanks, that was exactly what I was looking for. I tried to search online for what you mean by denormalize this to the User model. Would you mind explaining or adding an example?
Do you mean create a method in the model like:
def get_karma
return self.posts.map(&:votes_for).sum
end
By denormalize, I mean you can store the computed value on the User model (if you have lots of posts, would be useful, but not necessary - just for performance reasons).
By the way, you should generally name your methods with adjectives/nouns,
not verbs/adverbs, in Ruby convention. A.k.a., not get_karma, but karma.
Something like:
class User
def votes_for_all_posts
# Create an integer field `votes_for_all_posts` on User, and make sure
Post has an index on `created_at`.
if posts.order('created_at ASC').first.created_at > created_at
v = posts.map(&:votes_for).sum
write_attribute(:votes_for_all_posts, v)
v
else
read_attribute(:votes_for_all_posts)
end
end
end