Skip to content

Instantly share code, notes, and snippets.

@ryanchin
Last active December 14, 2015 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanchin/5096235 to your computer and use it in GitHub Desktop.
Save ryanchin/5096235 to your computer and use it in GitHub Desktop.
result of self.update_rank after changing game.total_points to points.total_points
def self.update_rank_by klass
rank_class = (klass.name + "Rank").constantize
rank_by_col = "#{klass.name.underscore}_id".to_sym
select_sql = "points.user_id, points.#{rank_by_col},
SUM(points.points) total_points"
rank = total_points = 0
Point.select(select_sql).group(:user_id, rank_by_col).
order("total_points DESC").find_in_batches do |points|
User.transaction do
points.each do |point|
ro = rank_class.send(
"find_or_initialize_by_user_id_and_#{rank_by_col}",
point.user_id, point.send(rank_by_col))
# calculate rank
if point.total_points > total_points
total_points = point.total_points
rank +=1
end
ro.total_points = point.total_points
ro.rank = rank
ro.save
end
end
end
end
Points:
points user_id game_type_id game_id
10 1 1 1
10 1 1 1
20 2 1 2
10 2 1 2
25 2 1 3
20 2 1 1
GameRanks:
user_id game_id total_points rank
1 1 20 1
2 2 30 2
2 3 25 2
2 1 20 2
Expected GameRanks:
user_id game_id total_points rank
1 1 20 1
2 2 30 1
2 3 25 1
2 1 20 1
Trace:
irb(main):001:0> User.update_rank
Scoped order and limit are ignored, it's forced to be batch order and batch size
Point Load (99.0ms) SELECT points.user_id, points.game_id,
SUM(points.points) total_points FROM `points` WHERE (`points`.`id` >= 0) GROUP BY user_id, game_id ORDER BY `points`.`id` ASC LIMIT 1000
(0.9ms) BEGIN
GameRank Load (0.7ms) SELECT `game_ranks`.* FROM `game_ranks` WHERE `game_ran ks`.`user_id` = 1 AND `game_ranks`.`game_id` = 1 LIMIT 1
SQL (0.8ms) INSERT INTO `game_ranks` (`created_at`, `rank`, `game_id`, `total _points`, `updated_at`, `user_id`) VALUES ('2013-03-06 02:22:16', 1, 1, 20, '201 3-03-06 02:22:16', 1)
GameRank Load (0.6ms) SELECT `game_ranks`.* FROM `game_ranks` WHERE `game_ran ks`.`user_id` = 2 AND `game_ranks`.`game_id` = 2 LIMIT 1
SQL (0.6ms) INSERT INTO `game_ranks` (`created_at`, `rank`, `game_id`, `total _points`, `updated_at`, `user_id`) VALUES ('2013-03-06 02:22:16', 2, 2, 30, '201 3-03-06 02:22:16', 2)
GameRank Load (0.5ms) SELECT `game_ranks`.* FROM `game_ranks` WHERE `game_ran ks`.`user_id` = 2 AND `game_ranks`.`game_id` = 3 LIMIT 1
SQL (0.5ms) INSERT INTO `game_ranks` (`created_at`, `rank`, `game_id`, `total _points`, `updated_at`, `user_id`) VALUES ('2013-03-06 02:22:16', 2, 3, 25, '201 3-03-06 02:22:16', 2)
TeamRank Load (0.5ms) SELECT `game_ranks`.* FROM `game_ranks` WHERE `game_ran ks`.`user_id` = 2 AND `game_ranks`.`game_id` = 1 LIMIT 1
SQL (0.5ms) INSERT INTO `game_ranks` (`created_at`, `rank`, `game_id`, `total _points`, `updated_at`, `user_id`) VALUES ('2013-03-06 02:22:16', 2, 1, 20, '201 3-03-06 02:22:16', 2)
(23.3ms) COMMIT
Scoped order and limit are ignored, it's forced to be batch order and batch size
Point Load (1.1ms) SELECT points.user_id, points.game_type_id,
SUM(points.points) total_points FROM `points` WHERE (`points`.`id` >= 0) GROUP BY user_id, game_type_id ORDER BY `points`.`id` ASC LIMIT 1000
(0.4ms) BEGIN
GameTypeRank Load (0.5ms) SELECT `game_type_ranks`.* FROM `game_type_ranks` W HERE `game_type_ranks`.`user_id` = 1 AND `game_type_ranks`.`game_type_id` = 1 LI MIT 1
SQL (0.6ms) INSERT INTO `game_type_ranks` (`created_at`, `game_type_id`, `ran k`, `total_points`, `updated_at`, `user_id`) VALUES ('2013-03-06 02:22:16', 1, 1 , 20, '2013-03-06 02:22:16', 1)
GameTypeRank Load (0.5ms) SELECT `game_type_ranks`.* FROM `game_type_ranks` W HERE `game_type_ranks`.`user_id` = 2 AND `game_type_ranks`.`game_type_id` = 1 LI MIT 1
SQL (0.5ms) INSERT INTO `game_type_ranks` (`created_at`, `game_type_id`, `ran k`, `total_points`, `updated_at`, `user_id`) VALUES ('2013-03-06 02:22:16', 1, 2 , 75, '2013-03-06 02:22:16', 2)
(7.4ms) COMMIT
=> nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment