picky 4.0.0pre1 → 4.0.0pre2

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 (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,63 +0,0 @@
1
- module Picky
2
-
3
- module Sources
4
-
5
- # Describes a Delicious (http://deli.cio.us) source.
6
- #
7
- # This source has a fixed set of categories:
8
- # * title
9
- # * tags
10
- # * url
11
- #
12
- # Examples:
13
- # Sources::CSV.new('usrnam', 'paswrd')
14
- #
15
- class Delicious < Base
16
-
17
- def initialize username, password
18
- check_gem
19
- @username = username
20
- @password = password
21
- end
22
- def check_gem # :nodoc:
23
- require 'www/delicious'
24
- rescue LoadError
25
- warn_gem_missing 'www-delicious', 'the delicious source'
26
- exit 1
27
- end
28
-
29
- def to_s
30
- "#{self.class.name}(#{@username})"
31
- end
32
-
33
- # Harvests the data to index.
34
- #
35
- def harvest category
36
- get_data do |indexed_id, data|
37
- text = data[category.from]
38
- next unless text
39
- yield indexed_id, text
40
- end
41
- end
42
-
43
- #
44
- #
45
- def get_data # :nodoc:
46
- @generated_id ||= 0
47
- @posts ||= WWW::Delicious.new(@username, @password).posts_recent(count: 100)
48
- @posts.each do |post|
49
- data = {
50
- title: post.title,
51
- tags: post.tags.join(' '),
52
- url: post.url.to_s
53
- }
54
- @generated_id += 1
55
- yield @generated_id, data
56
- end
57
- end
58
-
59
- end
60
-
61
- end
62
-
63
- end
@@ -1,80 +0,0 @@
1
- module Picky
2
-
3
- module Sources
4
-
5
- # Important note: We're not sure if this works already.
6
- #
7
- # A Mongo database source.
8
- #
9
- # Options:
10
- # * url, db
11
- # Example:
12
- # Sources::Mongo.new(:collection1, :collection2, :url => 'localhost:28017', :db => 'testdatabase')
13
- # Be sure to escape the URL properly, e.g. # => %23 in the databasename if needed
14
- #
15
- # and all the options of a <tt>RestClient::Resource</tt>.
16
- # See http://github.com/archiloque/rest-client.
17
- #
18
- class Mongo < Base
19
-
20
- # Raised when a Mongo source is instantiated without a valid uri.
21
- #
22
- # Important!
23
- # You have to start your mongodb with --rest in order to use
24
- # the rest / http interface
25
- #
26
- class NoDBGiven < StandardError; end
27
-
28
- @@id_key = '_id'
29
- #
30
- #
31
- def initialize *category_names, options
32
- check_gem
33
-
34
- unless options[:url] && options[:db]
35
- raise_no_db_given(category_names)
36
- end
37
-
38
- @db = RestClient::Resource.new options.delete(:url), options
39
- @database = options.delete(:db)
40
- @key_format = options[:key_format] && options[:key_format].intern || :to_s
41
- end
42
-
43
- # Tries to require the rest_client gem.
44
- #
45
- def check_gem # :nodoc:
46
- require 'rest_client'
47
- rescue LoadError
48
- warn_gem_missing 'rest-client', 'the MongoDB source'
49
- exit 1
50
- end
51
-
52
- # Fetches the data, @limit=0 will return all records
53
- #
54
- # Limit is set to 0 by default - all collection entries will be send
55
- # If want to limit the results, set to to any other number, e.g. limit=15
56
- # to return only 15 entries
57
- #
58
- def harvest category
59
- collection = (category.from || category.index_name).to_s
60
- resp = @db["/#{@database}/#{category.index_name}/?@limit=0"].get
61
- JSON.parse(resp)['rows'].each do |row|
62
- text = row[collection].to_s
63
- next unless text
64
- index_key = row.delete @@id_key # Note: I removed .values
65
- yield index_key, text
66
- end
67
- end
68
-
69
- def raise_no_db_given category_names # :nodoc:
70
- raise NoDBGiven.new(category_names.join(', '))
71
- end
72
-
73
- def to_s
74
- self.class.name
75
- end
76
-
77
- end
78
- end
79
-
80
- end
@@ -1,38 +0,0 @@
1
- module Picky
2
- module Wrappers
3
- module Category
4
-
5
- module Location
6
-
7
- # THINK Is this the best way to do this?
8
- #
9
- def self.wrap category, grid, precision = 1, anchor = 0.0
10
- wrapped_exact = Wrappers::Bundle::Location.new category.exact, grid: grid, precision: precision, anchor: anchor
11
-
12
- category.class_eval do
13
-
14
- # Uses a basic tokenizer.
15
- #
16
- def tokenizer
17
- @tokenizer ||= Tokenizer.new
18
- end
19
-
20
- # Both use the exact index.
21
- #
22
- # TODO Necessary to wrap?
23
- #
24
- define_method :exact do
25
- wrapped_exact
26
- end
27
- define_method :partial do
28
- wrapped_exact
29
- end
30
-
31
- end
32
- end
33
-
34
- end
35
-
36
- end
37
- end
38
- end
@@ -1,8 +0,0 @@
1
- # Routing tasks.
2
- #
3
- desc "Shows the available URL paths."
4
- task :routes => :application do
5
- Picky::Application.apps.each do |app|
6
- puts app.to_routes
7
- end
8
- end
@@ -1,24 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- require 'spec_helper'
4
-
5
- describe Picky::Adapters::Rack::Base do
6
-
7
- before(:each) do
8
- @adapter = described_class.new
9
- end
10
-
11
- describe 'respond_with' do
12
- describe 'by default' do
13
- it 'uses json' do
14
- @adapter.respond_with('response').should ==
15
- [200, { 'Content-Type' => 'application/json', 'Content-Length' => '8' }, ['response']]
16
- end
17
- end
18
- it 'adapts the content length' do
19
- @adapter.respond_with('123').should ==
20
- [200, { 'Content-Type' => 'application/json', 'Content-Length' => '3' }, ['123']]
21
- end
22
- end
23
-
24
- end
@@ -1,26 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- require 'spec_helper'
4
-
5
- describe Picky::Adapters::Rack::LiveParameters do
6
-
7
- let(:live_parameters) { stub :live_parameters }
8
- let(:adapter) { described_class.new live_parameters }
9
-
10
- describe 'to_app' do
11
- it 'works' do
12
- lambda { adapter.to_app }.should_not raise_error
13
- end
14
- it 'returns the right thing' do
15
- adapter.to_app.should respond_to(:call)
16
- end
17
- it 'returned lambda should call parameters on the live parameters' do
18
- env = { 'rack.input' => 'some input' }
19
-
20
- live_parameters.should_receive(:parameters).once.with({}).and_return Hash.new
21
-
22
- adapter.to_app.call env
23
- end
24
- end
25
-
26
- end
@@ -1,39 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- require 'spec_helper'
4
-
5
- describe Picky::Adapters::Rack::Search do
6
-
7
- before(:each) do
8
- @query = stub :query
9
- @adapter = described_class.new @query
10
- end
11
-
12
- describe 'to_app' do
13
- it 'works' do
14
- lambda { @adapter.to_app }.should_not raise_error
15
- end
16
- it 'returns the right thing' do
17
- @adapter.to_app.should respond_to(:call)
18
- end
19
- end
20
-
21
- describe 'extracted' do
22
- it 'extracts the query' do
23
- @adapter.extracted('query' => 'some_query')[0].should == 'some_query'
24
- end
25
- it 'extracts the default ids amount' do
26
- @adapter.extracted('query' => 'some_query')[1].should == 20
27
- end
28
- it 'extracts the default offset' do
29
- @adapter.extracted('query' => 'some_query')[2].should == 0
30
- end
31
- it 'extracts a given ids amount' do
32
- @adapter.extracted('query' => 'some_query', 'ids' => '123')[1].should == 123
33
- end
34
- it 'extracts a given offset' do
35
- @adapter.extracted('query' => 'some_query', 'offset' => '123')[2].should == 123
36
- end
37
- end
38
-
39
- end
@@ -1,155 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- require 'spec_helper'
4
-
5
- describe Picky::Application do
6
-
7
- describe "integration" do
8
- it "should run ok" do
9
- lambda {
10
- class MinimalTestApplication < described_class
11
- books = Picky::Index.new :books do
12
- source Picky::Sources::DB.new(
13
- 'SELECT id, title FROM books',
14
- :file => 'app/db.yml'
15
- )
16
- end
17
- books.category :title
18
-
19
- rack_adapter.stub! :exclaim # Stopping it from exclaiming.
20
-
21
- route %r{^/books} => Picky::Search.new(books)
22
- end
23
- Picky::Tokenizer.index_default.tokenize 'some text'
24
- Picky::Tokenizer.query_default.tokenize 'some text'
25
- }.should_not raise_error
26
- end
27
- it "should run ok" do
28
- lambda {
29
- # Here we just test if the API can be called ok.
30
- #
31
- class TestApplication < described_class
32
- indexing removes_characters: /[^a-zA-Z0-9\s\/\-\"\&\.]/,
33
- stopwords: /\b(and|the|of|it|in|for)\b/,
34
- splits_text_on: /[\s\/\-\"\&\.]/,
35
- removes_characters_after_splitting: /[\.]/,
36
- normalizes_words: [[/\$(\w+)/i, '\1 dollars']],
37
- rejects_token_if: lambda { |token| token.blank? || token == :amistad }
38
-
39
- searching removes_characters: /[^a-zA-Z0-9äöü\s\/\-\,\&\"\~\*\:]/,
40
- stopwords: /\b(and|the|of|it|in|for)\b/,
41
- splits_text_on: /[\s\/\-\,\&]+/,
42
- normalizes_words: [[/Deoxyribonucleic Acid/i, 'DNA']],
43
-
44
- substitutes_characters_with: Picky::CharacterSubstituters::WestEuropean.new,
45
- maximum_tokens: 5
46
-
47
- books_index = Picky::Index.new :books do
48
- source Picky::Sources::DB.new(
49
- 'SELECT id, title, author, isbn13 as isbn FROM books',
50
- :file => 'app/db.yml'
51
- )
52
- end
53
-
54
- books_index.category :title,
55
- similarity: Picky::Similarity::DoubleMetaphone.new(3) # Up to three similar title word indexed.
56
- books_index.category :author,
57
- similarity: Picky::Similarity::Soundex.new(2)
58
- books_index.category :isbn,
59
- partial: Picky::Partial::None.new # Partially searching on an ISBN makes not much sense.
60
-
61
- geo_index = Picky::Index.new :geo do
62
- source Picky::Sources::CSV.new(:location, :north, :east, file: 'data/ch.csv', col_sep: ',')
63
- indexing removes_characters: /[^a-z]/
64
- category :location,
65
- similarity: Picky::Similarity::Metaphone.new(4)
66
- ranged_category :north1, 1, precision: 3, from: :north
67
- ranged_category :east1, 1, precision: 3, from: :east
68
- end
69
-
70
- rack_adapter.stub! :exclaim # Stopping it from exclaiming.
71
-
72
- route %r{^/books} => Picky::Search.new(books_index)
73
-
74
- buks_search = Picky::Search.new(books_index) do
75
- searching removes_characters: /[buks]/
76
- ignore :author
77
- end
78
- route %r{^/buks} => buks_search
79
- end
80
- }.should_not raise_error
81
- end
82
- end
83
-
84
- describe 'finalize' do
85
- before(:each) do
86
- described_class.stub! :check
87
- end
88
- it 'checks if all is ok' do
89
- described_class.should_receive(:check).once.with
90
-
91
- described_class.finalize
92
- end
93
- it 'tells the rack adapter to finalize' do
94
- described_class.rack_adapter.should_receive(:finalize).once.with
95
-
96
- described_class.finalize
97
- end
98
- end
99
-
100
- describe 'check' do
101
- it 'does something' do
102
- described_class.should_receive(:warn).once.with "\nWARNING: No routes defined for application configuration in Class.\n\n"
103
-
104
- described_class.check
105
- end
106
- end
107
-
108
- describe 'delegation' do
109
- it "should delegate route" do
110
- described_class.rack_adapter.should_receive(:route).once.with :path => :query
111
-
112
- described_class.route :path => :query
113
- end
114
- end
115
-
116
- describe 'rack_adapter' do
117
- it 'should be there' do
118
- lambda { described_class.rack_adapter }.should_not raise_error
119
- end
120
- it "should return a new FrontendAdapters::Rack instance" do
121
- described_class.rack_adapter.should be_kind_of(Picky::FrontendAdapters::Rack)
122
- end
123
- it "should cache the instance" do
124
- described_class.rack_adapter.should == described_class.rack_adapter
125
- end
126
- end
127
-
128
- describe 'route' do
129
- it 'is delegated' do
130
- described_class.rack_adapter.should_receive(:route).once.with :some_options
131
-
132
- described_class.route(:some_options)
133
- end
134
- it 'raises on block' do
135
- expect {
136
- described_class.route :quack => Hash.new do # Anything with a block.
137
- # do something
138
- end
139
- }.to raise_error("Warning: block passed into #route method, not into Search.new!")
140
- end
141
- end
142
-
143
- describe 'call' do
144
- before(:each) do
145
- @routes = stub :routes
146
- described_class.stub! :rack_adapter => @routes
147
- end
148
- it 'should delegate' do
149
- @routes.should_receive(:call).once.with :env
150
-
151
- described_class.call :env
152
- end
153
- end
154
-
155
- end
@@ -1,294 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- require 'spec_helper'
4
-
5
- describe Picky::FrontendAdapters::Rack do
6
-
7
- before(:each) do
8
- @rack_adapter = described_class.new
9
- @rack_adapter.stub! :exclaim
10
- end
11
-
12
- def rack_defaults_for url
13
- url, query_string = url.split ??
14
-
15
- { "GATEWAY_INTERFACE"=>"CGI/1.1",
16
- "PATH_INFO"=>"#{url}",
17
- "QUERY_STRING"=>"#{query_string}",
18
- "REMOTE_ADDR"=>"127.0.0.1",
19
- "REMOTE_HOST"=>"localhost",
20
- "REQUEST_METHOD"=>"GET",
21
- "REQUEST_URI"=>"http://localhost:3001#{url}",
22
- "SCRIPT_NAME"=>"",
23
- "SERVER_NAME"=>"localhost",
24
- "SERVER_PORT"=>"3001",
25
- "SERVER_PROTOCOL"=>"HTTP/1.1",
26
- "SERVER_SOFTWARE"=>"WEBrick/1.3.1 (Ruby/1.9.2/2010-07-11)",
27
- "HTTP_HOST"=>"localhost:3001",
28
- "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-us) AppleWebKit/533.16 (KHTML like Gecko) Version/5.0 Safari/533.16",
29
- "HTTP_ACCEPT"=>"application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
30
- "HTTP_CACHE_CONTROL"=>"max-age=0",
31
- "HTTP_ACCEPT_LANGUAGE"=>"en-us",
32
- "HTTP_ACCEPT_ENCODING"=>"gzip,
33
- deflate",
34
- "HTTP_COOKIE"=>"__utma=111872281.1536032598.1255697925.1255697925.1255697925.1; _jsuid=8971917605087477351; locale=de",
35
- "HTTP_CONNECTION"=>"keep-alive",
36
- "rack.input"=>'' }
37
- end
38
-
39
- context 'empty?' do
40
- context 'no routes' do
41
- before(:each) do
42
- @rack_adapter.reset_routes
43
- end
44
- it 'returns the right answer' do
45
- @rack_adapter.empty?.should == true
46
- end
47
- end
48
- context 'with routes' do
49
- before(:each) do
50
- @rack_adapter.route %r{something} => Picky::Search.new
51
- end
52
- it 'returns the right answer' do
53
- @rack_adapter.empty?.should == false
54
- end
55
- describe 'to_s' do
56
- it 'outputs correctly' do
57
- @rack_adapter.to_s.should == "Note: Anchored (✓) regexps are faster, e.g. /\\A.*\\Z/ or /^.*$/.\n\n something => Picky::Search(weights: Picky::Query::Weights({}))"
58
- end
59
- end
60
- end
61
- end
62
-
63
- context 'real routes' do
64
- before(:each) do
65
- @rack_adapter.reset_routes
66
- Picky.logger.stub! :info
67
- end
68
- it 'should route correctly' do
69
- env = {}
70
-
71
- @rack_adapter.routes.freeze
72
- @rack_adapter.call(env).should == [404, {"Content-Type" => "text/html", "X-Cascade" => "pass"}, ["Not Found"]]
73
- end
74
- it 'should route correctly' do
75
- env = rack_defaults_for '/'
76
-
77
- @rack_adapter.root 200
78
-
79
- @rack_adapter.routes.freeze
80
- @rack_adapter.call(env).should == [200, {"Content-Type"=>"text/html", "Content-Length"=>"0"}, ['']]
81
- end
82
- it 'should route correctly' do
83
- env = rack_defaults_for '/blarf'
84
-
85
- @rack_adapter.default 200
86
-
87
- @rack_adapter.routes.freeze
88
- @rack_adapter.call(env).should == [200, {"Content-Type"=>"text/html", "Content-Length"=>"0"}, ['']]
89
- end
90
- it 'should route correctly' do
91
- env = rack_defaults_for '/gurk'
92
-
93
- @rack_adapter.answer %r{/gurk}, lambda { |env| [333, {}, ['this is gurk']] }
94
-
95
- @rack_adapter.routes.freeze
96
- @rack_adapter.call(env).should == [333, {}, ['this is gurk']]
97
- end
98
- it 'should route correctly' do
99
- env = rack_defaults_for '/gurk'
100
-
101
- @rack_adapter.answer '/gurk', lambda { |env| [333, {}, ['this is gurk']] }
102
-
103
- @rack_adapter.routes.freeze
104
- @rack_adapter.call(env).should == [333, {}, ['this is gurk']]
105
- end
106
- it 'should route correctly' do
107
- env = rack_defaults_for '/searches/some_route?query=some_query'
108
-
109
- search = stub :search
110
- search.should_receive(:search).once.with(anything, 20, 0).and_return(Picky::Results.new)
111
- Picky::Search.stub! :new => search
112
-
113
- @rack_adapter.route '/searches/some_route' => Picky::Search.new(:some_index, :some_other_index)
114
-
115
- @rack_adapter.routes.freeze
116
- @rack_adapter.call(env).should == [200, {"Content-Type"=>"application/json", "Content-Length"=>"52"}, ["{\"allocations\":[],\"offset\":0,\"duration\":0,\"total\":0}"]]
117
- end
118
- it 'should route correctly' do
119
- env = rack_defaults_for '/searches/some_route?query=some_query&type=some_type'
120
-
121
- search = stub :search
122
- search.should_receive(:search).once.with(anything, 20, 0).and_return(Picky::Results.new)
123
- Picky::Search.stub! :new => search
124
-
125
- @rack_adapter.route '/searches/some_route' => Picky::Search.new(:some_index, :some_other_index), :query => { :type => :some_type }
126
-
127
- @rack_adapter.routes.freeze
128
- @rack_adapter.call(env).should == [200, {"Content-Type"=>"application/json", "Content-Length"=>"52"}, ["{\"allocations\":[],\"offset\":0,\"duration\":0,\"total\":0}"]]
129
- end
130
- it 'should route correctly' do
131
- env = rack_defaults_for '/searches/some_wrong_route?query=some_query'
132
-
133
- search = stub :search
134
- search.should_receive(:search).never
135
- Picky::Search.stub! :new => search
136
-
137
- @rack_adapter.route '/searches/some_route' => Picky::Search.new(:some_index, :some_other_index)
138
-
139
- @rack_adapter.routes.freeze
140
- @rack_adapter.call(env).should == [404, {"Content-Type"=>"text/html", "X-Cascade"=>"pass"}, ["Not Found"]]
141
- end
142
- end
143
-
144
- describe 'to_s' do
145
- context 'no routes' do
146
- it 'outputs correctly' do
147
- @rack_adapter.to_s.should == "Note: Anchored (✓) regexps are faster, e.g. /\\A.*\\Z/ or /^.*$/.\n\n"
148
- end
149
- end
150
- end
151
-
152
- context 'stubbed routes' do
153
- before(:each) do
154
- @routes = stub :routes
155
- @rack_adapter.stub! :routes => @routes
156
- end
157
-
158
- describe 'generate_query_string' do
159
- it 'should not allow an empty query condition' do
160
- lambda {
161
- @rack_adapter.generate_query_string({}).should == 'this=must_be'
162
- }.should raise_error "At least one query string condition is needed."
163
- end
164
- it 'should handle a single condition' do
165
- @rack_adapter.generate_query_string(:this => :must_be).should == 'this=must_be'
166
- end
167
- it 'should not allow multiple query strings' do
168
- lambda {
169
- @rack_adapter.generate_query_string(:this => :must_be, :that => :should_be).should == 'this=must_be|that=should_be'
170
- }.should raise_error "Too many query param conditions (only 1 allowed): {:this=>:must_be, :that=>:should_be}"
171
- end
172
- it 'should be sanity checked' do
173
- '/searches/some_route?query=some_query&type=some_type'.should match(%r{#{"type=some_type"}})
174
- end
175
- end
176
-
177
- describe "route" do
178
- it "should delegate correctly" do
179
- @rack_adapter.should_receive(:route_one).once.with %r{regexp1}, :query1, {}
180
- @rack_adapter.should_receive(:route_one).once.with %r{regexp2}, :query2, {}
181
-
182
- @rack_adapter.route %r{regexp1} => :query1, %r{regexp2} => :query2
183
- end
184
- it "should split options correctly" do
185
- @rack_adapter.should_receive(:route_one).once.with %r{regexp1}, :query1, :some => :option
186
- @rack_adapter.should_receive(:route_one).once.with %r{regexp2}, :query2, :some => :option
187
-
188
- @rack_adapter.route %r{regexp1} => :query1, %r{regexp2} => :query2, :some => :option
189
- end
190
- it 'does not accept nil queries' do
191
- lambda { @rack_adapter.route %r{some/regexp} => nil }.should raise_error(Picky::FrontendAdapters::Rack::RouteTargetNilError, /Routing for \/some\\\/regexp\/ was defined with a nil target object, i.e. \/some\\\/regexp\/ => nil./)
192
- end
193
- end
194
-
195
- describe 'finalize' do
196
- before(:each) do
197
- @rack_adapter.routes.should_receive(:freeze).once.with
198
-
199
- @rack_adapter.finalize
200
- end
201
- end
202
-
203
- describe 'route_one' do
204
- before(:each) do
205
- Picky::Adapters::Rack.stub! :app_for => :some_query_app
206
- end
207
- it 'should add the right route' do
208
- @routes.should_receive(:add_route).once.with :some_query_app, { :request_method => "GET", :path_info => /some_url/ }, {}, "some_query"
209
-
210
- @rack_adapter.route_one %r{some_url}, :some_query, {}
211
- end
212
- it 'should add the right route' do
213
- @routes.should_receive(:add_route).once.with :some_query_app, { :request_method => "GET", :path_info => /some_url/ }, {}, "some_query"
214
-
215
- @rack_adapter.route_one 'some_url', :some_query, {}
216
- end
217
- it 'should add the right route' do
218
- @routes.should_receive(:add_route).once.with :some_query_app, { :request_method => "GET", :glarf => :blarf, :path_info => /some_url/ }, {}, "some_query"
219
-
220
- @rack_adapter.route_one 'some_url', :some_query, { :glarf => :blarf }
221
- end
222
- end
223
-
224
- describe 'default' do
225
- it 'should call answer' do
226
- @rack_adapter.should_receive(:answer).once.with nil, Picky::FrontendAdapters::Rack::STATUSES[200]
227
-
228
- @rack_adapter.default 200
229
- end
230
- end
231
-
232
- describe 'STATUSES' do
233
- it 'is a lambda' do
234
- Picky::FrontendAdapters::Rack::STATUSES[200].respond_to?(:call).should == true
235
- end
236
- it 'is a lambda' do
237
- Picky::FrontendAdapters::Rack::STATUSES[404].respond_to?(:call).should == true
238
- end
239
- end
240
-
241
- describe 'root' do
242
- it 'should call answer' do
243
- @rack_adapter.should_receive(:answer).once.with %r{^/$}, Picky::FrontendAdapters::Rack::STATUSES[200]
244
-
245
- @rack_adapter.root 200
246
- end
247
- it 'should call answer' do
248
- @rack_adapter.should_receive(:answer).once.with %r{^/$}, Picky::FrontendAdapters::Rack::STATUSES[404]
249
-
250
- @rack_adapter.root 404
251
- end
252
- end
253
-
254
- describe 'answer' do
255
- context 'with app' do
256
- before(:each) do
257
- @app = stub :app
258
- end
259
- context 'with url' do
260
- it 'should use the app with default_options from the url' do
261
- @routes.should_receive(:add_route).once.with @app, { :request_method => "GET", :path_info => /some_url/ }
262
-
263
- @rack_adapter.answer 'some_url', @app
264
- end
265
- end
266
- context 'without url' do
267
- it 'should use the app with default_options' do
268
- @routes.should_receive(:add_route).once.with @app, { :request_method => "GET" }
269
-
270
- @rack_adapter.answer nil, @app
271
- end
272
- end
273
- end
274
- context 'without app' do
275
- context 'with url' do
276
- it 'should use the 200 with default_options from the url' do
277
- @routes.should_receive(:add_route).once.with Picky::FrontendAdapters::Rack::STATUSES[200], { :request_method => "GET", :path_info => /some_url/ }
278
-
279
- @rack_adapter.answer 'some_url'
280
- end
281
- end
282
- context 'without url' do
283
- it 'should use the 200 with default_options' do
284
- @routes.should_receive(:add_route).once.with Picky::FrontendAdapters::Rack::STATUSES[200], { :request_method => "GET" }
285
-
286
- @rack_adapter.answer
287
- end
288
- end
289
- end
290
- end
291
-
292
- end
293
-
294
- end