2013-05-08 2 views
0

사용자가 게임용 포인트를받는 앱이 있습니다. 내 코드에서 GameTRank 테이블의 지난 주 Game_Type을 사용하여 각 사용자의 점수를 소계하고 순위를 매기는 버그가 있습니다. 사용자가 지난 주 동안 포인트를 가지고 있다면 잘 작동하지만 지난 주 포인트가없는 사용자는 올바르게 작동하지 않습니다. 사용자가 점수가없는 경우 GameTypeRank에서 0 점으로 업데이트해야하며 그렇지 않은 경우 업데이트 할 때까지 마지막 순위를 유지합니다 (순위가 잘못됨).레일 : 레일 관련 버그 검색어 :

# user.rb: 
def self.update_game_type_weekly_rank 
    @game_types = GameType.all 
    @game_types.each do |game_type| 

    # this query is where the bug is since it is possible a User has no Points 
    @user_with_points = Point.where("game_type_id = ? and created_at >= ?", game_type.id, 1.week.ago).sum(:points, :group => :user_id, :order => 'sum(points) desc') 
    rank = point_counter = 0 

    @user_with_points.each do |user_id, points| 
     @game_type_rank = GameTypeRank.find_or_create_by_user_id_and_game_type_id(user_id, game_type.id) 
     if points != point_counter 
     point_counter = points 
     rank += 1 
     end 
     @game_type_rank.weekly_rank = rank 
     @game_type_rank.weekly_points = points 
     @game_type_rank.save 
    end 
    end 
end 

# Models 

# game_type_rank.rb 
# fields - user_id, game_type_id, weekly_points, weekly_rank 
belongs_to :game_type 
belongs_to :user 

# point.rb 
# fields - user_id, points, game_type_id 
belongs_to :game 
belongs_to :game_type 
belongs_to :user 
나는 매주 실행하고 주에 대한이 없었 각 사용자에 대한 (Point.points = 0) 포인트 레코드를 작성하지만 가난한 솔루션입니다 방법을 만들 수

.

또한 메서드 시작 부분에 각 GameTypeRank 레코드에 대해 weekly_pointsweekly_rank을 초기화 할 수는 있지만 이는 나에게 비효율적 인 것으로 보입니다.이 작업을 수행하는 가장 좋은 방법은 확실치 않습니다.

# Sample Data 
Points 
|user_id|points|game_type_id|created_at 
|1  | 10 |   1|2013-05-07 
|1  | 10 |   2|2013-05-07 
|2  | 20 |   2|2012-12-31 
|1  | 5 |   2|2012-12-31 

before weekly_update - Game_Type_Ranks 
|user_id |game_type_id | weekly_points | weekly_rank| 
|1  |2   |5    |2 
|2  |2   |20    |1 

after weekly_update - Game_Type_Ranks 
|user_id |game_type_id | weekly_points | weekly_rank| 
|1  |1   |10    |1 
|1  |2   |10    |1 
|2  |2   |20    |1 

what should happen after weekly_update - Game_Type_Ranks 
|user_id |game_type_id | weekly_points | weekly_rank| 
|1  |1   |10    |1 
|1  |2   |10    |1 
|2  |2   |0    |2 <== update for user_id 2 
+0

예상되는 실제 출력과 함께 일부 샘플 입력 데이터가 유용합니다. –

+0

몇 가지 샘플 데이터를 추가했습니다. 감사합니다. – yellowreign

+0

이번 주에 활동하지 않은 사용자에게는 주당 0 점이 필요합니까? 우리가 그들을 버릴 수 있을까요? – bennick

답변

0

주요 문제는 기존 순위를 가지고 있지만 주어진 GameType에 대한 @user_with_points에서 현재 주 동안 활성화되지 않은 사용자에 대한 액세스 권한이없는 것입니다.

그대로 두지 말고 updated_at 타임 스탬프를 사용하십시오. GameTypeRank 개체를 호출 할 때 지난 주에 업데이트 된 개체 만 가져옵니다.

# some controller 
GameTypeRank.where("id = ? and updated_at >= ?", id, 1.week.ago) 

그러나이하면 0

대안은과 같이, 시간에 관계없이 주어진 게임 타입에 대한 포인트가 모든 사용자 통해 루프되는 사용자 weekly_points 레이크 이전을 설정할 수있는 기능을 잃게 :

# user.rb: 
def self.update_game_type_weekly_rank 
    @game_types = GameType.all 
    @game_types.each do |game_type| 

    @user_with_points = Point.where("game_type_id = ?", game_type.id).sum(:points, :group => :user_id, :order => 'sum(points) desc') 
     rank = point_counter = 0 
     @user_with_points.each do |user_id, points| 
     @game_type_rank = GameTypeRank.find_or_create_by_user_id_and_game_type_id(user_id, game_type.id) 
     if points != point_counter 
      point_counter = points 
      rank += 1 
     end 
     @game_type_rank.weekly_rank = rank 
     @game_type_rank.weekly_points = points 
     @game_type_rank.save 
     end 
    end 

    end 
end 

이 다음에 원하는 방식으로 테이블을 만들어야합니다. 이제 당신은 아마 깨닫는 것처럼 비용이 들게됩니다. 어쩌면 당신은 비활성에서 어떤 종류의 차단을 할 수 있습니다. 예를 들어 6 개월이라고 말하십시오.

# users.rb 
.... 
@user_with_points = Point.where("game_type_id = ? and created_at >= ?", game_type.id, 6.months.ago).sum(:points, :group => :user_id, :order => 'sum(points) desc') 
.... 

# some controller 
GameTypeRank.where("id = ? and created_at >= ?", id, 6.months.ago) 

이 두 가지 방법 모두 비효율적이지만 작업이 완료됩니다. 게다가이 방법을 cron 작업 및/또는 백그라운드 작업으로 실행하고 있으므로 사용자에게 미치는 영향을 없앨 수 있습니다.

+0

답변 해 주셔서 감사합니다. 첫 번째 옵션에서 지적했듯이, 사용자가 이전 주에 포인트를 가졌던 GameTypeRank는 수정하지 않지만이 점수는 그렇지 않습니다. 두 번째 옵션의 문제는 일주일 동안 포인트가 없더라도 모든 사용자의 순위를 매기는 것입니다. GameTypeRank에는 실제로 rank 2, weekly_rank 및 monthly_rank (및 해당 지점 필드)가 있으므로 옵션 2에 대한 코드가 이미 작성되어 있습니다 (created_at 생략). 내 전반적인 순위, 점수 필드는 매월 또는 매주가 아닙니다. – yellowreign