如何在模型中定义信誉系统值

时间:2012-09-23 16:40:49

标签: ruby-on-rails voting

如何在我的博客应用程序中设置default_scope,以便索引按照模型中定义的算法对条目进行排序?

如果我使用HackerNews-like formula作为排名算法,如下所示,我该如何在我的模型中定义它?

total_score = (votes_gained - 1) / (age_in_hours + 2)^1.5

voting_gained变量依赖于Active_Record_Reputation_System,并在我的视图中写成如下:

votes_gained = @post.reputation_value_for(:votes).to_i

最后,age_in_hours非常简单

age_in_hours = (Time.now - @post.created_at)/1.hour

如何使用这些数字来订购我的博客文章索引?我一直在试图弄清楚如何在模型中正确定义total_score,以便我可以将其作为default_scope order("total_score DESC")或类似的东西添加到默认范围中。直接替换没有奏效,我不确定如何“重新措辞”公式的每个部分。

我应该如何定义total_score?非常感谢您的见解!

1 个答案:

答案 0 :(得分:1)

看到如何不依赖活动记录将公式转换为SQL,您必须自己编写。这里唯一可能的问题是,这不是一个独立于数据库的解决方案。

由于你使用的是Postgres,你可以将你的范围定义为(我还没有测试过,所以让我知道它是否有效):

AGE_IN_HOURS = "(#{Time.now.tv_sec} - EXTRACT (EPOCH FROM posts.created_at))/3600"
TOTAL_SCORE = "(rs_reputations.value - 1)/((#{AGE_IN_HOURS}) + 2)^1.5"

default_scope joins("INNER JOIN rs_reputations ON rs_reputations.target_id = posts.id").where("rs_reputations.target_type = 'Post'").order(TOTAL_SCORE)

编辑:实际上这不起作用,因为,就目前而言,Time.now计算一次(当模型加载时),但每次拉动记录时都需要重新计算。使用

default_scope lambda { order_by_score }

def self.order_by_score

    age_in_hours = "(#{Time.now.tv_sec} - EXTRACT (EPOCH FROM posts.created_at))/3600"
    total_score = "(rs_reputations.value - 1)/((#{age_in_hours}) + 2)^1.5"

    joins("INNER JOIN rs_reputations ON rs_reputations.target_id = posts.id").where("rs_reputations.target_type = 'Post'").order(TOTAL_SCORE)
end