picky 3.6.7 → 3.6.8

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.
Files changed (63) hide show
  1. data/lib/picky/backends/file/basic.rb +1 -1
  2. data/lib/picky/backends/file/json.rb +5 -1
  3. data/lib/picky/backends/file.rb +7 -0
  4. data/lib/picky/backends/memory.rb +7 -0
  5. data/lib/picky/backends/redis/basic.rb +3 -11
  6. data/lib/picky/backends/redis/directly_manipulable.rb +48 -0
  7. data/lib/picky/backends/redis/list.rb +39 -15
  8. data/lib/picky/backends/redis/string.rb +17 -9
  9. data/lib/picky/backends/redis.rb +102 -66
  10. data/lib/picky/backends/sqlite/array.rb +38 -0
  11. data/lib/picky/backends/sqlite/basic.rb +100 -0
  12. data/lib/picky/backends/sqlite/directly_manipulable.rb +42 -0
  13. data/lib/picky/backends/sqlite/value.rb +34 -0
  14. data/lib/picky/backends/sqlite.rb +14 -4
  15. data/lib/picky/bundle.rb +12 -5
  16. data/lib/picky/bundle_indexed.rb +15 -2
  17. data/lib/picky/bundle_indexing.rb +6 -5
  18. data/lib/picky/bundle_realtime.rb +22 -31
  19. data/lib/picky/categories_realtime.rb +1 -1
  20. data/lib/picky/category_indexed.rb +1 -1
  21. data/lib/picky/category_indexing.rb +7 -5
  22. data/lib/picky/category_realtime.rb +17 -5
  23. data/lib/picky/generators/strategy.rb +4 -0
  24. data/lib/picky/index_indexing.rb +1 -4
  25. data/lib/picky/index_realtime.rb +16 -6
  26. data/lib/picky/indexers/base.rb +7 -1
  27. data/lib/picky/indexes.rb +1 -0
  28. data/lib/picky/loader.rb +11 -7
  29. data/lib/picky/query/allocation.rb +1 -1
  30. data/lib/picky/query/indexes.rb +2 -2
  31. data/lib/picky/query/token.rb +1 -1
  32. data/lib/picky/search.rb +20 -8
  33. data/lib/picky/tokenizer.rb +6 -6
  34. data/lib/picky/wrappers/bundle/delegators.rb +3 -1
  35. data/spec/category_realtime_spec.rb +33 -0
  36. data/spec/functional/backends/file_spec.rb +98 -0
  37. data/spec/functional/backends/memory_spec.rb +96 -0
  38. data/spec/functional/backends/redis_spec.rb +107 -0
  39. data/spec/functional/backends/sqlite_spec.rb +104 -0
  40. data/spec/{specific → functional}/dynamic_weights_spec.rb +0 -0
  41. data/spec/{specific → functional}/exact_first_spec.rb +2 -4
  42. data/spec/functional/max_allocations_spec.rb +33 -0
  43. data/spec/{specific → functional}/realtime_spec.rb +0 -0
  44. data/spec/{specific → functional}/regression_spec.rb +0 -0
  45. data/spec/{specific → functional}/speed_spec.rb +0 -0
  46. data/spec/lib/backends/file/basic_spec.rb +1 -1
  47. data/spec/lib/backends/redis/basic_spec.rb +12 -13
  48. data/spec/lib/backends/redis/directly_manipulable_spec.rb +91 -0
  49. data/spec/lib/backends/redis/float_spec.rb +17 -17
  50. data/spec/lib/backends/redis/list_spec.rb +9 -9
  51. data/spec/lib/backends/sqlite/array_spec.rb +143 -0
  52. data/spec/lib/backends/sqlite/directly_manipulable_spec.rb +65 -0
  53. data/spec/lib/backends/sqlite/{db_spec.rb → value_spec.rb} +2 -7
  54. data/spec/lib/backends/sqlite_spec.rb +22 -20
  55. data/spec/lib/category_indexed_spec.rb +1 -1
  56. data/spec/lib/category_indexing_spec.rb +2 -2
  57. data/spec/lib/index_indexing_spec.rb +0 -7
  58. data/spec/lib/index_realtime_spec.rb +34 -0
  59. data/spec/lib/indexed/bundle_realtime_spec.rb +166 -75
  60. data/spec/lib/indexers/base_spec.rb +13 -1
  61. data/spec/lib/search_spec.rb +31 -20
  62. metadata +58 -34
  63. data/lib/picky/backends/sqlite/db.rb +0 -84
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::Backends::Redis::DirectlyManipulable do
4
+
5
+ let(:client) { stub :client }
6
+ let(:backend) { stub :backend, client: client, namespace: 'some:namespace' }
7
+ let(:list) do
8
+ list = [1,2]
9
+ described_class.make backend, list, 'some:key'
10
+ list
11
+ end
12
+
13
+ context 'stubbed backend' do
14
+ before(:each) do
15
+ backend.stub! :[]
16
+ end
17
+ it 'calls the right client method' do
18
+ num = described_class.class_variable_get(:@@append_index)
19
+
20
+ client.should_receive(:zadd).once.with "some:namespace:some:key", num+1, 3
21
+
22
+ list << 3
23
+ end
24
+ it 'calls the right client method' do
25
+ num = described_class.class_variable_get(:@@unshift_index)
26
+
27
+ client.should_receive(:zadd).once.with "some:namespace:some:key", num-1, 3
28
+
29
+ list.unshift 3
30
+ end
31
+ it 'calls the right client method' do
32
+ client.should_receive(:zrem).once.with "some:namespace:some:key", 1
33
+
34
+ list.delete 1
35
+ end
36
+ it 'calls the right client method' do
37
+ client.should_receive(:zrem).never
38
+
39
+ list.delete 5
40
+ end
41
+ end
42
+
43
+ context 'stubbed client' do
44
+ before(:each) do
45
+ client.stub! :zadd
46
+ client.stub! :zrem
47
+ end
48
+ it 'calls [] at the end of the method' do
49
+ backend.should_receive(:[]).once.with 'some:key'
50
+
51
+ list << 3
52
+ end
53
+ it 'calls [] at the end of the method' do
54
+ backend.should_receive(:[]).once.with 'some:key'
55
+
56
+ list.unshift 3
57
+ end
58
+ it 'returns the result' do
59
+ list.delete(1).should == 1
60
+ end
61
+ end
62
+
63
+ context 'stubbed client/backend' do
64
+ before(:each) do
65
+ backend.stub! :[]
66
+ client.stub! :zadd
67
+ client.stub! :zrem
68
+ end
69
+ it 'behaves like an ordinary Array' do
70
+ list << 3
71
+
72
+ list.should == [1,2,3]
73
+ end
74
+ it 'behaves like an ordinary Array' do
75
+ list.unshift 3
76
+
77
+ list.should == [3,1,2]
78
+ end
79
+ it 'behaves like an ordinary Array' do
80
+ list.delete 1
81
+
82
+ list.should == [2]
83
+ end
84
+ it 'behaves like an ordinary Array' do
85
+ list.delete 5
86
+
87
+ list.should == [1,2]
88
+ end
89
+ end
90
+
91
+ end
@@ -1,38 +1,38 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::Redis::Float do
4
-
4
+
5
5
  let(:client) { stub :client }
6
- let(:backend) { described_class.new client, :some_namespace }
7
-
6
+ let(:backend) { described_class.new client, 'some_namespace' }
7
+
8
8
  describe 'dump' do
9
9
  it 'dumps correctly' do
10
- client.should_receive(:del).once.ordered.with :some_namespace
11
- client.should_receive(:hset).once.ordered.with :some_namespace, :a, 1
12
- client.should_receive(:hset).once.ordered.with :some_namespace, :b, 2
13
- client.should_receive(:hset).once.ordered.with :some_namespace, :c, 3
14
-
15
- backend.dump a: 1, b: 2, c: 3
10
+ client.should_receive(:del).once.ordered.with 'some_namespace'
11
+ client.should_receive(:hset).once.ordered.with 'some_namespace', 'a', 1
12
+ client.should_receive(:hset).once.ordered.with 'some_namespace', 'b', 2
13
+ client.should_receive(:hset).once.ordered.with 'some_namespace', 'c', 3
14
+
15
+ backend.dump 'a' => 1, 'b' => 2, 'c' => 3
16
16
  end
17
17
  end
18
-
18
+
19
19
  describe 'member' do
20
20
  it 'delegates to the backend' do
21
- client.should_receive(:hget).once.with :some_namespace, :some_symbol
22
-
23
- backend[:some_symbol]
21
+ client.should_receive(:hget).once.with 'some_namespace', 'some'
22
+
23
+ backend['some']
24
24
  end
25
25
  it 'returns whatever it gets from the backend' do
26
26
  client.should_receive(:hget).any_number_of_times.and_return '1.23'
27
-
28
- backend[:anything].should == 1.23
27
+
28
+ backend['anything'].should == 1.23
29
29
  end
30
30
  end
31
-
31
+
32
32
  describe 'to_s' do
33
33
  it 'returns the cache path with the default file extension' do
34
34
  backend.to_s.should == 'Picky::Backends::Redis::Float(some_namespace:*)'
35
35
  end
36
36
  end
37
-
37
+
38
38
  end
@@ -1,27 +1,27 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::Redis::List do
4
-
4
+
5
5
  let(:client) { stub :client }
6
6
  let(:index) { described_class.new client, :some_namespace }
7
-
7
+
8
8
  describe '[]' do
9
9
  it 'returns whatever comes back from the backend' do
10
- client.stub! :zrange => :some_lrange_result
11
-
12
- index[:anything].should == :some_lrange_result
10
+ client.stub! :zrange => [:some_lrange_result]
11
+
12
+ index[:anything].should == [:some_lrange_result]
13
13
  end
14
14
  it 'calls the right method on the backend' do
15
- client.should_receive(:zrange).once.with "some_namespace:some_sym", 0, -1
16
-
15
+ client.should_receive(:zrange).once.with "some_namespace:some_sym", :"0", :"-1"
16
+
17
17
  index[:some_sym]
18
18
  end
19
19
  end
20
-
20
+
21
21
  describe 'to_s' do
22
22
  it 'returns the cache path with the default file extension' do
23
23
  index.to_s.should == 'Picky::Backends::Redis::List(some_namespace:*)'
24
24
  end
25
25
  end
26
-
26
+
27
27
  end
@@ -0,0 +1,143 @@
1
+ require 'spec_helper'
2
+
3
+ require 'sqlite3'
4
+
5
+ describe Picky::Backends::SQLite::Array do
6
+
7
+ context 'hash-based indexes' do
8
+ let(:db) { described_class.new 'some/cache/path/to/file' }
9
+
10
+ describe 'dump' do
11
+ it 'delegates to the given hash' do
12
+ hash = stub :hash
13
+
14
+ db.should_receive(:dump_sqlite).once.with hash
15
+
16
+ db.dump hash
17
+ end
18
+ end
19
+
20
+ describe 'dump_sqlite' do
21
+ let(:client) { stub :client }
22
+ before(:each) do
23
+ db.stub! :db => client
24
+ end
25
+ it 'initializes the client' do
26
+ client.stub! :execute
27
+
28
+ db.should_receive(:lazily_initialize_client).once.with
29
+
30
+ db.dump_sqlite Hash.new
31
+ end
32
+ it 'executes something' do
33
+ db.stub! :lazily_initialize_client
34
+
35
+ client.should_receive(:execute).at_least(1).times
36
+
37
+ db.dump_sqlite Hash.new
38
+ end
39
+ it 'inserts keys and values' do
40
+ db.stub! :lazily_initialize_client
41
+ client.stub! :execute # We only want to test the insert statements.
42
+
43
+ client.should_receive(:execute).once.with 'insert into key_value values (?,?)', 'a', '[1,2,3]'
44
+ client.should_receive(:execute).once.with 'insert into key_value values (?,?)', 'b', '[4,5,6]'
45
+
46
+ db.dump_sqlite :a => [1,2,3], :b => [4,5,6]
47
+ end
48
+ end
49
+
50
+ describe 'load' do
51
+ it 'returns a copy of itself' do
52
+ db.load.should == db
53
+ end
54
+ end
55
+
56
+ describe 'empty' do
57
+ it 'returns the container that is used for indexing' do
58
+ db.empty.should == {}
59
+ end
60
+ end
61
+
62
+ describe 'initial' do
63
+ it 'is correct' do
64
+ db.initial.should == {}
65
+ end
66
+ end
67
+
68
+ describe 'to_s' do
69
+ it 'returns the cache path with the default file extension' do
70
+ db.to_s.should == 'Picky::Backends::SQLite::Array(some/cache/path/to/file.sqlite3)'
71
+ end
72
+ end
73
+ end
74
+
75
+ context 'hash-based indexes' do
76
+ let(:db) { described_class.new 'some/cache/path/to/file', self_indexed: true }
77
+
78
+ describe 'dump' do
79
+ it 'delegates to the given hash' do
80
+ hash = stub :hash
81
+
82
+ db.should_receive(:dump_sqlite).never
83
+
84
+ db.dump hash
85
+ end
86
+ end
87
+
88
+ describe 'dump_sqlite' do
89
+ let(:client) { stub :client }
90
+ before(:each) do
91
+ db.stub! :db => client
92
+ end
93
+ it 'initializes the client' do
94
+ client.stub! :execute
95
+
96
+ db.should_receive(:lazily_initialize_client).once.with
97
+
98
+ db.dump_sqlite Hash.new
99
+ end
100
+ it 'executes something' do
101
+ db.stub! :lazily_initialize_client
102
+
103
+ client.should_receive(:execute).at_least(1).times
104
+
105
+ db.dump_sqlite Hash.new
106
+ end
107
+ it 'inserts keys and values' do
108
+ db.stub! :lazily_initialize_client
109
+ client.stub! :execute # We only want to test the insert statements.
110
+
111
+ client.should_receive(:execute).once.with 'insert into key_value values (?,?)', 'a', '[1,2,3]'
112
+ client.should_receive(:execute).once.with 'insert into key_value values (?,?)', 'b', '[4,5,6]'
113
+
114
+ db.dump_sqlite :a => [1,2,3], :b => [4,5,6]
115
+ end
116
+ end
117
+
118
+ describe 'load' do
119
+ it 'returns a copy of itself' do
120
+ db.load.should == db
121
+ end
122
+ end
123
+
124
+ describe 'empty' do
125
+ it 'returns the container that is used for indexing' do
126
+ db.empty.should == db
127
+ end
128
+ end
129
+
130
+ describe 'initial' do
131
+ it 'is correct' do
132
+ db.initial.should == db
133
+ end
134
+ end
135
+
136
+ describe 'to_s' do
137
+ it 'returns the cache path with the default file extension' do
138
+ db.to_s.should == 'Picky::Backends::SQLite::Array(some/cache/path/to/file.sqlite3)'
139
+ end
140
+ end
141
+ end
142
+
143
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::Backends::SQLite::DirectlyManipulable do
4
+
5
+ let(:client) { stub :client }
6
+ let(:backend) { stub :backend, client: client, namespace: 'some:namespace' }
7
+ let(:array) do
8
+ array = [1,2]
9
+ described_class.make backend, array, 'some:key'
10
+ array
11
+ end
12
+
13
+ context 'stubbed backend' do
14
+ before(:each) do
15
+ backend.stub! :[]
16
+ end
17
+ it 'calls the right client method' do
18
+ backend.should_receive(:[]=).once.with 'some:key', [1,2,3]
19
+
20
+ array << 3
21
+ end
22
+ it 'calls the right client method' do
23
+ backend.should_receive(:[]=).once.with 'some:key', [3,1,2]
24
+
25
+ array.unshift 3
26
+ end
27
+ it 'calls the right client method' do
28
+ backend.should_receive(:[]=).once.with 'some:key', [2]
29
+
30
+ array.delete 1
31
+ end
32
+ it 'calls the right client method' do
33
+ client.should_receive(:zrem).never
34
+
35
+ array.delete 5
36
+ end
37
+ end
38
+
39
+ context 'stubbed client/backend' do
40
+ before(:each) do
41
+ backend.stub! :[]=
42
+ end
43
+ it 'behaves like an ordinary Array' do
44
+ array << 3
45
+
46
+ array.should == [1,2,3]
47
+ end
48
+ it 'behaves like an ordinary Array' do
49
+ array.unshift 3
50
+
51
+ array.should == [3,1,2]
52
+ end
53
+ it 'behaves like an ordinary Array' do
54
+ array.delete 1
55
+
56
+ array.should == [2]
57
+ end
58
+ it 'behaves like an ordinary Array' do
59
+ array.delete 5
60
+
61
+ array.should == [1,2]
62
+ end
63
+ end
64
+
65
+ end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  require 'sqlite3'
4
4
 
5
- describe Picky::Backends::SQLite::DB do
5
+ describe Picky::Backends::SQLite::Value do
6
6
 
7
7
  context 'hash-based indexes' do
8
8
  let(:db) { described_class.new 'some/cache/path/to/file' }
@@ -51,11 +51,6 @@ describe Picky::Backends::SQLite::DB do
51
51
  it 'returns a copy of itself' do
52
52
  db.load.should == db
53
53
  end
54
- it 'initializes the client' do
55
- db.should_receive(:lazily_initialize_client).once.with
56
-
57
- db.load
58
- end
59
54
  end
60
55
 
61
56
  describe 'empty' do
@@ -72,7 +67,7 @@ describe Picky::Backends::SQLite::DB do
72
67
 
73
68
  describe 'to_s' do
74
69
  it 'returns the cache path with the default file extension' do
75
- db.to_s.should == 'Picky::Backends::SQLite::DB(some/cache/path/to/file.sqlite3)'
70
+ db.to_s.should == 'Picky::Backends::SQLite::Value(some/cache/path/to/file.sqlite3)'
76
71
  end
77
72
  end
78
73
  end
@@ -1,23 +1,25 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'sqlite3'
4
+
3
5
  describe Picky::Backends::SQLite do
4
6
 
5
7
  context 'with options' do
6
8
  before(:each) do
7
- @backend = described_class.new inverted: Picky::Backends::SQLite::DB.new(:unimportant),
8
- weights: Picky::Backends::SQLite::DB.new(:unimportant),
9
- similarity: Picky::Backends::SQLite::DB.new(:unimportant),
10
- configuration: Picky::Backends::SQLite::DB.new(:unimportant)
9
+ @backend = described_class.new inverted: Picky::Backends::SQLite::Value.new(:unimportant),
10
+ weights: Picky::Backends::SQLite::Array.new(:unimportant),
11
+ similarity: Picky::Backends::SQLite::Value.new(:unimportant),
12
+ configuration: Picky::Backends::SQLite::Array.new(:unimportant)
11
13
 
12
14
  @backend.stub! :timed_exclaim
13
15
  end
14
16
 
15
17
  describe 'create_...' do
16
18
  [
17
- [:inverted, Picky::Backends::SQLite::DB],
18
- [:weights, Picky::Backends::SQLite::DB],
19
- [:similarity, Picky::Backends::SQLite::DB],
20
- [:configuration, Picky::Backends::SQLite::DB]
19
+ [:inverted, Picky::Backends::SQLite::Value],
20
+ [:weights, Picky::Backends::SQLite::Array],
21
+ [:similarity, Picky::Backends::SQLite::Value],
22
+ [:configuration, Picky::Backends::SQLite::Array]
21
23
  ].each do |type, kind|
22
24
  it "creates and returns a(n) #{type} index" do
23
25
  @backend.send(:"create_#{type}",
@@ -30,20 +32,20 @@ describe Picky::Backends::SQLite do
30
32
 
31
33
  context 'with lambda options' do
32
34
  before(:each) do
33
- @backend = described_class.new inverted: ->(bundle){ Picky::Backends::SQLite::DB.new(bundle.index_path(:inverted)) },
34
- weights: ->(bundle){ Picky::Backends::SQLite::DB.new(bundle.index_path(:weights)) },
35
- similarity: ->(bundle){ Picky::Backends::SQLite::DB.new(bundle.index_path(:similarity)) },
36
- configuration: ->(bundle){ Picky::Backends::SQLite::DB.new(bundle.index_path(:configuration)) }
35
+ @backend = described_class.new inverted: ->(bundle){ Picky::Backends::SQLite::Value.new(bundle.index_path(:inverted)) },
36
+ weights: ->(bundle){ Picky::Backends::SQLite::Array.new(bundle.index_path(:weights)) },
37
+ similarity: ->(bundle){ Picky::Backends::SQLite::Value.new(bundle.index_path(:similarity)) },
38
+ configuration: ->(bundle){ Picky::Backends::SQLite::Array.new(bundle.index_path(:configuration)) }
37
39
 
38
40
  @backend.stub! :timed_exclaim
39
41
  end
40
42
 
41
43
  describe 'create_...' do
42
44
  [
43
- [:inverted, Picky::Backends::SQLite::DB],
44
- [:weights, Picky::Backends::SQLite::DB],
45
- [:similarity, Picky::Backends::SQLite::DB],
46
- [:configuration, Picky::Backends::SQLite::DB]
45
+ [:inverted, Picky::Backends::SQLite::Value],
46
+ [:weights, Picky::Backends::SQLite::Array],
47
+ [:similarity, Picky::Backends::SQLite::Value],
48
+ [:configuration, Picky::Backends::SQLite::Array]
47
49
  ].each do |type, kind|
48
50
  it "creates and returns a(n) #{type} index" do
49
51
  to_a_able_stub = Object.new
@@ -63,10 +65,10 @@ describe Picky::Backends::SQLite do
63
65
 
64
66
  describe 'create_...' do
65
67
  [
66
- [:inverted, Picky::Backends::SQLite::DB],
67
- [:weights, Picky::Backends::SQLite::DB],
68
- [:similarity, Picky::Backends::SQLite::DB],
69
- [:configuration, Picky::Backends::SQLite::DB]
68
+ [:inverted, Picky::Backends::SQLite::Array],
69
+ [:weights, Picky::Backends::SQLite::Value],
70
+ [:similarity, Picky::Backends::SQLite::Array],
71
+ [:configuration, Picky::Backends::SQLite::Value]
70
72
  ].each do |type, kind|
71
73
  it "creates and returns a(n) #{type} index" do
72
74
  @backend.send(:"create_#{type}",
@@ -160,7 +160,7 @@ describe Picky::Category do
160
160
 
161
161
  describe 'load' do
162
162
  it 'should call two methods' do
163
- @category.should_receive(:clear_realtime_mapping).once
163
+ @category.should_receive(:clear_realtime).once
164
164
  @exact.should_receive(:load).once
165
165
  @partial.should_receive(:load).once
166
166
 
@@ -14,8 +14,8 @@ describe Picky::Category do
14
14
 
15
15
  describe 'clear' do
16
16
  it 'delegates to both bundles' do
17
- exact.should_receive(:delete).once.with()
18
- partial.should_receive(:delete).once.with()
17
+ exact.should_receive(:clear).once.with()
18
+ partial.should_receive(:clear).once.with()
19
19
 
20
20
  category.clear
21
21
  end
@@ -97,13 +97,6 @@ describe Picky::Index do
97
97
  @index.define_category :some_category_name1
98
98
  @index.define_category :some_category_name2
99
99
  end
100
- describe "warn_no_source" do
101
- it "should warn" do
102
- @index.should_receive(:warn).once.with "No source given for index some_name."
103
-
104
- @index.warn_no_source
105
- end
106
- end
107
100
  describe 'define_source' do
108
101
  it 'can be set with this method' do
109
102
  source = stub :source, :each => [].each
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe Picky::Index, "Realtime API" do
6
+
7
+ Thing = Struct.new :id, :text
8
+
9
+ let(:index) do
10
+ described_class.new :some_index_name do
11
+ category :text
12
+ end
13
+ end
14
+
15
+ it 'offers an add method' do
16
+ index.add Thing.new(1, 'text')
17
+ end
18
+ it 'offers a remove method' do
19
+ index.remove 1
20
+ end
21
+ it 'offers a replace method' do
22
+ index.replace Thing.new(1, 'text')
23
+ end
24
+ it 'offers a << method' do
25
+ index << Thing.new(1, 'text')
26
+ end
27
+ # it 'offers a >> method' do
28
+ # Thing.new(1, 'text') >> index # I mean, as long as we're dreaming.
29
+ # end
30
+ it 'offers an unshift method' do
31
+ index.unshift Thing.new(1, 'text')
32
+ end
33
+
34
+ end