如何在我的博客应用程序中设置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
?非常感谢您的见解!
答案 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