leaderboard 2.5.0 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc CHANGED
@@ -1,3 +1,2 @@
1
1
  rvm --create 1.8.7@leaderboard_gem
2
- rvm --create 1.9.2@leaderboard_gem
3
2
  rvm --create 1.9.3@leaderboard_gem
data/CHANGELOG.markdown CHANGED
@@ -1,5 +1,12 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## leaderboard 3.0.0.rc1 (2012-11-08)
4
+
5
+ * Removes `:use_zero_index_for_rank_option` as valid option for requesting data from the leaderboard. [Original proposal](https://github.com/agoragames/leaderboard/pull/27)
6
+ * Optional member data is stored in a single hash. [Original proposal](https://github.com/agoragames/leaderboard/pull/26)
7
+ * Adds `:sort_by` as valid option for requesting data from the leaderboard. [Original proposal](https://github.com/agoragames/leaderboard/pull/30)
8
+ * Removes `:with_scores` and `:with_ranks` as valid options for requesting data from the leaderboard.
9
+
3
10
  ## leaderboard 2.5.0 (2012-10-12)
4
11
 
5
12
  * Added `members_from_rank_range` and `members_from_rank_range_in` methods to be able to retrieve members from a leaderboard in a given rank range.
data/README.markdown CHANGED
@@ -119,30 +119,34 @@ Get some information about your leaderboard:
119
119
  => 1
120
120
  ```
121
121
 
122
- The `rank_member` call will also accept an optional hash of member data that could
123
- be used to store other information about a given member in the leaderboard. This
124
- may be useful in situations where you are storing member IDs in the leaderboard and
125
- you want to be able to store a member name for display. Example:
122
+ The `rank_member` call will also accept an optional string member data that could
123
+ be used to store other information about a given member in the leaderboard. This
124
+ may be useful in situations where you are storing member IDs in the leaderboard and
125
+ you want to be able to store a member name for display. You could use JSON to
126
+ encode a Hash of member data. Example:
126
127
 
127
128
  ```ruby
128
- highscore_lb.rank_member('84849292', 1, {'username' => 'member_name'})
129
+ require 'json'
130
+ highscore_lb.rank_member('84849292', 1, JSON.generate({'username' => 'member_name'})
129
131
  ```
130
132
 
131
133
  You can retrieve, update and remove the optional member data using the
132
134
  `member_data_for`, `update_member_data` and `remove_member_data` calls. Example:
133
135
 
134
136
  ```ruby
135
- highscore_lb.member_data_for('84849292')
137
+ JSON.parse(highscore_lb.member_data_for('84849292'))
136
138
  => {"username"=>"member_name"}
137
139
 
138
- highscore_lb.update_member_data('84849292', {'last_updated' => Time.now, 'username' => 'updated_member_name'})
139
- => "OK"
140
- highscore_lb.member_data_for('84849292')
140
+ highscore_lb.update_member_data('84849292', JSON.generate({'last_updated' => Time.now, 'username' => 'updated_member_name'}))
141
+ => "OK"
142
+ JSON.parse(highscore_lb.member_data_for('84849292'))
141
143
  => {"username"=>"updated_member_name", "last_updated"=>"2012-06-09 09:11:06 -0400"}
142
144
 
143
145
  highscore_lb.remove_member_data('84849292')
144
146
  ```
145
147
 
148
+ If you delete the leaderboard, ALL of the member data is deleted as well.
149
+
146
150
  Get some information about a specific member(s) in the leaderboard:
147
151
 
148
152
  ```ruby
@@ -162,23 +166,10 @@ Get page 1 in the leaderboard:
162
166
  highscore_lb.leaders(1)
163
167
  => [{:member=>"member_10", :rank=>1, :score=>10.0}, {:member=>"member_9", :rank=>2, :score=>9.0}, {:member=>"member_8", :rank=>3, :score=>8.0}, {:member=>"member_7", :rank=>4, :score=>7.0}, {:member=>"member_6", :rank=>5, :score=>6.0}, {:member=>"member_5", :rank=>6, :score=>5.0}, {:member=>"member_4", :rank=>7, :score=>4.0}, {:member=>"member_3", :rank=>8, :score=>3.0}, {:member=>"member_2", :rank=>9, :score=>2.0}, {:member=>"member_1", :rank=>10, :score=>1.0}]
164
168
  ```
165
-
166
- You can pass various options to the calls `leaders`, `around_me` and `ranked_in_list`.
167
- Valid options are `:with_scores`, `:with_rank`, `:with_member_data`, `:use_zero_index_for_rank`
168
- and `:page_size`. Below is an example of retrieving the first page in the leaderboard
169
- without ranks:
170
-
171
- ```ruby
172
- highscore_lb.leaders(1, :with_rank => false)
173
- => [{:member=>"member_10", :score=>9.0}, {:member=>"member_9", :score=>7.0}, {:member=>"member_8", :score=>5.0}, {:member=>"member_7", :score=>3.0}, {:member=>"member_6", :score=>1.0}, {:member=>"member_5", :score=>0.0}, {:member=>"member_4", :score=>0.0}, {:member=>"member_3", :score=>0.0}, {:member=>"member_2", :score=>0.0}, {:member=>"member_1", :score=>0.0}]
174
- ```
175
-
176
- Below is an example of retrieving the first page in the leaderboard without scores or ranks:
177
-
178
- ```ruby
179
- highscore_lb.leaders(1, :with_scores => false, :with_rank => false)
180
- => [{:member=>"member_10"}, {:member=>"member_9"}, {:member=>"member_8"}, {:member=>"member_7"}, {:member=>"member_6"}, {:member=>"member_5"}, {:member=>"member_4"}, {:member=>"member_3"}, {:member=>"member_2"}, {:member=>"member_1"}]
181
- ```
169
+
170
+ You can pass various options to the calls `leaders`, `around_me` and `ranked_in_list`.
171
+ Valid options are `:with_member_data`, `:page_size` and `:sort_option`. Valid values for
172
+ `:sort_option` are `:none` (default), `:score` and `:rank`.
182
173
 
183
174
  You can also use the `members` and `members_in` methods as aliases for the `leaders` and `leaders_in` methods.
184
175
 
@@ -231,6 +222,20 @@ members = highscore_lb.members_from_rank_range(1, 5)
231
222
  => [{:member=>"member_95", :rank=>1, :score=>95.0}, {:member=>"member_94", :rank=>2, :score=>94.0}, {:member=>"member_93", :rank=>3, :score=>93.0}, {:member=>"member_92", :rank=>4, :score=>92.0}, {:member=>"member_91", :rank=>5, :score=>91.0}]
232
223
  ```
233
224
 
225
+ The option `:sort_option` is useful for retrieving an arbitrary list of
226
+ members from a given leaderboard where you would like the data sorted
227
+ when returned. The follow examples demonstrate its use:
228
+
229
+ ```ruby
230
+ friends = highscore_lb.ranked_in_list(['member_6', 'member_1', 'member_10'], :sort_by => :rank)
231
+ => [{:member=>"member_10", :rank=>47, :score=>10.0}, {:member=>"member_6", :rank=>51, :score=>6.0}, {:member=>"member_1", :rank=>56, :score=>1.0}]
232
+ ```
233
+
234
+ ```ruby
235
+ friends = highscore_lb.ranked_in_list(['member_6', 'member_1', 'member_10'], :sort_by => :score)
236
+ => [{:member=>"member_1", :rank=>56, :score=>1.0}, {:member=>"member_6", :rank=>51, :score=>6.0}, {:member=>"member_10", :rank=>47, :score=>10.0}]
237
+ ```
238
+
234
239
  ### Ranking multiple members in a leaderboard at once
235
240
 
236
241
  Insert multiple data items for members and their associated scores:
data/Rakefile CHANGED
@@ -10,6 +10,7 @@ end
10
10
 
11
11
  task :default => :spec
12
12
 
13
+ desc "Run the specs against Ruby 1.8.7 and 1.9.3"
13
14
  task :test_rubies do
14
- system "rvm 1.8.7@leaderboard_gem,1.9.2@leaderboard_gem,1.9.3@leaderboard_gem do rake spec"
15
+ system "rvm 1.8.7@leaderboard_gem,1.9.3@leaderboard_gem do rake spec"
15
16
  end
@@ -1,4 +1,4 @@
1
1
  class Leaderboard
2
2
  # Leaderboard version
3
- VERSION = '2.5.0'.freeze
3
+ VERSION = '3.0.0.rc1'.freeze
4
4
  end
data/lib/leaderboard.rb CHANGED
@@ -27,17 +27,13 @@ class Leaderboard
27
27
  }
28
28
 
29
29
  # Default options when requesting data from a leaderboard.
30
- # +:with_scores+ true: Return scores along with the member names.
31
- # +:with_rank+ true: Return ranks along with the member names.
32
30
  # +:with_member_data+ false: Return member data along with the member names.
33
- # +:use_zero_index_for_rank+ false: If you want to 0-index ranks.
34
31
  # +:page_size+ nil: The default page size will be used.
32
+ # +:sort_by+ :none: The default sort for a call to `ranked_in_list`.
35
33
  DEFAULT_LEADERBOARD_REQUEST_OPTIONS = {
36
- :with_scores => true,
37
- :with_rank => true,
38
34
  :with_member_data => false,
39
- :use_zero_index_for_rank => false,
40
- :page_size => nil
35
+ :page_size => nil,
36
+ :sort_by => :none
41
37
  }
42
38
 
43
39
  # Name of the leaderboard.
@@ -103,7 +99,10 @@ class Leaderboard
103
99
  #
104
100
  # @param leaderboard_name [String] Name of the leaderboard.
105
101
  def delete_leaderboard_named(leaderboard_name)
106
- @redis_connection.del(leaderboard_name)
102
+ @redis_connection.multi do |transaction|
103
+ transaction.del(leaderboard_name)
104
+ transaction.del(member_data_key(leaderboard_name))
105
+ end
107
106
  end
108
107
 
109
108
  # Rank a member in the leaderboard.
@@ -124,9 +123,7 @@ class Leaderboard
124
123
  def rank_member_in(leaderboard_name, member, score, member_data)
125
124
  @redis_connection.multi do |transaction|
126
125
  transaction.zadd(leaderboard_name, score, member)
127
- if member_data
128
- transaction.hmset(member_data_key(leaderboard_name, member), *member_data.to_a.flatten)
129
- end
126
+ transaction.hset(member_data_key(leaderboard_name), member, member_data) if member_data
130
127
  end
131
128
  end
132
129
 
@@ -146,7 +143,7 @@ class Leaderboard
146
143
  #
147
144
  # @return Hash of optional member data.
148
145
  def member_data_for_in(leaderboard_name, member)
149
- @redis_connection.hgetall(member_data_key(leaderboard_name, member))
146
+ @redis_connection.hget(member_data_key(leaderboard_name), member)
150
147
  end
151
148
 
152
149
  # Update the optional member data for a given member in the leaderboard.
@@ -163,7 +160,7 @@ class Leaderboard
163
160
  # @param member [String] Member name.
164
161
  # @param member_data [Hash] Optional member data.
165
162
  def update_member_data_in(leaderboard_name, member, member_data)
166
- @redis_connection.hmset(member_data_key(leaderboard_name, member), *member_data.to_a.flatten)
163
+ @redis_connection.hset(member_data_key(leaderboard_name), member, member_data)
167
164
  end
168
165
 
169
166
  # Remove the optional member data for a given member in the leaderboard.
@@ -178,7 +175,7 @@ class Leaderboard
178
175
  # @param leaderboard_name [String] Name of the leaderboard.
179
176
  # @param member [String] Member name.
180
177
  def remove_member_data_in(leaderboard_name, member)
181
- @redis_connection.del(member_data_key(leaderboard_name, member))
178
+ @redis_connection.hdel(member_data_key(leaderboard_name), member)
182
179
  end
183
180
 
184
181
  # Rank an array of members in the leaderboard.
@@ -218,7 +215,7 @@ class Leaderboard
218
215
  def remove_member_from(leaderboard_name, member)
219
216
  @redis_connection.multi do |transaction|
220
217
  transaction.zrem(leaderboard_name, member)
221
- transaction.del(member_data_key(leaderboard_name, member))
218
+ transaction.del(member_data_key(leaderboard_name), member)
222
219
  end
223
220
  end
224
221
 
@@ -299,33 +296,23 @@ class Leaderboard
299
296
  # Retrieve the rank for a member in the leaderboard.
300
297
  #
301
298
  # @param member [String] Member name.
302
- # @param use_zero_index_for_rank [boolean, false] If the returned rank should be 0-indexed.
303
- #
299
+ #
304
300
  # @return the rank for a member in the leaderboard.
305
- def rank_for(member, use_zero_index_for_rank = false)
306
- rank_for_in(@leaderboard_name, member, use_zero_index_for_rank)
301
+ def rank_for(member)
302
+ rank_for_in(@leaderboard_name, member)
307
303
  end
308
304
 
309
305
  # Retrieve the rank for a member in the named leaderboard.
310
306
  #
311
307
  # @param leaderboard_name [String] Name of the leaderboard.
312
308
  # @param member [String] Member name.
313
- # @param use_zero_index_for_rank [boolean, false] If the returned rank should be 0-indexed.
314
- #
309
+ #
315
310
  # @return the rank for a member in the leaderboard.
316
- def rank_for_in(leaderboard_name, member, use_zero_index_for_rank = false)
311
+ def rank_for_in(leaderboard_name, member)
317
312
  if @reverse
318
- if use_zero_index_for_rank
319
- return @redis_connection.zrank(leaderboard_name, member)
320
- else
321
- return @redis_connection.zrank(leaderboard_name, member) + 1 rescue nil
322
- end
313
+ return @redis_connection.zrank(leaderboard_name, member) + 1 rescue nil
323
314
  else
324
- if use_zero_index_for_rank
325
- return @redis_connection.zrevrank(leaderboard_name, member)
326
- else
327
- return @redis_connection.zrevrank(leaderboard_name, member) + 1 rescue nil
328
- end
315
+ return @redis_connection.zrevrank(leaderboard_name, member) + 1 rescue nil
329
316
  end
330
317
  end
331
318
 
@@ -370,21 +357,19 @@ class Leaderboard
370
357
  # Retrieve the score and rank for a member in the leaderboard.
371
358
  #
372
359
  # @param member [String] Member name.
373
- # @param use_zero_index_for_rank [boolean, false] If the returned rank should be 0-indexed.
374
360
  #
375
361
  # @return the score and rank for a member in the leaderboard as a Hash.
376
- def score_and_rank_for(member, use_zero_index_for_rank = false)
377
- score_and_rank_for_in(@leaderboard_name, member, use_zero_index_for_rank)
362
+ def score_and_rank_for(member)
363
+ score_and_rank_for_in(@leaderboard_name, member)
378
364
  end
379
365
 
380
366
  # Retrieve the score and rank for a member in the named leaderboard.
381
367
  #
382
368
  # @param leaderboard_name [String]Name of the leaderboard.
383
369
  # @param member [String] Member name.
384
- # @param use_zero_index_for_rank [boolean, false] If the returned rank should be 0-indexed.
385
370
  #
386
371
  # @return the score and rank for a member in the named leaderboard as a Hash.
387
- def score_and_rank_for_in(leaderboard_name, member, use_zero_index_for_rank = false)
372
+ def score_and_rank_for_in(leaderboard_name, member)
388
373
  responses = @redis_connection.multi do |transaction|
389
374
  transaction.zscore(leaderboard_name, member)
390
375
  if @reverse
@@ -395,11 +380,9 @@ class Leaderboard
395
380
  end
396
381
 
397
382
  responses[0] = responses[0].to_f
398
- if !use_zero_index_for_rank
399
- responses[1] = responses[1] + 1 rescue nil
400
- end
401
-
402
- {:member => member, :score => responses[0], :rank => responses[1]}
383
+ responses[1] = responses[1] + 1 rescue nil
384
+
385
+ {:member => member, :score => responses[0], :rank => responses[1]}
403
386
  end
404
387
 
405
388
  # Remove members from the leaderboard in a given score range.
@@ -795,38 +778,19 @@ class Leaderboard
795
778
  responses = @redis_connection.multi do |transaction|
796
779
  members.each do |member|
797
780
  if @reverse
798
- transaction.zrank(leaderboard_name, member) if leaderboard_options[:with_rank]
781
+ transaction.zrank(leaderboard_name, member)
799
782
  else
800
- transaction.zrevrank(leaderboard_name, member) if leaderboard_options[:with_rank]
783
+ transaction.zrevrank(leaderboard_name, member)
801
784
  end
802
- transaction.zscore(leaderboard_name, member) if leaderboard_options[:with_scores]
785
+ transaction.zscore(leaderboard_name, member)
803
786
  end
804
787
  end
805
788
 
806
789
  members.each_with_index do |member, index|
807
790
  data = {}
808
791
  data[:member] = member
809
- if leaderboard_options[:with_scores]
810
- if leaderboard_options[:with_rank]
811
- if leaderboard_options[:use_zero_index_for_rank]
812
- data[:rank] = responses[index * 2]
813
- else
814
- data[:rank] = responses[index * 2] + 1 rescue nil
815
- end
816
-
817
- data[:score] = responses[index * 2 + 1].to_f
818
- else
819
- data[:score] = responses[index].to_f
820
- end
821
- else
822
- if leaderboard_options[:with_rank]
823
- if leaderboard_options[:use_zero_index_for_rank]
824
- data[:rank] = responses[index]
825
- else
826
- data[:rank] = responses[index] + 1 rescue nil
827
- end
828
- end
829
- end
792
+ data[:rank] = responses[index * 2] + 1 rescue nil
793
+ data[:score] = responses[index * 2 + 1].to_f
830
794
 
831
795
  if leaderboard_options[:with_member_data]
832
796
  data[:member_data] = member_data_for_in(leaderboard_name, member)
@@ -835,6 +799,13 @@ class Leaderboard
835
799
  ranks_for_members << data
836
800
  end
837
801
 
802
+ case leaderboard_options[:sort_by]
803
+ when :rank
804
+ ranks_for_members = ranks_for_members.sort_by { |member| member[:rank] }
805
+ when :score
806
+ ranks_for_members = ranks_for_members.sort_by { |member| member[:score] }
807
+ end
808
+
838
809
  ranks_for_members
839
810
  end
840
811
 
@@ -861,11 +832,10 @@ class Leaderboard
861
832
  # Key for retrieving optional member data.
862
833
  #
863
834
  # @param leaderboard_name [String] Name of the leaderboard.
864
- # @param member [String] Member name.
865
- #
866
- # @return a key in the form of +leaderboard_name:data:member+
867
- def member_data_key(leaderboard_name, member)
868
- "#{leaderboard_name}:member_data:#{member}"
835
+ #
836
+ # @return a key in the form of +leaderboard_name:member_data+
837
+ def member_data_key(leaderboard_name)
838
+ "#{leaderboard_name}:member_data"
869
839
  end
870
840
 
871
841
  # Validate and return the page size. Returns the +DEFAULT_PAGE_SIZE+ if the page size is less than 1.
@@ -40,8 +40,10 @@ describe 'Leaderboard' do
40
40
  rank_members_in_leaderboard
41
41
 
42
42
  @redis_connection.exists('name').should be_true
43
+ @redis_connection.exists('name:member_data').should be_true
43
44
  @leaderboard.delete_leaderboard
44
45
  @redis_connection.exists('name').should be_false
46
+ @redis_connection.exists('name:member_data').should be_false
45
47
  end
46
48
 
47
49
  it 'should allow you to pass in an existing redis connection in the initializer' do
@@ -67,7 +69,6 @@ describe 'Leaderboard' do
67
69
  rank_members_in_leaderboard(5)
68
70
 
69
71
  @leaderboard.rank_for('member_4').should be(2)
70
- @leaderboard.rank_for('member_4', true).should be(1)
71
72
  end
72
73
 
73
74
  it 'should return the correct score when calling score_for' do
@@ -160,70 +161,57 @@ describe 'Leaderboard' do
160
161
  it 'should allow you to retrieve members in a given score range' do
161
162
  rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
162
163
 
163
- members = @leaderboard.members_from_score_range(10, 15, {:with_scores => false, :with_rank => false})
164
+ members = @leaderboard.members_from_score_range(10, 15)
164
165
 
165
- member_15 = {:member => 'member_15'}
166
+ member_15 = {:member => 'member_15', :score => 15.0, :rank => 11}
166
167
  members[0].should eql(member_15)
167
168
 
168
- member_10 = {:member => 'member_10'}
169
+ member_10 = {:member => 'member_10', :score => 10.0, :rank => 16}
169
170
  members[5].should eql(member_10)
170
171
 
171
- members = @leaderboard.members_from_score_range(10, 15, {:with_scores => true, :with_rank => true, :with_member_data => true})
172
+ members = @leaderboard.members_from_score_range(10, 15, {:with_member_data => true})
172
173
 
173
- member_15 = {:member => 'member_15', :rank => 11, :score => 15.0, :member_data => {'member_name' => 'Leaderboard member 15'}}
174
- members[0].should eql(member_15)
174
+ member_15 = {:member => 'member_15', :rank => 11, :score => 15.0, :member_data => {:member_name => 'Leaderboard member 15'}.to_s}
175
+ members[0].should == member_15
175
176
 
176
- member_10 = {:member => 'member_10', :rank => 16, :score => 10.0, :member_data => {'member_name' => 'Leaderboard member 10'}}
177
- members[5].should eql(member_10)
178
- end
179
-
180
- it 'should allow you to retrieve leaders without scores and ranks' do
181
- rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
182
-
183
- @leaderboard.total_members.should be(Leaderboard::DEFAULT_PAGE_SIZE)
184
- leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
185
-
186
- member_25 = {:member => 'member_25'}
187
- leaders[0].should eql(member_25)
188
-
189
- member_1 = {:member => 'member_1'}
190
- leaders[24].should eql(member_1)
177
+ member_10 = {:member => 'member_10', :rank => 16, :score => 10.0, :member_data => {:member_name => 'Leaderboard member 10'}.to_s}
178
+ members[5].should == member_10
191
179
  end
192
180
 
193
181
  it 'should allow you to retrieve leaders with extra data' do
194
182
  rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
195
183
 
196
184
  @leaderboard.total_members.should be(Leaderboard::DEFAULT_PAGE_SIZE)
197
- leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false, :with_member_data => true})
198
-
199
- member_25 = {:member => 'member_25', :member_data => { "member_name" => "Leaderboard member 25" }}
200
- leaders[0].should eql(member_25)
185
+ leaders = @leaderboard.leaders(1, {:with_member_data => true})
201
186
 
202
- member_1 = {:member => 'member_1', :member_data => { "member_name" => "Leaderboard member 1" }}
203
- leaders[24].should eql(member_1)
187
+ member_25 = {:member => 'member_25', :score => 25.0, :rank => 1, :member_data => { :member_name => "Leaderboard member 25" }.to_s }
188
+ leaders[0].should == member_25
189
+
190
+ member_1 = {:member => 'member_1', :score => 1.0, :rank => 25, :member_data => { :member_name => "Leaderboard member 1" }.to_s }
191
+ leaders[24].should == member_1
204
192
  end
205
193
 
206
194
  it 'should allow you to retrieve optional member data' do
207
195
  @leaderboard.rank_member('member_id', 1, {'username' => 'member_name', 'other_data_key' => 'other_data_value'})
208
196
 
209
- @leaderboard.member_data_for('unknown_member').should eql({})
210
- @leaderboard.member_data_for('member_id').should eql({'username' => 'member_name', 'other_data_key' => 'other_data_value'})
197
+ @leaderboard.member_data_for('unknown_member').should be_nil
198
+ @leaderboard.member_data_for('member_id').should == {'username' => 'member_name', 'other_data_key' => 'other_data_value'}.to_s
211
199
  end
212
200
 
213
201
  it 'should allow you to update optional member data' do
214
202
  @leaderboard.rank_member('member_id', 1, {'username' => 'member_name'})
215
203
 
216
- @leaderboard.member_data_for('member_id').should eql({'username' => 'member_name'})
217
- @leaderboard.update_member_data('member_id', {'other_data_key' => 'other_data_value'})
218
- @leaderboard.member_data_for('member_id').should eql({'username' => 'member_name', 'other_data_key' => 'other_data_value'})
204
+ @leaderboard.member_data_for('member_id').should == {'username' => 'member_name'}.to_s
205
+ @leaderboard.update_member_data('member_id', {'username' => 'member_name', 'other_data_key' => 'other_data_value'})
206
+ @leaderboard.member_data_for('member_id').should == {'username' => 'member_name', 'other_data_key' => 'other_data_value'}.to_s
219
207
  end
220
208
 
221
209
  it 'should allow you to remove optional member data' do
222
210
  @leaderboard.rank_member('member_id', 1, {'username' => 'member_name'})
223
211
 
224
- @leaderboard.member_data_for('member_id').should eql({'username' => 'member_name'})
212
+ @leaderboard.member_data_for('member_id').should == {'username' => 'member_name'}.to_s
225
213
  @leaderboard.remove_member_data('member_id')
226
- @leaderboard.member_data_for('member_id').should eql({})
214
+ @leaderboard.member_data_for('member_id').should be_nil
227
215
  end
228
216
 
229
217
  it 'should allow you to call leaders with various options that respect the defaults for the options not passed in' do
@@ -231,33 +219,7 @@ describe 'Leaderboard' do
231
219
 
232
220
  leaders = @leaderboard.leaders(1, :page_size => 1)
233
221
  leaders.size.should be(1)
234
-
235
- leaders = @leaderboard.leaders(1, :with_rank => false)
236
- leaders.size.should be(Leaderboard::DEFAULT_PAGE_SIZE)
237
- member_26 = {:member => 'member_26', :score => 26.0}
238
- member_25 = {:member => 'member_25', :score => 25.0}
239
- member_24 = {:member => 'member_24', :score => 24.0}
240
- leaders[0].should eql(member_26)
241
- leaders[1].should eql(member_25)
242
- leaders[2].should eql(member_24)
243
-
244
- leaders = @leaderboard.leaders(1, :with_scores => false)
245
- leaders.size.should be(Leaderboard::DEFAULT_PAGE_SIZE)
246
- member_26 = {:member => 'member_26', :rank => 1}
247
- member_25 = {:member => 'member_25', :rank => 2}
248
- leaders[0].should eql(member_26)
249
- leaders[1].should eql(member_25)
250
-
251
- leaders = @leaderboard.leaders(1, :with_scores => false, :with_rank => false)
252
- leaders.size.should be(Leaderboard::DEFAULT_PAGE_SIZE)
253
- member_26 = {:member => 'member_26'}
254
- member_25 = {:member => 'member_25'}
255
- leaders[0].should eql(member_26)
256
- leaders[1].should eql(member_25)
257
-
258
- leaders = @leaderboard.leaders(1, :with_rank => false, :page_size => 1)
259
- leaders.size.should be(1)
260
- member_26 = {:member => 'member_26', :score => 26.0}
222
+ member_26 = {:member => 'member_26', :score => 26.0, :rank => 1}
261
223
  leaders[0].should eql(member_26)
262
224
  end
263
225
 
@@ -268,8 +230,7 @@ describe 'Leaderboard' do
268
230
  @leaderboard.member_at(26)[:rank].should eql(26)
269
231
  @leaderboard.member_at(50)[:rank].should eql(50)
270
232
  @leaderboard.member_at(51).should be_nil
271
- @leaderboard.member_at(1, :with_member_data => true)[:member_data].should eql({'member_name' => 'Leaderboard member 50'})
272
- @leaderboard.member_at(1, :use_zero_index_for_rank => true)[:rank].should eql(0)
233
+ @leaderboard.member_at(1, :with_member_data => true)[:member_data].should == {:member_name => 'Leaderboard member 50'}.to_s
273
234
  end
274
235
 
275
236
  it 'should return the correct information when calling around_me' do
@@ -313,8 +274,7 @@ describe 'Leaderboard' do
313
274
  @leaderboard.total_members.should be(Leaderboard::DEFAULT_PAGE_SIZE)
314
275
 
315
276
  members = ['member_1', 'member_5', 'member_10']
316
- ranked_members = @leaderboard.ranked_in_list(members, {:with_scores => false, :with_rank => true, :use_zero_index_for_rank => false})
317
-
277
+ ranked_members = @leaderboard.ranked_in_list(members, {:with_rank => true})
318
278
  ranked_members.size.should be(3)
319
279
  ranked_members[0][:rank].should be(25)
320
280
  ranked_members[1][:rank].should be(21)
@@ -450,19 +410,15 @@ describe 'Leaderboard' do
450
410
  foobar.disconnect
451
411
  end
452
412
 
453
- it 'should respect the with_scores option in the massage_leader_data method' do
413
+ it 'should respect options in the massage_leader_data method' do
454
414
  rank_members_in_leaderboard(25)
455
415
 
456
416
  @leaderboard.total_members.should be(25)
457
417
 
458
- leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
418
+ leaders = @leaderboard.leaders(1)
459
419
  leaders[0][:member].should_not be_nil
460
- leaders[0][:score].should be_nil
461
- leaders[0][:rank].should be_nil
462
-
463
- @leaderboard.page_size = 25
464
- leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
465
- leaders.size.should be(25)
420
+ leaders[0][:score].should_not be_nil
421
+ leaders[0][:rank].should_not be_nil
466
422
 
467
423
  @leaderboard.page_size = Leaderboard::DEFAULT_PAGE_SIZE
468
424
  leaders = @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
@@ -638,4 +594,40 @@ describe 'Leaderboard' do
638
594
  members[0][:score].to_i.should be(25)
639
595
  members[24][:member].should eql('member_1')
640
596
  end
597
+
598
+ it 'should sort by rank if the :sort_by option is set to :rank' do
599
+ rank_members_in_leaderboard(25)
600
+
601
+ members = ['member_5', 'member_1', 'member_10']
602
+ ranked_members = @leaderboard.ranked_in_list(members, :sort_by => :rank)
603
+
604
+ ranked_members.size.should be(3)
605
+
606
+ ranked_members[0][:rank].should be(16)
607
+ ranked_members[0][:score].should eql(10.0)
608
+
609
+ ranked_members[1][:rank].should be(21)
610
+ ranked_members[1][:score].should eql(5.0)
611
+
612
+ ranked_members[2][:rank].should be(25)
613
+ ranked_members[2][:score].should eql(1.0)
614
+ end
615
+
616
+ it 'should sort by score if the :sort_by option is set to :score' do
617
+ rank_members_in_leaderboard(25)
618
+
619
+ members = ['member_5', 'member_1', 'member_10']
620
+ ranked_members = @leaderboard.ranked_in_list(members, :sort_by => :score)
621
+
622
+ ranked_members.size.should be(3)
623
+
624
+ ranked_members[0][:rank].should be(25)
625
+ ranked_members[0][:score].should eql(1.0)
626
+
627
+ ranked_members[1][:rank].should be(21)
628
+ ranked_members[1][:score].should eql(5.0)
629
+
630
+ ranked_members[2][:rank].should be(16)
631
+ ranked_members[2][:score].should eql(10.0)
632
+ end
641
633
  end
@@ -16,7 +16,6 @@ describe 'Leaderboard (reverse option)' do
16
16
  rank_members_in_leaderboard(5)
17
17
 
18
18
  @leaderboard.rank_for('member_4').should be(4)
19
- @leaderboard.rank_for('member_4', true).should be(3)
20
19
  end
21
20
 
22
21
  it 'should return the correct list when calling leaders' do
@@ -52,32 +51,19 @@ describe 'Leaderboard (reverse option)' do
52
51
 
53
52
  members = @leaderboard.members_from_score_range(10, 15, {:with_scores => false, :with_rank => false})
54
53
 
55
- member_10 = {:member => 'member_10'}
54
+ member_10 = {:member => 'member_10', :score => 10.0, :rank => 10}
56
55
  members[0].should eql(member_10)
57
56
 
58
- member_15 = {:member => 'member_15'}
57
+ member_15 = {:member => 'member_15', :score => 15.0, :rank => 15}
59
58
  members[5].should eql(member_15)
60
59
 
61
- members = @leaderboard.members_from_score_range(10, 15, {:with_scores => true, :with_rank => true, :with_member_data => true})
60
+ members = @leaderboard.members_from_score_range(10, 15, {:with_member_data => true})
62
61
 
63
- member_10 = {:member => 'member_10', :rank => 10, :score => 10.0, :member_data => {'member_name' => 'Leaderboard member 10'}}
64
- members[0].should eql(member_10)
65
-
66
- member_15 = {:member => 'member_15', :rank => 15, :score => 15.0, :member_data => {'member_name' => 'Leaderboard member 15'}}
67
- members[5].should eql(member_15)
68
- end
69
-
70
- it 'should allow you to retrieve leaders without scores and ranks' do
71
- rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
72
-
73
- @leaderboard.total_members.should be(Leaderboard::DEFAULT_PAGE_SIZE)
74
- leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
62
+ member_10 = {:member => 'member_10', :rank => 10, :score => 10.0, :member_data => {:member_name => 'Leaderboard member 10'}.to_s}
63
+ members[0].should == member_10
75
64
 
76
- member_1 = {:member => 'member_1'}
77
- leaders[0].should eql(member_1)
78
-
79
- member_25 = {:member => 'member_25'}
80
- leaders[24].should eql(member_25)
65
+ member_15 = {:member => 'member_15', :rank => 15, :score => 15.0, :member_data => {:member_name => 'Leaderboard member 15'}.to_s}
66
+ members[5].should == member_15
81
67
  end
82
68
 
83
69
  it 'should allow you to call leaders with various options that respect the defaults for the options not passed in' do
@@ -86,33 +72,14 @@ describe 'Leaderboard (reverse option)' do
86
72
  leaders = @leaderboard.leaders(1, :page_size => 1)
87
73
  leaders.size.should be(1)
88
74
 
89
- leaders = @leaderboard.leaders(1, :with_rank => false)
75
+ leaders = @leaderboard.leaders(1)
90
76
  leaders.size.should be(Leaderboard::DEFAULT_PAGE_SIZE)
91
- member_1 = {:member => 'member_1', :score => 1.0}
92
- member_2 = {:member => 'member_2', :score => 2.0}
93
- member_3 = {:member => 'member_3', :score => 3.0}
77
+ member_1 = {:member => 'member_1', :score => 1.0, :rank => 1}
78
+ member_2 = {:member => 'member_2', :score => 2.0, :rank => 2}
79
+ member_3 = {:member => 'member_3', :score => 3.0, :rank => 3}
94
80
  leaders[0].should eql(member_1)
95
81
  leaders[1].should eql(member_2)
96
82
  leaders[2].should eql(member_3)
97
-
98
- leaders = @leaderboard.leaders(1, :with_scores => false)
99
- leaders.size.should be(Leaderboard::DEFAULT_PAGE_SIZE)
100
- member_1 = {:member => 'member_1', :rank => 1}
101
- member_2 = {:member => 'member_2', :rank => 2}
102
- leaders[0].should eql(member_1)
103
- leaders[1].should eql(member_2)
104
-
105
- leaders = @leaderboard.leaders(1, :with_scores => false, :with_rank => false)
106
- leaders.size.should be(Leaderboard::DEFAULT_PAGE_SIZE)
107
- member_1 = {:member => 'member_1'}
108
- member_2 = {:member => 'member_2'}
109
- leaders[0].should eql(member_1)
110
- leaders[1].should eql(member_2)
111
-
112
- leaders = @leaderboard.leaders(1, :with_rank => false, :page_size => 1)
113
- leaders.size.should be(1)
114
- member_1 = {:member => 'member_1', :score => 1.0}
115
- leaders[0].should eql(member_1)
116
83
  end
117
84
 
118
85
  it 'should return a single member when calling member_at' do
@@ -122,8 +89,7 @@ describe 'Leaderboard (reverse option)' do
122
89
  @leaderboard.member_at(26)[:rank].should eql(26)
123
90
  @leaderboard.member_at(50)[:rank].should eql(50)
124
91
  @leaderboard.member_at(51).should be_nil
125
- @leaderboard.member_at(1, :with_member_data => true)[:member_data].should eql({'member_name' => 'Leaderboard member 1'})
126
- @leaderboard.member_at(1, :use_zero_index_for_rank => true)[:rank].should eql(0)
92
+ @leaderboard.member_at(1, :with_member_data => true)[:member_data].should == {:member_name => 'Leaderboard member 1'}.to_s
127
93
  end
128
94
 
129
95
  it 'should return the correct information when calling around_me' do
@@ -167,8 +133,7 @@ describe 'Leaderboard (reverse option)' do
167
133
  @leaderboard.total_members.should be(Leaderboard::DEFAULT_PAGE_SIZE)
168
134
 
169
135
  members = ['member_1', 'member_5', 'member_10']
170
- ranked_members = @leaderboard.ranked_in_list(members, {:with_scores => false, :with_rank => true, :use_zero_index_for_rank => false})
171
-
136
+ ranked_members = @leaderboard.ranked_in_list(members, {:with_scores => false, :with_rank => true})
172
137
  ranked_members.size.should be(3)
173
138
 
174
139
  ranked_members[0][:rank].should be(1)
@@ -261,29 +226,22 @@ describe 'Leaderboard (reverse option)' do
261
226
  foobar.disconnect
262
227
  end
263
228
 
264
- it 'should respect the with_scores option in the massage_leader_data method' do
229
+ it 'should respect options in the massage_leader_data method' do
265
230
  rank_members_in_leaderboard(25)
266
231
 
267
232
  @leaderboard.total_members.should be(25)
268
233
 
269
- leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
234
+ leaders = @leaderboard.leaders(1)
270
235
  leaders[0][:member].should_not be_nil
271
- leaders[0][:score].should be_nil
272
- leaders[0][:rank].should be_nil
273
-
274
- @leaderboard.page_size = 25
275
- leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
276
- leaders.size.should be(25)
236
+ leaders[0][:score].should_not be_nil
237
+ leaders[0][:rank].should_not be_nil
277
238
 
278
239
  @leaderboard.page_size = Leaderboard::DEFAULT_PAGE_SIZE
279
240
  leaders = @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
241
+ leaders.size.should be(25)
280
242
  leaders[0][:member].should_not be_nil
281
243
  leaders[0][:score].should_not be_nil
282
244
  leaders[0][:rank].should_not be_nil
283
-
284
- @leaderboard.page_size = 25
285
- leaders = @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
286
- leaders.size.should be(25)
287
245
  end
288
246
 
289
247
  it 'should return the correct number of members when calling around_me with a page_size options' do
@@ -354,4 +312,40 @@ describe 'Leaderboard (reverse option)' do
354
312
  members[0][:score].to_i.should be(1)
355
313
  members[24][:member].should eql('member_25')
356
314
  end
315
+
316
+ it 'should sort by rank if the :sort_by option is set to :rank' do
317
+ rank_members_in_leaderboard(25)
318
+
319
+ members = ['member_5', 'member_1', 'member_10']
320
+ ranked_members = @leaderboard.ranked_in_list(members, :sort_by => :rank)
321
+
322
+ ranked_members.size.should be(3)
323
+
324
+ ranked_members[0][:rank].should be(1)
325
+ ranked_members[0][:score].should eql(1.0)
326
+
327
+ ranked_members[1][:rank].should be(5)
328
+ ranked_members[1][:score].should eql(5.0)
329
+
330
+ ranked_members[2][:rank].should be(10)
331
+ ranked_members[2][:score].should eql(10.0)
332
+ end
333
+
334
+ it 'should sort by score if the :sort_by option is set to :score' do
335
+ rank_members_in_leaderboard(25)
336
+
337
+ members = ['member_5', 'member_1', 'member_10']
338
+ ranked_members = @leaderboard.ranked_in_list(members, :sort_by => :score)
339
+
340
+ ranked_members.size.should be(3)
341
+
342
+ ranked_members[0][:rank].should be(1)
343
+ ranked_members[0][:score].should eql(1.0)
344
+
345
+ ranked_members[1][:rank].should be(5)
346
+ ranked_members[1][:score].should eql(5.0)
347
+
348
+ ranked_members[2][:rank].should be(10)
349
+ ranked_members[2][:score].should eql(10.0)
350
+ end
357
351
  end
data/spec/version_spec.rb CHANGED
@@ -2,6 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  describe 'Leaderboard::VERSION' do
4
4
  it 'should be the correct version' do
5
- Leaderboard::VERSION.should == '2.5.0'
5
+ Leaderboard::VERSION.should == '3.0.0.rc1'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leaderboard
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
5
- prerelease:
4
+ version: 3.0.0.rc1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - David Czarnecki
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-12 00:00:00.000000000 Z
12
+ date: 2012-11-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
@@ -95,16 +95,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
95
95
  version: '0'
96
96
  segments:
97
97
  - 0
98
- hash: 1313694139295611168
98
+ hash: -395088559469707987
99
99
  required_rubygems_version: !ruby/object:Gem::Requirement
100
100
  none: false
101
101
  requirements:
102
- - - ! '>='
102
+ - - ! '>'
103
103
  - !ruby/object:Gem::Version
104
- version: '0'
105
- segments:
106
- - 0
107
- hash: 1313694139295611168
104
+ version: 1.3.1
108
105
  requirements: []
109
106
  rubyforge_project: leaderboard
110
107
  rubygems_version: 1.8.24