So I have a social-bookmarking-esque setup here. 4 tables: posts, users, comments, and votes. The homepage simply points to the posts model’s index page and runs a loop over the Post.all array and displays some basic info: title, upvotes – downvotes (I call ti the post’s “score”).
Now what I need to do it order these posts in (i’m guessing) the model by their score divided by their relative creation time (how many seconds since page load was this post created?). Rails gives me a created_at column in my posts object and I have a table of votes which looks like this:
Posts model
class Post < ActiveRecord::Base
attr_accessible :id, :title, :url, :user_id, :comment_count, :agreement
has_many :votes
has_many :comments
belongs_to :user
end
Votes model
class Vote < ActiveRecord::Base
attr_accessible :direction, :post_id, :vote_type, :user_id
belongs_to :user
belongs_to :post
belongs_to :comment
end
IDs in the post model correspond with post_id’s in the vote model.
:direction is a boolean. 0 associated with up voting and 1 associated with downvoting. Post_ID is the ID of the post the vote was cast on.
How should I order the posts so that their position on the homepage is determined by both their creation time AND their up votes – down votes?
def index
@posts = Post.join(:votes).order(<???>)
end
ETA: @shweta is on the right track with joining the posts and votes tables. The select portion of his answer does not work, however.
Disclaimer: I don’t know ruby or rails, only SQL.
shweta’s answer seems really close so I will attempt to finish it with some SQL hack and slash:
order by upvotes and then created_at
Also, to include posts with zero votes you will need to do a left join:
Update: to fix the ordering for un-voted posts:
Update 2: improved ranking
If you exclude older items you might end up with an empty list (eg on quiet days), which is probably not what you want. You might be better off adding another column for ranking, something like this:
For ranking purposes, this triples the score of posts less than 2 hours old.