picky 4.0.0pre6 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/lib/picky/api/category/partial.rb +26 -0
  2. data/lib/picky/api/category/similarity.rb +26 -0
  3. data/lib/picky/api/category/weight.rb +26 -0
  4. data/lib/picky/api/search/boost.rb +28 -0
  5. data/lib/picky/api/source.rb +35 -0
  6. data/lib/picky/api/tokenizer/character_substituter.rb +22 -0
  7. data/lib/picky/api/tokenizer.rb +37 -0
  8. data/lib/picky/bundle.rb +1 -1
  9. data/lib/picky/bundle_realtime.rb +2 -2
  10. data/lib/picky/category.rb +12 -6
  11. data/lib/picky/category_indexing.rb +2 -8
  12. data/lib/picky/generators/similarity/double_metaphone.rb +1 -1
  13. data/lib/picky/generators/similarity/metaphone.rb +1 -1
  14. data/lib/picky/generators/similarity/none.rb +1 -1
  15. data/lib/picky/generators/similarity/soundex.rb +1 -1
  16. data/lib/picky/index_indexing.rb +5 -25
  17. data/lib/picky/loader.rb +15 -5
  18. data/lib/picky/query/allocation.rb +1 -1
  19. data/lib/picky/query/{weights.rb → boosts.rb} +17 -17
  20. data/lib/picky/query/combinations.rb +2 -2
  21. data/lib/picky/search.rb +17 -19
  22. data/lib/picky/tokenizer.rb +7 -4
  23. data/spec/lib/api/category/partial_spec.rb +49 -0
  24. data/spec/lib/api/category/similarity_spec.rb +50 -0
  25. data/spec/lib/api/category/weight_spec.rb +47 -0
  26. data/spec/lib/api/search/boost_spec.rb +44 -0
  27. data/spec/lib/api/source_spec.rb +68 -0
  28. data/spec/lib/api/tokenizer/character_substituter_spec.rb +34 -0
  29. data/spec/lib/api/tokenizer_spec.rb +42 -0
  30. data/spec/lib/category_indexed_spec.rb +2 -2
  31. data/spec/lib/category_indexing_spec.rb +11 -24
  32. data/spec/lib/category_spec.rb +48 -11
  33. data/spec/lib/generators/similarity/double_metaphone_spec.rb +1 -1
  34. data/spec/lib/generators/similarity/metaphone_spec.rb +1 -1
  35. data/spec/lib/generators/similarity/none_spec.rb +1 -1
  36. data/spec/lib/generators/similarity/soundex_spec.rb +1 -1
  37. data/spec/lib/index_indexing_spec.rb +10 -14
  38. data/spec/lib/index_spec.rb +1 -1
  39. data/spec/lib/query/allocation_spec.rb +2 -2
  40. data/spec/lib/query/boosts_spec.rb +79 -0
  41. data/spec/lib/query/combinations_spec.rb +3 -3
  42. data/spec/lib/search_spec.rb +13 -13
  43. data/spec/lib/tokenizer_spec.rb +12 -8
  44. metadata +44 -23
  45. data/spec/lib/query/weights_spec.rb +0 -81
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::API::Category::Partial do
4
+ let(:object) do
5
+ Class.new do
6
+ include Picky::API::Category::Partial
7
+
8
+ def index_name
9
+ :some_index
10
+ end
11
+ def name
12
+ :some_category
13
+ end
14
+ end.new
15
+ end
16
+ context 'extract_partial' do
17
+ context 'with nil' do
18
+ it 'returns the default' do
19
+ object.extract_partial(nil).should == Picky::Partial::Default
20
+ end
21
+ end
22
+ context 'with a partial object' do
23
+ let(:partializer) do
24
+ Class.new do
25
+ def each_partial text
26
+ 'tex'
27
+ end
28
+ end.new
29
+ end
30
+ it 'yields the partial' do
31
+ object.extract_partial(partializer).each_partial('whatevs') do |text|
32
+ text.should == 'tex'
33
+ end
34
+ end
35
+ end
36
+ context 'invalid weight' do
37
+ it 'raises with a nice error message' do
38
+ expect {
39
+ object.extract_partial Object.new
40
+ }.to raise_error(<<-ERROR)
41
+ partial options for some_index:some_category should be either
42
+ * for example a Partial::Substring.new(from: m, to: n), Partial::Postfix.new(from: n), Partial::Infix.new(min: m, max: n) etc.
43
+ or
44
+ * an object that responds to #each_partial(str_or_sym) and yields each partial
45
+ ERROR
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::API::Category::Similarity do
4
+ let(:object) do
5
+ Class.new do
6
+ include Picky::API::Category::Similarity
7
+
8
+ def index_name
9
+ :some_index
10
+ end
11
+ def name
12
+ :some_category
13
+ end
14
+ end.new
15
+ end
16
+ context 'encode' do
17
+ context 'with nil' do
18
+ it 'returns the default' do
19
+ object.extract_similarity(nil).should == Picky::Similarity::Default
20
+ end
21
+ end
22
+ context 'with a similarity object' do
23
+ let(:similarizer) do
24
+ Class.new do
25
+ def encode text
26
+ :encoded
27
+ end
28
+ def prioritize ary, encoded
29
+
30
+ end
31
+ end.new
32
+ end
33
+ it 'returns the encoded string' do
34
+ object.extract_similarity(similarizer).encode('whatevs').should == :encoded
35
+ end
36
+ end
37
+ context 'invalid weight' do
38
+ it 'raises with a nice error message' do
39
+ expect {
40
+ object.extract_similarity Object.new
41
+ }.to raise_error(<<-ERROR)
42
+ similarity options for some_index:some_category should be either
43
+ * for example a Similarity::Phonetic.new(n), Similarity::Metaphone.new(n), Similarity::DoubleMetaphone.new(n) etc.
44
+ or
45
+ * an object that responds to #encode(text) => encoded_text and #prioritize(array_of_encoded, encoded)
46
+ ERROR
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::API::Category::Weight do
4
+ let(:object) do
5
+ Class.new do
6
+ include Picky::API::Category::Weight
7
+
8
+ def index_name
9
+ :some_index
10
+ end
11
+ def name
12
+ :some_category
13
+ end
14
+ end.new
15
+ end
16
+ context 'extract_weight' do
17
+ context 'with nil' do
18
+ it 'returns the default' do
19
+ object.extract_weight(nil).should == Picky::Weights::Default
20
+ end
21
+ end
22
+ context 'with a weight object' do
23
+ let(:weighter) do
24
+ Class.new do
25
+ def weight_for amount
26
+ 7.0
27
+ end
28
+ end.new
29
+ end
30
+ it 'creates a tokenizer' do
31
+ object.extract_weight(weighter).weight_for(21).should == 7.0
32
+ end
33
+ end
34
+ context 'invalid weight' do
35
+ it 'raises with a nice error message' do
36
+ expect {
37
+ object.extract_weight Object.new
38
+ }.to raise_error(<<-ERROR)
39
+ weight options for some_index:some_category should be either
40
+ * for example a Weights::Logarithmic.new, Weights::Constant.new(int = 0), Weights::Dynamic.new(&block) etc.
41
+ or
42
+ * an object that responds to #weight_for(amount_of_ids_for_token) => float
43
+ ERROR
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::API::Search::Boost do
4
+ let(:object) do
5
+ Class.new do
6
+ include Picky::API::Search::Boost
7
+ end.new
8
+ end
9
+ context 'extract_weight' do
10
+ context 'with a Hash' do
11
+ it 'returns a boosts object' do
12
+ combinations = [
13
+ stub(:combination, :category_name => :bla)
14
+ ]
15
+
16
+ object.extract_boosts([:bla] => +7.77).boost_for(combinations).should == 7.77
17
+ end
18
+ end
19
+ context 'with a boosts object' do
20
+ let(:booster) do
21
+ Class.new do
22
+ def boost_for whatever
23
+ 7.0
24
+ end
25
+ end.new
26
+ end
27
+ it 'returns a boosts object' do
28
+ object.extract_boosts(booster).boost_for(:anything).should == 7.0
29
+ end
30
+ end
31
+ context 'invalid weight' do
32
+ it 'raises with a nice error message' do
33
+ expect {
34
+ object.extract_boosts Object.new
35
+ }.to raise_error(<<-ERROR)
36
+ boost options for a Search should be either
37
+ * for example a Hash { [:name, :surname] => +3 }
38
+ or
39
+ * an object that responds to #boost_for(combinations) and returns a boost float
40
+ ERROR
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::API::Source do
4
+ let(:object) do
5
+ Class.new do
6
+ include Picky::API::Source
7
+ end.new
8
+ end
9
+ context 'unblock_source' do
10
+ before(:each) do
11
+ class << object
12
+ def source_with source = nil, &block
13
+ @source = source || block
14
+ end
15
+ end
16
+ end
17
+ context 'with block' do
18
+ it 'unblocks' do
19
+ object.source_with do
20
+ :some_source
21
+ end
22
+
23
+ object.unblock_source == :some_source
24
+ end
25
+ end
26
+ context 'with #each' do
27
+ it 'takes the source directly' do
28
+ object.source_with :some_source
29
+
30
+ object.unblock_source == :some_source
31
+ end
32
+ end
33
+ end
34
+ context 'extract_source' do
35
+ context 'block with source hash' do
36
+ it 'extracts a source' do
37
+ object.extract_source(Proc.new {}).should be_kind_of(Proc)
38
+ end
39
+ end
40
+ context 'each source' do
41
+ let(:source) do
42
+ Class.new do
43
+ def each
44
+
45
+ end
46
+ end.new
47
+ end
48
+ it 'extracts a source' do
49
+ object.extract_source(source).should == source
50
+ end
51
+ end
52
+ context 'invalid tokenizer' do
53
+ it 'raises with a nice error message' do
54
+ expect {
55
+ object.extract_source Object.new
56
+ }.to raise_error(<<-ERROR)
57
+ The source should respond to either the method #each or
58
+ it can be a lambda/block, returning such a source.
59
+ ERROR
60
+ end
61
+ end
62
+ context 'with nil_ok option' do
63
+ it 'simply returns nil back' do
64
+ object.extract_source(nil, nil_ok: true).should == nil
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::API::Tokenizer do
4
+ let(:object) do
5
+ Class.new do
6
+ include Picky::API::Tokenizer::CharacterSubstituter
7
+ end.new
8
+ end
9
+ context 'extract_character_substituter' do
10
+ context 'with a substituter' do
11
+ let(:substituter) do
12
+ Class.new do
13
+ def substitute text
14
+ text.tr('a-z', '1-9')
15
+ end
16
+ end.new
17
+ end
18
+ it 'creates a tokenizer' do
19
+ object.extract_character_substituter(substituter).
20
+ substitute("picky").should == '99399'
21
+ end
22
+ end
23
+ context 'invalid tokenizer' do
24
+ it 'raises with a nice error message' do
25
+ expect {
26
+ object.extract_character_substituter Object.new
27
+ }.to raise_error(<<-ERROR)
28
+ The substitutes_characters_with option needs a character substituter,
29
+ which responds to #substitute(text) and returns substituted_text."
30
+ ERROR
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::API::Tokenizer do
4
+ let(:object) do
5
+ Class.new do
6
+ include Picky::API::Tokenizer
7
+ end.new
8
+ end
9
+ context 'extract_tokenizer' do
10
+ context 'options hash' do
11
+ it 'creates a tokenizer' do
12
+ object.extract_tokenizer(indexing: { splits_text_on: /\t/ }).
13
+ tokenize("hello\tworld").should == [['hello', 'world'], ['hello', 'world']]
14
+ end
15
+ end
16
+ context 'tokenizer' do
17
+ let(:tokenizer) do
18
+ Class.new do
19
+ def tokenize text
20
+ ['unmoved', 'by', 'your', 'texts']
21
+ end
22
+ end.new
23
+ end
24
+ it 'creates a tokenizer' do
25
+ object.extract_tokenizer(tokenizer).
26
+ tokenize("hello\tworld").should == ['unmoved', 'by', 'your', 'texts']
27
+ end
28
+ end
29
+ context 'invalid tokenizer' do
30
+ it 'raises with a nice error message' do
31
+ expect {
32
+ object.extract_tokenizer Object.new
33
+ }.to raise_error(<<-ERROR)
34
+ indexing options should be either
35
+ * a Hash
36
+ or
37
+ * an object that responds to #tokenize(text) => [[token1, ...], [original1, ...]]
38
+ ERROR
39
+ end
40
+ end
41
+ end
42
+ end
@@ -6,9 +6,9 @@ describe Picky::Category do
6
6
  @index = Picky::Index.new :some_index do
7
7
  source []
8
8
  end
9
- @partial_strategy = stub :partial, :use_exact_for_partial? => false
9
+ @partial_strategy = stub :partial, :each_partial => nil, :use_exact_for_partial? => false
10
10
  @weight_strategy = stub :weights, :saved? => true
11
- @similarity_strategy = stub :similarity
11
+ @similarity_strategy = stub :similarity, :encode => nil, :prioritize => nil
12
12
 
13
13
  @exact = stub :exact, :dump => nil
14
14
  @partial = stub :partial, :dump => nil
@@ -4,7 +4,7 @@ describe Picky::Category do
4
4
 
5
5
  before(:each) do
6
6
  @index = Picky::Index.new :some_index
7
- @source = stub :some_given_source, :key_format => nil
7
+ @source = stub :some_given_source, :each => nil
8
8
  end
9
9
  let(:category) { described_class.new(:some_category, @index, :source => @source).tap { |c| c.stub! :timed_exclaim } }
10
10
 
@@ -70,37 +70,24 @@ describe Picky::Category do
70
70
  end
71
71
 
72
72
  describe 'key_format' do
73
- context 'source has key_format' do
73
+ context 'category has its own key_format' do
74
74
  before(:each) do
75
- category.stub! :source => stub(:source, :key_format => :some_key_format)
75
+ category.instance_variable_set :@key_format, :other_key_format
76
76
  end
77
77
  it 'returns that key_format' do
78
- category.key_format.should == :some_key_format
78
+ category.key_format.should == :other_key_format
79
79
  end
80
80
  end
81
- context 'source does not have key_format' do
81
+ context 'category does not have its own key format' do
82
82
  before(:each) do
83
- category.stub! :source => stub(:source)
83
+ category.instance_variable_set :@key_format, nil
84
84
  end
85
- context 'category has its own key_format' do
85
+ context 'it has an index' do
86
86
  before(:each) do
87
- category.instance_variable_set :@key_format, :other_key_format
87
+ category.instance_variable_set :@index, stub(:index, :key_format => :yet_another_key_format)
88
88
  end
89
89
  it 'returns that key_format' do
90
- category.key_format.should == :other_key_format
91
- end
92
- end
93
- context 'category does not have its own key format' do
94
- before(:each) do
95
- category.instance_variable_set :@key_format, nil
96
- end
97
- context 'it has an index' do
98
- before(:each) do
99
- category.instance_variable_set :@index, stub(:index, :key_format => :yet_another_key_format)
100
- end
101
- it 'returns that key_format' do
102
- category.key_format.should == :yet_another_key_format
103
- end
90
+ category.key_format.should == :yet_another_key_format
104
91
  end
105
92
  end
106
93
  end
@@ -108,9 +95,9 @@ describe Picky::Category do
108
95
 
109
96
  describe 'source' do
110
97
  context 'with explicit source' do
111
- let(:category) { described_class.new(:some_category, @index, :source => :category_source) }
98
+ let(:category) { described_class.new(:some_category, @index, :source => [1]) }
112
99
  it 'returns the right source' do
113
- category.source.should == :category_source
100
+ category.source.should == [1]
114
101
  end
115
102
  end
116
103
  context 'without explicit source' do
@@ -3,22 +3,59 @@ require 'spec_helper'
3
3
  describe Picky::Category do
4
4
 
5
5
  let(:index) { Picky::Index.new :some_index }
6
- let(:category) { described_class.new :some_category, index }
7
6
 
8
- it 'should set defaults correctly' do
9
- category.exact.weight_strategy.should == Picky::Generators::Weights::Default
10
- category.exact.partial_strategy.should be_kind_of(Picky::Generators::Partial::None)
11
- category.exact.similarity_strategy.should == Picky::Generators::Similarity::Default
7
+ context 'default parameters' do
8
+ let(:category) { described_class.new :some_category, index }
12
9
 
13
- category.partial.weight_strategy.should be_kind_of(Picky::Generators::Weights::Logarithmic)
14
- category.partial.partial_strategy.should == Picky::Generators::Partial::Default
15
- category.partial.similarity_strategy.should be_kind_of(Picky::Generators::Similarity::None)
10
+ it 'should set defaults correctly' do
11
+ category.exact.weight_strategy.should == Picky::Generators::Weights::Default
12
+ category.exact.partial_strategy.should be_kind_of(Picky::Generators::Partial::None)
13
+ category.exact.similarity_strategy.should == Picky::Generators::Similarity::Default
16
14
 
17
- category.exact.similarity_strategy.should == Picky::Generators::Similarity::Default
15
+ category.partial.weight_strategy.should be_kind_of(Picky::Generators::Weights::Logarithmic)
16
+ category.partial.partial_strategy.should == Picky::Generators::Partial::Default
17
+ category.partial.similarity_strategy.should be_kind_of(Picky::Generators::Similarity::None)
18
18
 
19
- category.partial.similarity_strategy.should be_kind_of(Picky::Generators::Similarity::None)
19
+ category.exact.similarity_strategy.should == Picky::Generators::Similarity::Default
20
20
 
21
- category.instance_variable_get(:@symbols).should == nil
21
+ category.partial.similarity_strategy.should be_kind_of(Picky::Generators::Similarity::None)
22
+
23
+ category.instance_variable_get(:@symbols).should == nil
24
+ end
25
+ end
26
+
27
+ context 'tokenizer' do
28
+ context 'options hash' do
29
+ let(:category) { described_class.new :some_category, index, indexing: { splits_text_on: /\t/ } }
30
+ it 'creates a tokenizer' do
31
+ category.tokenizer.tokenize("hello\tworld").should == [['hello', 'world'], ['hello', 'world']]
32
+ end
33
+ end
34
+ context 'tokenizer' do
35
+ let(:tokenizer) do
36
+ Class.new do
37
+ def tokenize text
38
+ ['unmoved', 'by', 'your', 'texts']
39
+ end
40
+ end.new
41
+ end
42
+ let(:category) { described_class.new :some_category, index, indexing: tokenizer }
43
+ it 'creates a tokenizer' do
44
+ category.tokenizer.tokenize("hello\tworld").should == ['unmoved', 'by', 'your', 'texts']
45
+ end
46
+ end
47
+ context 'invalid tokenizer' do
48
+ it 'raises with a nice error message' do
49
+ expect {
50
+ described_class.new :some_category, index, indexing: Object.new
51
+ }.to raise_error(<<-ERROR)
52
+ indexing options for some_index:some_category should be either
53
+ * a Hash
54
+ or
55
+ * an object that responds to #tokenize(text) => [[token1, ...], [original1, ...]]
56
+ ERROR
57
+ end
58
+ end
22
59
  end
23
60
 
24
61
  end
@@ -10,7 +10,7 @@ describe Picky::Generators::Similarity::DoubleMetaphone do
10
10
 
11
11
  def self.it_should_encode text, expected
12
12
  it "should encode #{text.inspect} correctly" do
13
- @similarity.encoded(text).should == expected
13
+ @similarity.encode(text).should == expected
14
14
  end
15
15
  end
16
16
  # def self.it_should_generate_from index, expected
@@ -10,7 +10,7 @@ describe Picky::Generators::Similarity::Metaphone do
10
10
 
11
11
  def self.it_should_encode text, expected
12
12
  it "should encode #{text.inspect} correctly" do
13
- @similarity.encoded(text).should == expected
13
+ @similarity.encode(text).should == expected
14
14
  end
15
15
  end
16
16
  # def self.it_should_generate_from index, expected
@@ -16,7 +16,7 @@ describe Picky::Generators::Similarity::None do
16
16
 
17
17
  describe 'encode' do
18
18
  it 'should always return nil' do
19
- @similarity.encoded(:whatever).should == nil
19
+ @similarity.encode(:whatever).should == nil
20
20
  end
21
21
  end
22
22
 
@@ -10,7 +10,7 @@ describe Picky::Generators::Similarity::Soundex do
10
10
 
11
11
  def self.it_should_encode text, expected
12
12
  it "should encode #{text.inspect} correctly" do
13
- @similarity.encoded(text).should == expected
13
+ @similarity.encode(text).should == expected
14
14
  end
15
15
  end
16
16
  # def self.it_should_generate_from index, expected
@@ -69,21 +69,17 @@ describe Picky::Index do
69
69
  end
70
70
  context 'with non#each source' do
71
71
  let(:source) { stub :source, :harvest => nil }
72
- let(:index) do
73
- the_source = source
74
- described_class.new :some_name do
75
- source the_source
76
- end
77
- end
78
72
 
79
- it 'does things in order' do
80
- categories = stub :categories
81
- index.stub! :categories => categories
82
-
83
- categories.should_receive(:prepare).once
84
- categories.should_receive(:cache).once
85
-
86
- index.index
73
+ it 'raises' do
74
+ the_source = source
75
+ expect {
76
+ described_class.new :some_name do
77
+ source the_source
78
+ end
79
+ }.to raise_error(<<-ERROR)
80
+ The some_name source should respond to either the method #each or
81
+ it can be a lambda/block, returning such a source.
82
+ ERROR
87
83
  end
88
84
  end
89
85
  end
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
 
5
5
  describe Picky::Index do
6
6
 
7
- let(:some_source) { stub :source, :harvest => nil, :inspect => 'some_source' }
7
+ let(:some_source) { stub :source, :each => nil, :inspect => 'some_source' }
8
8
 
9
9
  context 'initializer' do
10
10
  it 'works' do
@@ -180,9 +180,9 @@ describe Picky::Query::Allocation do
180
180
  context 'non-empty combinations' do
181
181
  it 'should delegate to backend and combinations' do
182
182
  @backend.should_receive(:weight).once.with(@combinations).and_return 1
183
- @combinations.should_receive(:weighted_score).once.with(:some_weights).and_return 2
183
+ @combinations.should_receive(:boost_for).once.with(:some_boosts).and_return 2
184
184
 
185
- @allocation.calculate_score(:some_weights).should == 3
185
+ @allocation.calculate_score(:some_boosts).should == 3
186
186
  end
187
187
  end
188
188
  context 'empty combinations' do
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::Query::Boosts do
4
+
5
+ context 'with boosts' do
6
+ let(:boosts) do
7
+ described_class.new [:test1, :test2] => 6,
8
+ [:test1] => 5,
9
+ [:test3] => 3,
10
+ [:test3, :test2] => 4,
11
+ [:test1, :test4] => 5,
12
+ [:test4, :test1] => 5,
13
+ [:test4, :test1, :test2] => 4,
14
+ [:test1, :test4, :test2] => 4,
15
+ [:test4, :test5] => 3,
16
+ [:test5, :test1] => 2,
17
+ [:test1, :test5] => 2,
18
+ [:test3, :test1] => 2,
19
+ [:test1, :test3] => 2
20
+ end
21
+
22
+ describe 'boost_for' do
23
+ it 'gets the category names from the combinations' do
24
+ combinations = [
25
+ stub(:combination1, :category_name => :test1),
26
+ stub(:combination1, :category_name => :test2)
27
+ ]
28
+
29
+ boosts.boost_for(combinations).should == +6
30
+ end
31
+ end
32
+
33
+ describe "weight_for" do
34
+ it "should return zero if there is no specific weight" do
35
+ boosts.boost_for_categories([:not_a_specific_allocation]).should be_zero
36
+ end
37
+ end
38
+
39
+ def self.it_should_return_a_specific_boost_for(allocation, boost)
40
+ it "should return boost #{boost} for #{allocation.inspect}" do
41
+ boosts.boost_for_categories(allocation).should == boost
42
+ end
43
+ end
44
+
45
+ it_should_return_a_specific_boost_for [:test1, :test2], 6
46
+ it_should_return_a_specific_boost_for [:test1], 5
47
+ it_should_return_a_specific_boost_for [:test1, :test3], 2
48
+ it_should_return_a_specific_boost_for [:test3], 3
49
+ it_should_return_a_specific_boost_for [:test3, :test2], 4
50
+ it_should_return_a_specific_boost_for [:test1, :test4], 5
51
+ it_should_return_a_specific_boost_for [:test4, :test1], 5
52
+ it_should_return_a_specific_boost_for [:test4, :test1, :test2], 4
53
+ it_should_return_a_specific_boost_for [:test1, :test4, :test2], 4
54
+ it_should_return_a_specific_boost_for [:test4, :test5], 3
55
+ it_should_return_a_specific_boost_for [:test5, :test1], 2
56
+ it_should_return_a_specific_boost_for [:test1, :test5], 2
57
+ it_should_return_a_specific_boost_for [:test3, :test1], 2
58
+
59
+ describe 'to_s' do
60
+ it 'is correct' do
61
+ boosts.to_s.should == "Picky::Query::Boosts({[:test1, :test2]=>6, [:test1]=>5, [:test3]=>3, [:test3, :test2]=>4, [:test1, :test4]=>5, [:test4, :test1]=>5, [:test4, :test1, :test2]=>4, [:test1, :test4, :test2]=>4, [:test4, :test5]=>3, [:test5, :test1]=>2, [:test1, :test5]=>2, [:test3, :test1]=>2, [:test1, :test3]=>2})"
62
+ end
63
+ end
64
+ describe 'empty?' do
65
+ it 'is correct' do
66
+ boosts.empty?.should == false
67
+ end
68
+ end
69
+ end
70
+ context 'without boosts' do
71
+ let(:boosts) { described_class.new }
72
+ describe 'empty?' do
73
+ it 'is correct' do
74
+ boosts.empty?.should == true
75
+ end
76
+ end
77
+ end
78
+
79
+ end