I am creating a rails app that has a User and Post model that implements the Act_As_Votable gem.
I want users to be able to upvote and downvote posts, but also want to rank and sort posts by a weighted_score algorithm that takes into account the number of upvotes, downvotes, and time the post was created.
My weighted_score algorithm is taken from Reddit and better described here.
My Post Model:
class Post < ActiveRecord::Base
belongs_to :user
acts_as_votable
# Raw scores are = upvotes - downvotes
def raw_score
return self.upvotes.size - self.downvotes.size
end
def weighted_score
raw_score = self.raw_score
order = Math.log([raw_score.abs, 1].max, 10)
if raw_score > 0
sign = 1
elsif raw_score < 0
sign = -1
else
sign = 0
end
seconds = self.created_at.to_i - 1134028003
return ((order + sign * seconds / 45000)*7).ceil / 7.0
end
end
I want to use the Acts_As_Voteable gem because it supports caching which may decrease the number of hard disk writes and save time. Currently the weight_score of a post can be calculated on the fly but is not saved in the database, meaning I cannot do database sorts on posts with the highest weighted_score.
If I created a column in the post model I would have to update the posts table every time a user voted on a post, which defeats the purpose of using the Acts_As_Tagable gem (as I don't take advantage of its caching ability).
So I want to add a column to the votes table to store the weighted_score (which will then be calculated every time the post is voted on), as well as a method to the Votes model to calculate this score, however the gem does not provide a model when I run its generator. It only creates a votes table which I do not know how to access without a model.
Any help on how I can add such a weighted_score column and method to the votes model, or on how to achieve efficiently storing the weighted score of a post in a different manner is appreciated.
acts_as_voteable adds methods to your model to access the votes http://juixe.com/techknow/index.php/2006/06/24/acts-as-voteable-rails-plugin/
positiveVoteCount = post.votes_for
negativeVoteCount = post.votes_against
totalVoteCount = post.votes_count
If you want to add a column, you can run a migration as normal on the table it creates. It also does appear to create a Vote model http://juixe.com/svn/acts_as_voteable/lib/vote.rb
I would add the weighted_score column to your Post model and handle updating via callback. For instance:
class Post < ActiveRecord::Base
#...
before_save :update_weighted_score
#...
def update_weighted_score
# check if some relevant variables have changed first, for example
if cached_votes_total.changed?
# do maths
weighted_score = blah
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With