mock_redis 0.5.5 → 0.6.0

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.
@@ -1,3 +1,6 @@
1
+ ### 0.6.0
2
+ * Support for `#sort` (ascending and descending only)
3
+
1
4
  ### 0.5.5
2
5
  * Support exclusive ranges in `zcount`
3
6
  * List methods (`lindex`, `lrange`, `lset`, and `ltrim`) can take string indexes
data/README.md CHANGED
@@ -51,6 +51,9 @@ necessary exceptions.
51
51
 
52
52
  * `#info` just returns canned values; they don't update over time.
53
53
 
54
+ * `#sort` supports ascending and descending sort. `ALPHA` sort is not yet
55
+ supported.
56
+
54
57
  ## Unsupported Commands
55
58
 
56
59
  Some stuff, we just can't do with a single Ruby object in a single
@@ -79,10 +82,6 @@ please submit a pull request with your (tested!) implementation.
79
82
  * `#config(:get|:set|:resetstat)` isn't done. They can just return
80
83
  canned values.
81
84
 
82
- * `#sort` isn't done. We just haven't gotten to it yet. The input
83
- validation will be a pain in the butt, but other than that, it
84
- shouldn't be too bad.
85
-
86
85
  ## Running the Tests
87
86
 
88
87
  If you want to work on this, you'll probably want to run the
@@ -5,6 +5,7 @@ require 'mock_redis/list_methods'
5
5
  require 'mock_redis/set_methods'
6
6
  require 'mock_redis/string_methods'
7
7
  require 'mock_redis/zset_methods'
8
+ require 'mock_redis/sort_method'
8
9
 
9
10
  class MockRedis
10
11
  class Database
@@ -13,6 +14,7 @@ class MockRedis
13
14
  include SetMethods
14
15
  include StringMethods
15
16
  include ZsetMethods
17
+ include SortMethod
16
18
 
17
19
  attr_reader :data, :expire_times
18
20
 
@@ -0,0 +1,82 @@
1
+ require 'mock_redis/assertions'
2
+
3
+ class MockRedis
4
+ module SortMethod
5
+ include Assertions
6
+
7
+ def sort(key, options={})
8
+ return [] if key.nil?
9
+
10
+ enumerable = data[key]
11
+
12
+ return [] if enumerable.nil?
13
+
14
+ by = options[:by]
15
+ limit = options[:limit] || []
16
+ store = options[:store]
17
+ get_patterns = Array(options[:get])
18
+ order = options[:order] || "ASC"
19
+ direction = order.split.first
20
+
21
+ projected = project(enumerable, by, get_patterns)
22
+ sorted = sort_by(projected, direction)
23
+ sliced = slice(sorted, limit)
24
+
25
+ store ? rpush(store, sliced) : sliced
26
+ end
27
+
28
+ private
29
+
30
+ ASCENDING_SORT = Proc.new { |a, b| a.first <=> b.first }
31
+ DESCENDING_SORT = Proc.new { |a, b| b.first <=> a.first }
32
+
33
+ def project(enumerable, by, get_patterns)
34
+ enumerable.map do |*elements|
35
+ element = elements.last
36
+ weight = by ? lookup_from_pattern(by, element) : element
37
+ value = element
38
+
39
+ if get_patterns.length > 0
40
+ value = get_patterns.map do |pattern|
41
+ pattern == "#" ? element : lookup_from_pattern(pattern, element)
42
+ end
43
+ value = value.first if value.length == 1
44
+ end
45
+
46
+ [weight, value]
47
+ end
48
+ end
49
+
50
+ def sort_by(projected, direction)
51
+ sorter =
52
+ case direction.upcase
53
+ when "DESC"
54
+ DESCENDING_SORT
55
+ when "ASC", "ALPHA"
56
+ ASCENDING_SORT
57
+ else
58
+ raise "Invalid direction '#{direction}'"
59
+ end
60
+
61
+ projected.sort(&sorter).map(&:last)
62
+ end
63
+
64
+ def slice(sorted, limit)
65
+ skip = limit.first || 0
66
+ take = limit.last || sorted.length
67
+
68
+ sorted[skip...(skip + take)] || sorted
69
+ end
70
+
71
+ def lookup_from_pattern(pattern, element)
72
+ key = pattern.sub('*', element)
73
+
74
+ if (hash_parts = key.split('->')).length > 1
75
+ hget hash_parts.first, hash_parts.last
76
+ else
77
+ get key
78
+ end
79
+ end
80
+
81
+ end
82
+ end
@@ -1,3 +1,3 @@
1
1
  class MockRedis
2
- VERSION = '0.5.5'
2
+ VERSION = '0.6.0'
3
3
  end
@@ -21,7 +21,7 @@ describe "#setbit(key, offset)" do
21
21
 
22
22
  it "does the right thing with multibyte characters" do
23
23
  @redises.set(@key, "€99.94") # the euro sign is 3 bytes wide in UTF-8
24
- # @redises.setbit(@key, 63, 1).should == 0
24
+ @redises.setbit(@key, 63, 1).should == 0
25
25
  @redises.get(@key).should == "€99.95"
26
26
  end
27
27
 
@@ -43,4 +43,4 @@ describe "#setbit(key, offset)" do
43
43
 
44
44
  it_should_behave_like "a string-only command"
45
45
  end
46
-
46
+
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#sort(key, options)' do
4
+ before do
5
+ @key = "mock-redis-test:list_sort"
6
+
7
+ @redises.rpush(@key, '1')
8
+ @redises.rpush(@key, '2')
9
+
10
+ @redises.set('mock-redis-test:values_1', 'a')
11
+ @redises.set('mock-redis-test:values_2', 'b')
12
+
13
+ @redises.set('mock-redis-test:weight_1', '2')
14
+ @redises.set('mock-redis-test:weight_2', '1')
15
+
16
+ @redises.hset('mock-redis-test:hash_1', 'key', 'x')
17
+ @redises.hset('mock-redis-test:hash_2', 'key', 'y')
18
+ end
19
+
20
+ it_should_behave_like "a sortable"
21
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#sort(key, options)' do
4
+ before do
5
+ @key = "mock-redis-test:set_sort"
6
+
7
+ @redises.sadd(@key, '1')
8
+ @redises.sadd(@key, '2')
9
+
10
+ @redises.set('mock-redis-test:values_1', 'a')
11
+ @redises.set('mock-redis-test:values_2', 'b')
12
+
13
+ @redises.set('mock-redis-test:weight_1', '2')
14
+ @redises.set('mock-redis-test:weight_2', '1')
15
+
16
+ @redises.hset('mock-redis-test:hash_1', 'key', 'x')
17
+ @redises.hset('mock-redis-test:hash_2', 'key', 'y')
18
+ end
19
+
20
+ it_should_behave_like "a sortable"
21
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#sort(key, options)' do
4
+ before do
5
+ @key = "mock-redis-test:zset_sort"
6
+
7
+ @redises.zadd(@key, 100, '1')
8
+ @redises.zadd(@key, 99, '2')
9
+
10
+ @redises.set('mock-redis-test:values_1', 'a')
11
+ @redises.set('mock-redis-test:values_2', 'b')
12
+
13
+ @redises.set('mock-redis-test:weight_1', '2')
14
+ @redises.set('mock-redis-test:weight_2', '1')
15
+
16
+ @redises.hset('mock-redis-test:hash_1', 'key', 'x')
17
+ @redises.hset('mock-redis-test:hash_2', 'key', 'y')
18
+ end
19
+
20
+ it_should_behave_like "a sortable"
21
+ end
@@ -0,0 +1,56 @@
1
+ shared_examples_for "a sortable" do
2
+ it 'returns empty array on nil' do
3
+ @redises.sort(nil).should == []
4
+ end
5
+
6
+ context 'ordering' do
7
+ it 'orders ascending by default' do
8
+ @redises.sort(@key).should == ['1', '2']
9
+ end
10
+
11
+ it 'orders by descending when specified' do
12
+ @redises.sort(@key, :order => "DESC").should == ['2', '1']
13
+ end
14
+ end
15
+
16
+ context 'projections' do
17
+ it 'projects element when :get is "#"' do
18
+ @redises.sort(@key, :get => '#').should == ['1', '2']
19
+ end
20
+
21
+ it 'projects through a key pattern' do
22
+ @redises.sort(@key, :get => 'mock-redis-test:values_*').should == ['a', 'b']
23
+ end
24
+
25
+ it 'projects through a key pattern and reflects element' do
26
+ @redises.sort(@key, :get => ['#', 'mock-redis-test:values_*']).should == [['1', 'a'], ['2', 'b']]
27
+ end
28
+
29
+ it 'projects through a hash key pattern' do
30
+ @redises.sort(@key, :get => 'mock-redis-test:hash_*->key').should == ['x', 'y']
31
+ end
32
+ end
33
+
34
+ context 'weights' do
35
+ it 'weights by projecting through a key pattern' do
36
+ @redises.sort(@key, :by => "mock-redis-test:weight_*").should == ['2', '1']
37
+ end
38
+
39
+ it 'weights by projecting through a key pattern and a specific order' do
40
+ @redises.sort(@key, :order => "DESC", :by => "mock-redis-test:weight_*").should == ['1', '2']
41
+ end
42
+ end
43
+
44
+ context 'limit' do
45
+ it 'only returns requested window in the enumerable' do
46
+ @redises.sort(@key, :limit => [0, 1]).should == ['1']
47
+ end
48
+ end
49
+
50
+ context 'store' do
51
+ it 'stores into another key' do
52
+ @redises.sort(@key, :store => "mock-redis-test:some_bucket").should == 2
53
+ @redises.lrange("mock-redis-test:some_bucket", 0, -1).should == ['1', '2']
54
+ end
55
+ end
56
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mock_redis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-10-28 00:00:00.000000000 Z
13
+ date: 2012-10-30 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
@@ -86,6 +86,7 @@ files:
86
86
  - lib/mock_redis/multi_db_wrapper.rb
87
87
  - lib/mock_redis/pipelined_wrapper.rb
88
88
  - lib/mock_redis/set_methods.rb
89
+ - lib/mock_redis/sort_method.rb
89
90
  - lib/mock_redis/string_methods.rb
90
91
  - lib/mock_redis/transaction_wrapper.rb
91
92
  - lib/mock_redis/undef_redis_methods.rb
@@ -178,6 +179,9 @@ files:
178
179
  - spec/commands/sismember_spec.rb
179
180
  - spec/commands/smembers_spec.rb
180
181
  - spec/commands/smove_spec.rb
182
+ - spec/commands/sort_list_spec.rb
183
+ - spec/commands/sort_set_spec.rb
184
+ - spec/commands/sort_zset_spec.rb
181
185
  - spec/commands/spop_spec.rb
182
186
  - spec/commands/srandmember_spec.rb
183
187
  - spec/commands/srem_spec.rb
@@ -212,6 +216,7 @@ files:
212
216
  - spec/support/shared_examples/only_operates_on_sets.rb
213
217
  - spec/support/shared_examples/only_operates_on_strings.rb
214
218
  - spec/support/shared_examples/only_operates_on_zsets.rb
219
+ - spec/support/shared_examples/sorts_enumerables.rb
215
220
  - spec/transactions_spec.rb
216
221
  homepage: https://github.com/causes/mock_redis
217
222
  licenses: []
@@ -322,6 +327,9 @@ test_files:
322
327
  - spec/commands/sismember_spec.rb
323
328
  - spec/commands/smembers_spec.rb
324
329
  - spec/commands/smove_spec.rb
330
+ - spec/commands/sort_list_spec.rb
331
+ - spec/commands/sort_set_spec.rb
332
+ - spec/commands/sort_zset_spec.rb
325
333
  - spec/commands/spop_spec.rb
326
334
  - spec/commands/srandmember_spec.rb
327
335
  - spec/commands/srem_spec.rb
@@ -356,5 +364,6 @@ test_files:
356
364
  - spec/support/shared_examples/only_operates_on_sets.rb
357
365
  - spec/support/shared_examples/only_operates_on_strings.rb
358
366
  - spec/support/shared_examples/only_operates_on_zsets.rb
367
+ - spec/support/shared_examples/sorts_enumerables.rb
359
368
  - spec/transactions_spec.rb
360
369
  has_rdoc: