picky 4.0.0pre1 → 4.0.0pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. data/aux/picky/cli.rb +6 -2
  2. data/lib/picky.rb +10 -8
  3. data/lib/picky/backends/backend.rb +37 -0
  4. data/lib/picky/backends/file.rb +0 -20
  5. data/lib/picky/backends/memory.rb +0 -29
  6. data/lib/picky/backends/redis.rb +74 -15
  7. data/lib/picky/backends/redis/list.rb +1 -1
  8. data/lib/picky/backends/sqlite.rb +0 -27
  9. data/lib/picky/bundle.rb +2 -2
  10. data/lib/picky/bundle_indexed.rb +1 -1
  11. data/lib/picky/bundle_indexing.rb +1 -1
  12. data/lib/picky/categories_indexed.rb +1 -11
  13. data/lib/picky/category.rb +4 -4
  14. data/lib/picky/category/location.rb +25 -0
  15. data/lib/picky/category_realtime.rb +4 -3
  16. data/lib/picky/console.rb +1 -1
  17. data/lib/picky/constants.rb +1 -1
  18. data/lib/picky/ext/maybe_compile.rb +2 -2
  19. data/lib/picky/extensions/object.rb +3 -2
  20. data/lib/picky/generators/aliases.rb +7 -2
  21. data/lib/picky/generators/partial/default.rb +1 -0
  22. data/lib/picky/generators/similarity/default.rb +1 -0
  23. data/lib/picky/generators/similarity/phonetic.rb +13 -2
  24. data/lib/picky/generators/strategy.rb +0 -2
  25. data/lib/picky/generators/weights/constant.rb +1 -2
  26. data/lib/picky/generators/weights/default.rb +1 -0
  27. data/lib/picky/generators/weights/dynamic.rb +1 -1
  28. data/lib/picky/generators/weights/logarithmic.rb +1 -1
  29. data/lib/picky/generators/weights/{runtime.rb → stub.rb} +1 -3
  30. data/lib/picky/index.rb +3 -3
  31. data/lib/picky/index_indexing.rb +0 -2
  32. data/lib/picky/index_realtime.rb +1 -1
  33. data/lib/picky/indexers/base.rb +7 -0
  34. data/lib/picky/indexers/parallel.rb +2 -4
  35. data/lib/picky/indexers/serial.rb +2 -0
  36. data/lib/picky/indexes_indexing.rb +1 -1
  37. data/lib/picky/interfaces/live_parameters/master_child.rb +175 -0
  38. data/lib/picky/interfaces/live_parameters/unicorn.rb +37 -0
  39. data/lib/picky/loader.rb +238 -259
  40. data/lib/picky/query/allocation.rb +19 -10
  41. data/lib/picky/query/combination.rb +7 -1
  42. data/lib/picky/query/combinations.rb +1 -6
  43. data/lib/picky/query/token.rb +26 -36
  44. data/lib/picky/results.rb +18 -17
  45. data/lib/picky/scheduler.rb +2 -1
  46. data/lib/picky/search.rb +1 -1
  47. data/lib/picky/sinatra.rb +6 -6
  48. data/lib/picky/statistics.rb +2 -0
  49. data/lib/picky/tokenizer.rb +8 -8
  50. data/lib/picky/wrappers/bundle/calculation.rb +4 -4
  51. data/lib/picky/wrappers/bundle/location.rb +1 -2
  52. data/lib/tasks/framework.rake +1 -1
  53. data/lib/tasks/statistics.rake +1 -1
  54. data/lib/tasks/try.rake +1 -1
  55. data/lib/tasks/try.rb +1 -1
  56. data/spec/aux/picky/cli_spec.rb +12 -12
  57. data/spec/ext/performant_spec.rb +16 -16
  58. data/spec/functional/backends/file_spec.rb +78 -7
  59. data/spec/functional/backends/memory_spec.rb +78 -7
  60. data/spec/functional/backends/redis_spec.rb +73 -13
  61. data/spec/functional/dynamic_weights_spec.rb +3 -4
  62. data/spec/functional/realtime_spec.rb +2 -2
  63. data/spec/functional/speed_spec.rb +2 -2
  64. data/spec/functional/terminate_early_spec.rb +3 -3
  65. data/spec/lib/analytics_spec.rb +1 -1
  66. data/spec/lib/analyzer_spec.rb +5 -3
  67. data/spec/lib/categories_indexed_spec.rb +38 -20
  68. data/spec/lib/category/location_spec.rb +30 -0
  69. data/spec/lib/character_substituters/west_european_spec.rb +1 -0
  70. data/spec/lib/extensions/hash_spec.rb +6 -5
  71. data/spec/lib/extensions/module_spec.rb +6 -6
  72. data/spec/lib/extensions/object_spec.rb +9 -8
  73. data/spec/lib/extensions/string_spec.rb +1 -1
  74. data/spec/lib/generators/similarity/phonetic_spec.rb +11 -0
  75. data/spec/lib/index_realtime_spec.rb +5 -5
  76. data/spec/lib/interfaces/{live_parameters_spec.rb → live_parameters/master_child_spec.rb} +26 -26
  77. data/spec/lib/interfaces/live_parameters/unicorn_spec.rb +160 -0
  78. data/spec/lib/loader_spec.rb +65 -25
  79. data/spec/lib/query/allocation_spec.rb +25 -22
  80. data/spec/lib/query/combinations_spec.rb +13 -36
  81. data/spec/lib/query/token_spec.rb +144 -131
  82. data/spec/lib/query/tokens_spec.rb +14 -0
  83. data/spec/lib/results_spec.rb +14 -8
  84. data/spec/lib/search_spec.rb +1 -1
  85. data/spec/lib/sinatra_spec.rb +8 -8
  86. metadata +28 -91
  87. data/lib/picky/adapters/rack.rb +0 -34
  88. data/lib/picky/adapters/rack/base.rb +0 -27
  89. data/lib/picky/adapters/rack/live_parameters.rb +0 -37
  90. data/lib/picky/adapters/rack/search.rb +0 -67
  91. data/lib/picky/application.rb +0 -268
  92. data/lib/picky/frontend_adapters/rack.rb +0 -161
  93. data/lib/picky/interfaces/live_parameters.rb +0 -187
  94. data/lib/picky/sources/base.rb +0 -92
  95. data/lib/picky/sources/couch.rb +0 -76
  96. data/lib/picky/sources/csv.rb +0 -83
  97. data/lib/picky/sources/db.rb +0 -189
  98. data/lib/picky/sources/delicious.rb +0 -63
  99. data/lib/picky/sources/mongo.rb +0 -80
  100. data/lib/picky/wrappers/category/location.rb +0 -38
  101. data/lib/tasks/routes.rake +0 -8
  102. data/spec/lib/adapters/rack/base_spec.rb +0 -24
  103. data/spec/lib/adapters/rack/live_parameters_spec.rb +0 -26
  104. data/spec/lib/adapters/rack/query_spec.rb +0 -39
  105. data/spec/lib/application_spec.rb +0 -155
  106. data/spec/lib/frontend_adapters/rack_spec.rb +0 -294
  107. data/spec/lib/sources/base_spec.rb +0 -53
  108. data/spec/lib/sources/couch_spec.rb +0 -114
  109. data/spec/lib/sources/csv_spec.rb +0 -89
  110. data/spec/lib/sources/db_spec.rb +0 -125
  111. data/spec/lib/sources/delicious_spec.rb +0 -94
  112. data/spec/lib/sources/mongo_spec.rb +0 -50
@@ -1,53 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Picky::Sources::Base do
4
- context 'with the base class' do
5
- let(:source) { described_class.new }
6
-
7
- describe 'connect_backend' do
8
- it 'exists' do
9
- source.connect_backend
10
- end
11
- end
12
-
13
- describe 'take_snapshot' do
14
- it 'exists and takes a single parameter' do
15
- source.take_snapshot :some_index
16
- end
17
- end
18
- end
19
-
20
- context 'with subclass' do
21
- let(:take_snapshot_called) { 0 }
22
- let(:subclass) do
23
- Class.new(described_class) do
24
- def take_snapshot index
25
- index.call index
26
- end
27
- end.new
28
- end
29
-
30
- describe 'with snapshot' do
31
- it 'is called only once when called in nested blocks' do
32
- index = stub :index, :identifier => :some_index
33
- subclass.stub! :timed_exclaim
34
-
35
- index.should_receive(:call).once.with index
36
-
37
- subclass.with_snapshot(index) do
38
- subclass.with_snapshot(index) do
39
- subclass.with_snapshot(index) do
40
-
41
- end
42
- end
43
- subclass.with_snapshot(index) do
44
- subclass.with_snapshot(index) do
45
-
46
- end
47
- end
48
- end
49
- end
50
- end
51
- end
52
-
53
- end
@@ -1,114 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Picky::Sources::Couch do
4
-
5
- describe 'key_format' do
6
- context 'default' do
7
- let(:source) { described_class.new(:a, :b, url: 'bla') }
8
- it 'is correct' do
9
- source.key_format.should == :to_s
10
- end
11
- end
12
- context 'non-default' do
13
- let(:source) { described_class.new(:a, :b, url: 'bla', key_format: 'some_key_method') }
14
- it 'is correct' do
15
- source.key_format.should == :some_key_method
16
- end
17
- end
18
- end
19
-
20
- describe 'to_s' do
21
- let(:source) { described_class.new(:a, :b, :url => 'bla') }
22
- it 'is correct' do
23
- source.to_s.should == 'Picky::Sources::Couch'
24
- end
25
- end
26
-
27
- describe 'special keys' do
28
- context 'uuid keys' do
29
- context "with database" do
30
- before(:each) do
31
- @source = described_class.new :a, :b, :c, url: 'http://localhost:5984/picky'
32
- RestClient::Request.should_receive(:execute).any_number_of_times.and_return %{{"rows":[{"doc":{"_id":"550e8400-e29b-41d4-a716-446655440000","a":"a data","b":"b data","c":"c data"}}]}}
33
- end
34
-
35
- describe "harvest" do
36
- it "yields the right data" do
37
- category = stub :b, :from => :b
38
- @source.harvest category do |id, token|
39
- id.should eql('550e8400-e29b-41d4-a716-446655440000')
40
- token.should eql('b data')
41
- end.should have(1).item
42
- end
43
- end
44
-
45
- describe "get_data" do
46
- it "yields each line" do
47
- @source.get_data do |data|
48
- data.should == { "_id" => "550e8400-e29b-41d4-a716-446655440000", "a" => "a data", "b" => "b data", "c" => "c data" }
49
- end.should have(1).item
50
- end
51
- end
52
- end
53
- end
54
- context 'integer keys' do
55
- context "with database" do
56
- before(:each) do
57
- @source = described_class.new :a, :b, :c, url: 'http://localhost:5984/picky'
58
- RestClient::Request.should_receive(:execute).any_number_of_times.and_return %{{"rows":[{"doc":{"_id":"123","a":"a data","b":"b data","c":"c data"}}]}}
59
- end
60
-
61
- describe "harvest" do
62
- it "yields the right data" do
63
- category = stub :b, :from => :b
64
- @source.harvest category do |id, token|
65
- id.should eql('123')
66
- token.should eql('b data')
67
- end.should have(1).item
68
- end
69
- end
70
-
71
- describe "get_data" do
72
- it "yields each line" do
73
- @source.get_data do |data|
74
- data.should == { "_id" => "123", "a" => "a data", "b" => "b data", "c" => "c data" }
75
- end.should have(1).item
76
- end
77
- end
78
- end
79
- end
80
- end
81
-
82
- context 'default keys' do
83
- context "without database" do
84
- it "should fail correctly" do
85
- lambda { described_class.new(:a, :b, :c) }.should raise_error(described_class::NoDBGiven)
86
- end
87
- end
88
-
89
- context "with database" do
90
- before(:each) do
91
- @source = described_class.new :a, :b, :c, url: 'http://localhost:5984/picky'
92
- RestClient::Request.should_receive(:execute).any_number_of_times.and_return %{{"rows":[{"doc":{"_id":"7f","a":"a data","b":"b data","c":"c data"}}]}}
93
- end
94
-
95
- describe "harvest" do
96
- it "yields the right data" do
97
- category = stub :b, :from => :b
98
- @source.harvest category do |id, token|
99
- id.should eql('7f')
100
- token.should eql('b data')
101
- end.should have(1).item
102
- end
103
- end
104
-
105
- describe "get_data" do
106
- it "yields each line" do
107
- @source.get_data do |data|
108
- data.should == { "_id" => "7f", "a" => "a data", "b" => "b data", "c" => "c data" }
109
- end.should have(1).item
110
- end
111
- end
112
- end
113
- end
114
- end
@@ -1,89 +0,0 @@
1
- require 'spec_helper'
2
- require 'csv'
3
-
4
- describe Picky::Sources::CSV do
5
-
6
- describe 'to_s' do
7
- let(:source) { described_class.new :a, :b, :c, file:'some/file.csv' }
8
- it 'outputs the correct string' do
9
- source.to_s.should == 'Picky::Sources::CSV(a, b, c, {:file=>"some/file.csv"})'
10
- end
11
- end
12
-
13
- describe 'without separator' do
14
- before(:each) do
15
- @source = described_class.new :a, :b, :c, :file => :some_file
16
- end
17
- it 'calls foreach correctly' do
18
- block = lambda { |*args| }
19
-
20
- ::CSV.should_receive(:foreach).once.with :some_file, {}, &block
21
-
22
- @source.get_data &block
23
- end
24
- end
25
- describe 'with separator' do
26
- before(:each) do
27
- @source = described_class.new :a, :b, :c, :file => :some_file, :col_sep => 'some_separator'
28
- end
29
- it 'calls foreach correctly' do
30
- block = lambda { |*args| }
31
-
32
- ::CSV.should_receive(:foreach).once.with :some_file, :col_sep => 'some_separator', &block
33
-
34
- @source.get_data &block
35
- end
36
- end
37
-
38
- context "without file" do
39
- it "should fail correctly" do
40
- lambda { @source = described_class.new(:a, :b, :c) }.should raise_error(described_class::NoFileGiven)
41
- end
42
- end
43
- context "with file" do
44
- before(:each) do
45
- ::CSV.should_receive(:foreach).any_number_of_times.and_yield [' 7', 'a data', 'b data', 'c data']
46
- end
47
- context 'without separator' do
48
- before(:each) do
49
- @source = described_class.new :a, :b, :c, :file => :some_file
50
- end
51
- describe "harvest" do
52
- it "should yield the right data" do
53
- category = stub :b, :from => :b
54
- @source.harvest category do |id, token|
55
- [id, token].should == [' 7', 'b data']
56
- end
57
- end
58
- end
59
- describe "get_data" do
60
- it "should yield each line" do
61
- @source.get_data do |data|
62
- data.should == [' 7', 'a data', 'b data', 'c data']
63
- end
64
- end
65
- end
66
- end
67
- context 'with key_format method' do
68
- before(:each) do
69
- @source = described_class.new :a, :b, :c, :file => :some_file, :key_format => :strip
70
- end
71
- describe "harvest" do
72
- it "should yield the right data" do
73
- category = stub :b, :from => :b
74
- @source.harvest category do |id, token|
75
- [id, token].should == [' 7', 'b data']
76
- end
77
- end
78
- end
79
- describe "get_data" do
80
- it "should yield each line" do
81
- @source.get_data do |data|
82
- data.should == [' 7', 'a data', 'b data', 'c data']
83
- end
84
- end
85
- end
86
- end
87
- end
88
-
89
- end
@@ -1,125 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Picky::Sources::DB do
4
-
5
- before(:each) do
6
- @connection = stub :connection
7
- @adapter = stub :adapter, :connection => @connection
8
-
9
- @select_statement = stub :statement, :inspect => '"some statement"'
10
-
11
- @source = described_class.new @select_statement, :option => :some_options
12
-
13
- @source.stub! :database => @adapter
14
- @source.stub! :connect_backend
15
- end
16
-
17
- describe 'to_s' do
18
- it 'does something' do
19
- @source.to_s.should == 'Picky::Sources::DB("some statement", {:option=>:some_options})'
20
- end
21
- end
22
-
23
- describe "get_data" do
24
- before(:each) do
25
- @category = stub :category, :from => :some_category, :index_name => :some_index_name
26
- end
27
- context 'mysql' do
28
- before(:each) do
29
- @connection.stub! :adapter_name => 'mysql'
30
- end
31
- context 'no data' do
32
- it "delegates to the connection" do
33
-
34
- @connection.should_receive(:execute).
35
- once.
36
- with('SELECT id, some_category FROM picky_some_index_name_index st WHERE st.__picky_id > some_offset LIMIT 25000').
37
- and_return []
38
-
39
- @source.get_data @category, :some_offset
40
- end
41
- end
42
- context 'with data' do
43
- it 'yields to the caller' do
44
- @connection.should_receive(:execute).
45
- any_number_of_times.
46
- with('SELECT id, some_category FROM picky_some_index_name_index st WHERE st.__picky_id > some_offset LIMIT 25000').
47
- and_return [[1, 'text']]
48
-
49
- @source.get_data @category, :some_offset do |id, text|
50
- id.should == 1
51
- text.should == 'text'
52
- end
53
- end
54
- end
55
- end
56
- end
57
-
58
- describe "configure" do
59
- it "works" do
60
- lambda { @source.configure({}) }.should_not raise_error
61
- end
62
- context "with file" do
63
- it "opens the config file relative to root" do
64
- File.should_receive(:open).once.with 'spec/test_directory/app/bla.yml'
65
-
66
- @source.configure :file => 'app/bla.yml'
67
- end
68
- end
69
- end
70
-
71
- describe "connect_backend" do
72
- it "works" do
73
- lambda { @source.connect_backend }.should_not raise_error
74
- end
75
- end
76
-
77
- describe "chunksize" do
78
- it "should be a specific size" do
79
- @source.chunksize.should == 25_000
80
- end
81
- end
82
-
83
- describe "count" do
84
- it "should get the count through the public DB connection" do
85
- result = stub(:result, :to_i => 12_345)
86
- @connection.should_receive(:select_value).once.and_return(result)
87
-
88
- @source.count :anything
89
- end
90
- it "should get the id count" do
91
- result = stub(:result, :to_i => 12_345)
92
- @connection.should_receive(:select_value).once.with("SELECT COUNT(__picky_id) FROM picky_some_type_name_index")
93
-
94
- @source.count :some_type_name
95
- end
96
- end
97
-
98
- describe 'harvest' do
99
- before(:each) do
100
- @category = stub :category, :name => :some_category, :index_name => :some_index
101
-
102
- @source.should_receive(:get_data).any_number_of_times.and_return [[:some_id, 'some_text']].cycle
103
- @source.stub! :count => 17
104
- end
105
- end
106
-
107
- describe "harvest_statement_with_offset" do
108
- before(:each) do
109
- @category = stub :category, :from => :some_category
110
- end
111
- it "should get a harvest statement and the chunksize to put the statement together" do
112
- @source.should_receive(:harvest_statement).once.with(@category).and_return 'some_example_statement'
113
- @source.harvest_statement_with_offset(@category, :some_offset)
114
- end
115
- it "should add an AND if it already contains a WHERE statement" do
116
- @source.should_receive(:harvest_statement).and_return 'WHERE'
117
- @source.harvest_statement_with_offset(@category, :some_offset).should == "WHERE AND st.__picky_id > some_offset LIMIT 25000"
118
- end
119
- it "should add a WHERE if it doesn't already contain one" do
120
- @source.should_receive(:harvest_statement).and_return 'some_statement'
121
- @source.harvest_statement_with_offset(@category, :some_offset).should == "some_statement WHERE st.__picky_id > some_offset LIMIT 25000"
122
- end
123
- end
124
-
125
- end
@@ -1,94 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Picky::Sources::Delicious do
4
-
5
- context "with file" do
6
-
7
- describe 'to_s' do
8
- it 'outputs correctly' do
9
- described_class.new(:username, :password).to_s.should == 'Picky::Sources::Delicious(username)'
10
- end
11
- end
12
-
13
- describe "check_gem" do
14
- before(:each) do
15
- @source = described_class.allocate
16
- end
17
- context "doesn't find www/delicious" do
18
- before(:each) do
19
- @source.should_receive(:require).any_number_of_times.and_raise LoadError
20
- end
21
- it "warns & exits" do
22
- @source.should_receive(:warn).once.with "www-delicious gem missing!\nTo use the delicious source, you need to:\n 1. Add the following line to Gemfile:\n gem 'www-delicious'\n or\n require 'www-delicious'\n for example on top of your app.rb/application.rb\n 2. Then, run:\n bundle update\n"
23
- @source.should_receive(:exit).once.with 1
24
-
25
- @source.check_gem
26
- end
27
- end
28
- context "finds www/delicious" do
29
- before(:each) do
30
- @source.should_receive(:require).any_number_of_times.and_return
31
- end
32
- it "checks if the gem is there" do
33
- lambda { @source.check_gem }.should_not raise_error
34
- end
35
- end
36
- end
37
-
38
- describe "harvest" do
39
- before(:each) do
40
- @source = described_class.new(:username, :password)
41
-
42
- post1 = WWW::Delicious::Post.new
43
- post1.uid = "5045d67b3f251e4ae966dffe71501763"
44
- post1.tags = ["barefoot", "running", "shoe"]
45
- post1.title = "VIBRAM - FiveFingers"
46
- post1.url = URI.parse('http://www.vibramfivefingers.it/')
47
-
48
- delicious = stub :delicious, :posts_recent => [post1]
49
-
50
- WWW::Delicious.should_receive(:new).and_return delicious
51
- end
52
- it "should yield the right data" do
53
- category = stub :b, :from => :tags
54
- @source.harvest category do |id, token|
55
- [id, token].should == [1, "barefoot running shoe"]
56
- end
57
- end
58
- it "should yield the right data" do
59
- category = stub :b, :from => :title
60
- @source.harvest category do |id, token|
61
- [id, token].should == [1, "VIBRAM - FiveFingers"]
62
- end
63
- end
64
- it "should yield the right data" do
65
- category = stub :b, :from => :url
66
- @source.harvest category do |id, token|
67
- [id, token].should == [1, "http://www.vibramfivefingers.it/"]
68
- end
69
- end
70
- end
71
- describe "get_data" do
72
- before(:each) do
73
- @source = described_class.new(:username, :password)
74
-
75
- post1 = WWW::Delicious::Post.new
76
- post1.uid = "5045d67b3f251e4ae966dffe71501763"
77
- post1.tags = ["barefoot", "running", "shoe"]
78
- post1.title = "VIBRAM - FiveFingers"
79
- post1.url = URI.parse('http://www.vibramfivefingers.it/')
80
-
81
- delicious = stub :delicious, :posts_recent => [post1]
82
-
83
- WWW::Delicious.should_receive(:new).and_return delicious
84
- end
85
- it "should yield each line" do
86
- @source.get_data do |uid, data|
87
- uid.should == 1
88
- data.should == { :title => "VIBRAM - FiveFingers", :tags => "barefoot running shoe", :url => "http://www.vibramfivefingers.it/" }
89
- end
90
- end
91
- end
92
- end
93
-
94
- end