leaderboard 2.5.0 → 3.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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