Если вы используете MySQL, вы можете сделать все это с помощью запроса:
SELECT posts.id,
(COUNT(votes.id)/(TIME_TO_SEC(NOW()) - TIME_TO_SEC(posts.created_at))) as score
FROM posts INNER JOIN votes ON votes.post_id = posts.id
GROUP BY posts.id
ORDER BY score DESC
Или:
class Post
scope :with_score, select('posts.*')
.select('(COUNT(votes.id)/(TIME_TO_SEC(NOW()) - TIME_TO_SEC(posts.created_at))) as score')
.joins(:votes)
.group('posts.id')
.order('score DESC')
end
Что сделает весь ваш запрос:
@posts = Post.with_score.all
P.S .: Затем вы можете изменить свой класс Post, чтобы использовать версию счета SQL, если она присутствует. Вы также можете сделать функцию оценки кэшированной в экземпляре, чтобы вам не приходилось пересчитывать ее каждый раз, когда вы запрашиваете оценку сообщения:
class Post
def score
@score ||= self[:score] || (votes.count/(Time.now.utc - x.created_at.utc)
end
end
P.S .: Эквивалент SQLLite3:
strftime('%s','now') - strftime('%s',posts.created_at)