picky 4.0.0pre1 → 4.0.0pre2
Sign up to get free protection for your applications and to get access to all the features.
- data/aux/picky/cli.rb +6 -2
- data/lib/picky.rb +10 -8
- data/lib/picky/backends/backend.rb +37 -0
- data/lib/picky/backends/file.rb +0 -20
- data/lib/picky/backends/memory.rb +0 -29
- data/lib/picky/backends/redis.rb +74 -15
- data/lib/picky/backends/redis/list.rb +1 -1
- data/lib/picky/backends/sqlite.rb +0 -27
- data/lib/picky/bundle.rb +2 -2
- data/lib/picky/bundle_indexed.rb +1 -1
- data/lib/picky/bundle_indexing.rb +1 -1
- data/lib/picky/categories_indexed.rb +1 -11
- data/lib/picky/category.rb +4 -4
- data/lib/picky/category/location.rb +25 -0
- data/lib/picky/category_realtime.rb +4 -3
- data/lib/picky/console.rb +1 -1
- data/lib/picky/constants.rb +1 -1
- data/lib/picky/ext/maybe_compile.rb +2 -2
- data/lib/picky/extensions/object.rb +3 -2
- data/lib/picky/generators/aliases.rb +7 -2
- data/lib/picky/generators/partial/default.rb +1 -0
- data/lib/picky/generators/similarity/default.rb +1 -0
- data/lib/picky/generators/similarity/phonetic.rb +13 -2
- data/lib/picky/generators/strategy.rb +0 -2
- data/lib/picky/generators/weights/constant.rb +1 -2
- data/lib/picky/generators/weights/default.rb +1 -0
- data/lib/picky/generators/weights/dynamic.rb +1 -1
- data/lib/picky/generators/weights/logarithmic.rb +1 -1
- data/lib/picky/generators/weights/{runtime.rb → stub.rb} +1 -3
- data/lib/picky/index.rb +3 -3
- data/lib/picky/index_indexing.rb +0 -2
- data/lib/picky/index_realtime.rb +1 -1
- data/lib/picky/indexers/base.rb +7 -0
- data/lib/picky/indexers/parallel.rb +2 -4
- data/lib/picky/indexers/serial.rb +2 -0
- data/lib/picky/indexes_indexing.rb +1 -1
- data/lib/picky/interfaces/live_parameters/master_child.rb +175 -0
- data/lib/picky/interfaces/live_parameters/unicorn.rb +37 -0
- data/lib/picky/loader.rb +238 -259
- data/lib/picky/query/allocation.rb +19 -10
- data/lib/picky/query/combination.rb +7 -1
- data/lib/picky/query/combinations.rb +1 -6
- data/lib/picky/query/token.rb +26 -36
- data/lib/picky/results.rb +18 -17
- data/lib/picky/scheduler.rb +2 -1
- data/lib/picky/search.rb +1 -1
- data/lib/picky/sinatra.rb +6 -6
- data/lib/picky/statistics.rb +2 -0
- data/lib/picky/tokenizer.rb +8 -8
- data/lib/picky/wrappers/bundle/calculation.rb +4 -4
- data/lib/picky/wrappers/bundle/location.rb +1 -2
- data/lib/tasks/framework.rake +1 -1
- data/lib/tasks/statistics.rake +1 -1
- data/lib/tasks/try.rake +1 -1
- data/lib/tasks/try.rb +1 -1
- data/spec/aux/picky/cli_spec.rb +12 -12
- data/spec/ext/performant_spec.rb +16 -16
- data/spec/functional/backends/file_spec.rb +78 -7
- data/spec/functional/backends/memory_spec.rb +78 -7
- data/spec/functional/backends/redis_spec.rb +73 -13
- data/spec/functional/dynamic_weights_spec.rb +3 -4
- data/spec/functional/realtime_spec.rb +2 -2
- data/spec/functional/speed_spec.rb +2 -2
- data/spec/functional/terminate_early_spec.rb +3 -3
- data/spec/lib/analytics_spec.rb +1 -1
- data/spec/lib/analyzer_spec.rb +5 -3
- data/spec/lib/categories_indexed_spec.rb +38 -20
- data/spec/lib/category/location_spec.rb +30 -0
- data/spec/lib/character_substituters/west_european_spec.rb +1 -0
- data/spec/lib/extensions/hash_spec.rb +6 -5
- data/spec/lib/extensions/module_spec.rb +6 -6
- data/spec/lib/extensions/object_spec.rb +9 -8
- data/spec/lib/extensions/string_spec.rb +1 -1
- data/spec/lib/generators/similarity/phonetic_spec.rb +11 -0
- data/spec/lib/index_realtime_spec.rb +5 -5
- data/spec/lib/interfaces/{live_parameters_spec.rb → live_parameters/master_child_spec.rb} +26 -26
- data/spec/lib/interfaces/live_parameters/unicorn_spec.rb +160 -0
- data/spec/lib/loader_spec.rb +65 -25
- data/spec/lib/query/allocation_spec.rb +25 -22
- data/spec/lib/query/combinations_spec.rb +13 -36
- data/spec/lib/query/token_spec.rb +144 -131
- data/spec/lib/query/tokens_spec.rb +14 -0
- data/spec/lib/results_spec.rb +14 -8
- data/spec/lib/search_spec.rb +1 -1
- data/spec/lib/sinatra_spec.rb +8 -8
- metadata +28 -91
- data/lib/picky/adapters/rack.rb +0 -34
- data/lib/picky/adapters/rack/base.rb +0 -27
- data/lib/picky/adapters/rack/live_parameters.rb +0 -37
- data/lib/picky/adapters/rack/search.rb +0 -67
- data/lib/picky/application.rb +0 -268
- data/lib/picky/frontend_adapters/rack.rb +0 -161
- data/lib/picky/interfaces/live_parameters.rb +0 -187
- data/lib/picky/sources/base.rb +0 -92
- data/lib/picky/sources/couch.rb +0 -76
- data/lib/picky/sources/csv.rb +0 -83
- data/lib/picky/sources/db.rb +0 -189
- data/lib/picky/sources/delicious.rb +0 -63
- data/lib/picky/sources/mongo.rb +0 -80
- data/lib/picky/wrappers/category/location.rb +0 -38
- data/lib/tasks/routes.rake +0 -8
- data/spec/lib/adapters/rack/base_spec.rb +0 -24
- data/spec/lib/adapters/rack/live_parameters_spec.rb +0 -26
- data/spec/lib/adapters/rack/query_spec.rb +0 -39
- data/spec/lib/application_spec.rb +0 -155
- data/spec/lib/frontend_adapters/rack_spec.rb +0 -294
- data/spec/lib/sources/base_spec.rb +0 -53
- data/spec/lib/sources/couch_spec.rb +0 -114
- data/spec/lib/sources/csv_spec.rb +0 -89
- data/spec/lib/sources/db_spec.rb +0 -125
- data/spec/lib/sources/delicious_spec.rb +0 -94
- 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
|
data/lib/picky/sources/mongo.rb
DELETED
@@ -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
|
data/lib/tasks/routes.rake
DELETED
@@ -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
|