Sorting by a virtual attribute in Rails 3

前端 未结 2 1724
醉话见心
醉话见心 2021-02-06 18:04

BACKGROUND: I have a set of Posts that can be voted on. I\'d like to sort Posts according to their \"vote score\" which is determined by the following equation:

2条回答
  •  感情败类
    2021-02-06 19:00

    If you are using MySQL you can do the entire thing using a query:

    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
    

    Or:

    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
    

    Which would make your entire query:

    @posts = Post.with_score.all
    

    P.S: You can then modify your Post class to use the SQL version of score if it is present. You can also make the score function cached in an instance so you don't have to re-calculate it every time you ask for a post's score:

    class Post
      def score
        @score ||= self[:score] || (votes.count/(Time.now.utc - x.created_at.utc)
      end
    end
    

    P.S: The SQLLite3 equivalent is:

    strftime('%s','now') - strftime('%s',posts.created_at)
    

提交回复
热议问题