2012-09-23 1 views
0

에서 평판 시스템 값을 정의?어떻게 알고리즘에 의해 인덱스 주문 항목이 모델에 정의 있도록 내 블로그 응용 프로그램에서 default_scope을 설정하는 방법 모델

아래 그림과 같이 내가 순위 알고리즘에 대한 HackerNews-like formula를 사용한다면, 어떻게 내 모델에서 정의 할 수 있습니다?

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 

입니다 이 수치는 내 블로그 게시물 색인을 주문 하시겠습니까? 나는 default_scope order("total_score DESC") 또는 유사한 무언가로 기본 범위에 추가 할 수 있도록 모델에 제대로 total_score을 정의하는 방법을 알아 내기 위해 노력했습니다. 직접 치환은 효과가 없었으므로 공식의 각 부분을 "바꾸는"방법을 잘 모르겠습니다.

나는 total_score을 정확히 어떻게 정의해야 하는가? 통찰력을 가져 주셔서 감사합니다.

+1

를 사용 : 투표) '를 선택하십시오. SQL은 루비를 호출하여 함수를 평가할 수 없습니다. 이 수식에는 SQL에서 열 수있는 값이나 그 값이 포함 된 간단한 수학 식 또는 심지어 루비에서 전달하거나 SQL NOW를 사용하여 얻을 수있는 현재 시간과 같이 SQL이 스스로 알아낼 수있는 용어 만 포함될 수 있습니다. – cdesrosiers

+0

감사합니다 @cdesrosiers. 그래서 솔루션은 내 Post 모델에'total_score' 컬럼을 생성하는 것이겠습니까? 그렇다면이 작업을 수행하는 쉬운 방법이 있습니까? – umezo

+1

'total_score' 자체는'age_in_hours'라는 연속적으로 변하는 매개 변수에 의존하기 때문에 저장할 수 없습니다. 저장할 필요가있는 것은'votes_gained'입니다. 누군가 투표 할 때 업데이트 만하면됩니다. 테이블에 투표 열이 있습니까? – cdesrosiers

답변

1

당신이 SQL로 공식 번역 활동 기록에 의존 할 수있는 방법으로보고, 당신은 그것을 직접 작성해야합니다. 유일한 잠재적 인 관심사는 이것이 데이터베이스 독립적 인 솔루션이 아니라는 것입니다. 당신이 포스트 그레스를 사용하고 있기 때문에

, 당신은 (내가 아직 테스트하지 않은, 그래서 내가 그것을 작동 여부를 알려주)로 범위를 정의 할 수 있습니다

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는 한 번 (모델이로드 될 때) 계산되지만 레코드를 가져올 때마다 다시 계산해야합니다. 내가 여기에 볼 수있는 주요 문제는 당신이 기록을 주문할 수 있도록 SQL에게 공식을 줄 필요가 있지만, 수식, 즉`reputation_value_for 루비 (에 의해 평가되어야 함수 호출이 포함되어 있다는 것입니다

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 
+0

작동하고있는 것 같습니다. 감사! 그러나 그것은 오름차순으로 정렬 된 것으로 보인다. 다른 방향으로 주문하려면 어떻게해야합니까? 방금'.order ("TOTAL_SCORE DESC")'로 변경하려고 시도했지만 작동하지 않습니다. 귀하의 성원에 진심으로 감사드립니다. – umezo

+0

수정 사항을 보지 못했습니다. 이것을 시도하겠습니다 ... – umezo

+0

"total_score"문자열의 끝에 "DESC"를 추가 할 수 있습니다 : "(rs_reputations.value - 1)/((# {age_in_hours}) + 2)^1.5 DESC". 모서리 케이스만으로 작동하는지 확인하기 위해 철저히 테스트해야합니다. – cdesrosiers

관련 문제