0

ブログアプリケーションでdefault_scopeを設定して、インデックスがモデルで定義されたアルゴリズムによってエントリを並べ替えるにはどうすればよいですか?

以下に示すように、ランキングアルゴリズムにHackerNewsのような式を使用する場合、モデルでどのように定義できますか?

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

votes_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か?あなたの洞察に感謝します!

4

1 に答える 1

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は(モデルがロードされるときに)1回計算されるため、これは機能しませんが、レコードがプルされるたびに再計算する必要があります。使用する

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
于 2012-09-23T20:22:30.843 に答える