picky 1.2.4 → 1.3.0
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.
- data/lib/picky/adapters/rack/base.rb +23 -0
- data/lib/picky/adapters/rack/live_parameters.rb +33 -0
- data/lib/picky/adapters/rack/query.rb +59 -0
- data/lib/picky/adapters/rack.rb +28 -0
- data/lib/picky/alias_instances.rb +2 -0
- data/lib/picky/application.rb +9 -8
- data/lib/picky/cli.rb +25 -3
- data/lib/picky/frontend_adapters/rack.rb +150 -0
- data/lib/picky/helpers/measuring.rb +0 -2
- data/lib/picky/index_api.rb +1 -1
- data/lib/picky/indexed/categories.rb +51 -14
- data/lib/picky/indexers/solr.rb +1 -5
- data/lib/picky/indexing/indexes.rb +6 -0
- data/lib/picky/interfaces/live_parameters.rb +165 -0
- data/lib/picky/loader.rb +13 -2
- data/lib/picky/query/base.rb +15 -18
- data/lib/picky/query/combination.rb +2 -2
- data/lib/picky/query/solr.rb +0 -17
- data/lib/picky/query/token.rb +14 -27
- data/lib/picky/query/weights.rb +13 -1
- data/lib/picky/results/base.rb +9 -2
- data/spec/lib/adapters/rack/base_spec.rb +24 -0
- data/spec/lib/adapters/rack/live_parameters_spec.rb +21 -0
- data/spec/lib/adapters/rack/query_spec.rb +33 -0
- data/spec/lib/application_spec.rb +27 -8
- data/spec/lib/cli_spec.rb +9 -0
- data/spec/lib/extensions/symbol_spec.rb +1 -3
- data/spec/lib/{routing_spec.rb → frontend_adapters/rack_spec.rb} +69 -66
- data/spec/lib/indexed/categories_spec.rb +24 -0
- data/spec/lib/interfaces/live_parameters_spec.rb +138 -0
- data/spec/lib/query/base_spec.rb +10 -14
- data/spec/lib/query/live_spec.rb +1 -30
- data/spec/lib/query/token_spec.rb +72 -5
- data/spec/lib/query/weights_spec.rb +59 -36
- data/spec/lib/results/base_spec.rb +13 -1
- metadata +20 -7
- data/lib/picky/routing.rb +0 -171
@@ -0,0 +1,165 @@
|
|
1
|
+
# This is very optional.
|
2
|
+
# Only load if the user wants it.
|
3
|
+
#
|
4
|
+
module Interfaces
|
5
|
+
# This is an interface that provides the user of
|
6
|
+
# Picky with the possibility to change parameters
|
7
|
+
# while the Application is running.
|
8
|
+
#
|
9
|
+
# Important Note: This will only work in Master/Child configurations.
|
10
|
+
#
|
11
|
+
class LiveParameters
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@child, @parent = IO.pipe
|
15
|
+
start_master_process_thread
|
16
|
+
end
|
17
|
+
|
18
|
+
# This runs a thread that listens to child processes.
|
19
|
+
#
|
20
|
+
def start_master_process_thread
|
21
|
+
# This thread is stopped in the children.
|
22
|
+
#
|
23
|
+
Thread.new do
|
24
|
+
loop do
|
25
|
+
sleep 1 # TODO select
|
26
|
+
result = @child.gets ';;;'
|
27
|
+
pid, configuration_hash = eval result
|
28
|
+
next unless Hash === configuration_hash
|
29
|
+
next if configuration_hash.empty?
|
30
|
+
exclaim "Trying to update MASTER configuration."
|
31
|
+
try_updating_configuration_with configuration_hash
|
32
|
+
kill_each_worker_except pid
|
33
|
+
# TODO rescue on error.
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# TODO This needs to be webserver agnostic.
|
40
|
+
#
|
41
|
+
def worker_pids
|
42
|
+
Unicorn::HttpServer::WORKERS.keys
|
43
|
+
end
|
44
|
+
|
45
|
+
# Taken from Unicorn.
|
46
|
+
#
|
47
|
+
def kill_each_worker_except pid
|
48
|
+
worker_pids.each do |wpid|
|
49
|
+
next if wpid == pid
|
50
|
+
kill_worker :KILL, wpid
|
51
|
+
end
|
52
|
+
end
|
53
|
+
def kill_worker signal, wpid
|
54
|
+
Process.kill signal, wpid
|
55
|
+
exclaim "Killing worker ##{wpid} with signal #{signal}."
|
56
|
+
rescue Errno::ESRCH
|
57
|
+
remove_worker wpid
|
58
|
+
end
|
59
|
+
# TODO This needs to be Webserver agnostic.
|
60
|
+
#
|
61
|
+
def remove_worker wpid
|
62
|
+
worker = Unicorn::HttpServer::WORKERS.delete(wpid) and worker.tmp.close rescue nil
|
63
|
+
end
|
64
|
+
|
65
|
+
# Updates any parameters with the ones given and
|
66
|
+
# returns the updated params.
|
67
|
+
#
|
68
|
+
# The params are a strictly defined hash of:
|
69
|
+
# * querying_removes_characters: Regexp
|
70
|
+
# * querying_stopwords: Regexp
|
71
|
+
# TODO etc.
|
72
|
+
#
|
73
|
+
# This first tries to update in the child process,
|
74
|
+
# and if successful, in the parent process
|
75
|
+
#
|
76
|
+
def parameters configuration_hash
|
77
|
+
close_child
|
78
|
+
exclaim "Trying to update worker child configuration." unless configuration_hash.empty?
|
79
|
+
try_updating_configuration_with configuration_hash
|
80
|
+
write_parent configuration_hash
|
81
|
+
extract_configuration
|
82
|
+
rescue CouldNotUpdateConfigurationError => e
|
83
|
+
# I need to die such that my broken config is never used.
|
84
|
+
#
|
85
|
+
exclaim "Child process #{Process.pid} performs harakiri because of broken config."
|
86
|
+
harakiri
|
87
|
+
{ e.config_key => :ERROR }
|
88
|
+
end
|
89
|
+
# Kills itself, but still answering the request honorably.
|
90
|
+
#
|
91
|
+
def harakiri
|
92
|
+
Process.kill :QUIT, Process.pid
|
93
|
+
end
|
94
|
+
# Write the parent.
|
95
|
+
#
|
96
|
+
# Note: The ;;; is the end marker for the message.
|
97
|
+
#
|
98
|
+
def write_parent configuration_hash
|
99
|
+
@parent.write "#{[Process.pid, configuration_hash]};;;"
|
100
|
+
end
|
101
|
+
# Close the child if it isn't yet closed.
|
102
|
+
#
|
103
|
+
def close_child
|
104
|
+
@child.close unless @child.closed?
|
105
|
+
end
|
106
|
+
|
107
|
+
class CouldNotUpdateConfigurationError < StandardError
|
108
|
+
attr_reader :config_key
|
109
|
+
def initialize config_key, message
|
110
|
+
super message
|
111
|
+
@config_key = config_key
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Tries updating the configuration in the child process or parent process.
|
116
|
+
#
|
117
|
+
def try_updating_configuration_with configuration_hash
|
118
|
+
current_key = nil
|
119
|
+
begin
|
120
|
+
configuration_hash.each_pair do |key, new_value|
|
121
|
+
exclaim " Setting #{key} with #{new_value}."
|
122
|
+
current_key = key
|
123
|
+
send :"#{key}=", new_value
|
124
|
+
end
|
125
|
+
rescue StandardError => e
|
126
|
+
raise CouldNotUpdateConfigurationError.new current_key, e.message
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def extract_configuration
|
131
|
+
{
|
132
|
+
querying_removes_characters: querying_removes_characters,
|
133
|
+
querying_stopwords: querying_stopwords,
|
134
|
+
querying_splits_text_on: querying_splits_text_on
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
# TODO Move to Interface object.
|
139
|
+
#
|
140
|
+
def querying_removes_characters
|
141
|
+
Tokenizers::Query.default.instance_variable_get(:@removes_characters_regexp).source
|
142
|
+
end
|
143
|
+
def querying_removes_characters= new_value
|
144
|
+
Tokenizers::Query.default.instance_variable_set(:@removes_characters_regexp, %r{#{new_value}})
|
145
|
+
end
|
146
|
+
def querying_stopwords
|
147
|
+
Tokenizers::Query.default.instance_variable_get(:@remove_stopwords_regexp).source
|
148
|
+
end
|
149
|
+
def querying_stopwords= new_value
|
150
|
+
Tokenizers::Query.default.instance_variable_set(:@remove_stopwords_regexp, %r{#{new_value}})
|
151
|
+
end
|
152
|
+
def querying_splits_text_on
|
153
|
+
Tokenizers::Query.default.instance_variable_get(:@splits_text_on_regexp).source
|
154
|
+
end
|
155
|
+
def querying_splits_text_on= new_value
|
156
|
+
Tokenizers::Query.default.instance_variable_set(:@splits_text_on_regexp, %r{#{new_value}})
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
# Aka.
|
162
|
+
#
|
163
|
+
::LiveParameters = LiveParameters
|
164
|
+
|
165
|
+
end
|
data/lib/picky/loader.rb
CHANGED
@@ -68,7 +68,7 @@ module Loader # :nodoc:all
|
|
68
68
|
|
69
69
|
# Finalize the applications.
|
70
70
|
#
|
71
|
-
# TODO Problem: Reload Routes.
|
71
|
+
# TODO Problem: Reload Routes. Throw them all away and do them again?
|
72
72
|
#
|
73
73
|
Application.finalize_apps
|
74
74
|
|
@@ -249,9 +249,20 @@ module Loader # :nodoc:all
|
|
249
249
|
#
|
250
250
|
load_relative 'configuration/index'
|
251
251
|
|
252
|
+
# Interfaces
|
253
|
+
#
|
254
|
+
load_relative 'interfaces/live_parameters'
|
255
|
+
|
256
|
+
# Adapters.
|
257
|
+
#
|
258
|
+
load_relative 'adapters/rack/base'
|
259
|
+
load_relative 'adapters/rack/query'
|
260
|
+
load_relative 'adapters/rack/live_parameters'
|
261
|
+
load_relative 'adapters/rack'
|
262
|
+
|
252
263
|
# Application and routing.
|
253
264
|
#
|
254
|
-
load_relative '
|
265
|
+
load_relative 'frontend_adapters/rack'
|
255
266
|
load_relative 'application'
|
256
267
|
|
257
268
|
# Load tools.
|
data/lib/picky/query/base.rb
CHANGED
@@ -23,7 +23,7 @@ module Query
|
|
23
23
|
|
24
24
|
include Helpers::Measuring
|
25
25
|
|
26
|
-
attr_writer :tokenizer
|
26
|
+
attr_writer :tokenizer, :identifiers_to_remove
|
27
27
|
attr_accessor :reduce_to_amount, :weights
|
28
28
|
|
29
29
|
# Takes:
|
@@ -43,13 +43,14 @@ module Query
|
|
43
43
|
@weights = Hash === weights ? Weights.new(weights) : weights
|
44
44
|
end
|
45
45
|
|
46
|
-
#
|
46
|
+
# This is the main entry point for a query.
|
47
|
+
# Use this in specs and also for running queries.
|
47
48
|
#
|
48
49
|
# Parameters:
|
49
50
|
# * text: The search text.
|
50
51
|
# * offset = 0: _optional_ The offset from which position to return the ids. Useful for pagination.
|
51
52
|
#
|
52
|
-
# Note: The
|
53
|
+
# Note: The Rack adapter calls this method after unravelling the HTTP request.
|
53
54
|
#
|
54
55
|
def search_with_text text, offset = 0
|
55
56
|
search tokenized(text), offset
|
@@ -75,7 +76,7 @@ module Query
|
|
75
76
|
# Note: Internal method, use #search_with_text.
|
76
77
|
#
|
77
78
|
def execute tokens, offset
|
78
|
-
|
79
|
+
result_type.from offset, sorted_allocations(tokens)
|
79
80
|
end
|
80
81
|
|
81
82
|
# Returns an empty result with default values.
|
@@ -140,28 +141,24 @@ module Query
|
|
140
141
|
def reduce allocations # :nodoc:
|
141
142
|
allocations.reduce_to reduce_to_amount if reduce_to_amount
|
142
143
|
end
|
143
|
-
|
144
|
-
|
145
|
-
|
144
|
+
|
145
|
+
#
|
146
|
+
#
|
146
147
|
def remove_from allocations # :nodoc:
|
147
|
-
allocations.remove
|
148
|
+
allocations.remove identifiers_to_remove
|
148
149
|
end
|
149
|
-
#
|
150
|
+
#
|
150
151
|
#
|
151
152
|
def identifiers_to_remove # :nodoc:
|
152
153
|
@identifiers_to_remove ||= []
|
153
154
|
end
|
154
155
|
|
155
|
-
#
|
156
|
-
#
|
157
|
-
# This generates the id intersections. Lots of work going on.
|
156
|
+
# Display some nice information for the user.
|
158
157
|
#
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
results.prepare!
|
164
|
-
results
|
158
|
+
def to_s
|
159
|
+
s = "#{self.class}"
|
160
|
+
s << ", weights: #{@weights}" unless @weights.empty?
|
161
|
+
s
|
165
162
|
end
|
166
163
|
|
167
164
|
end
|
@@ -26,7 +26,7 @@ module Query
|
|
26
26
|
|
27
27
|
# Returns the weight of this combination.
|
28
28
|
#
|
29
|
-
#
|
29
|
+
# Note: Caching is most oft the time useful.
|
30
30
|
#
|
31
31
|
def weight
|
32
32
|
@weight ||= @bundle.weight(@text)
|
@@ -34,7 +34,7 @@ module Query
|
|
34
34
|
|
35
35
|
# Returns an array of ids for the given text.
|
36
36
|
#
|
37
|
-
#
|
37
|
+
# Note: Caching is most oft the time useful.
|
38
38
|
#
|
39
39
|
def ids
|
40
40
|
@ids ||= @bundle.ids(@text)
|
data/lib/picky/query/solr.rb
CHANGED
@@ -13,21 +13,6 @@ module Query
|
|
13
13
|
super *index_types
|
14
14
|
end
|
15
15
|
|
16
|
-
# # This runs the actual search.
|
17
|
-
# #
|
18
|
-
# # TODO Remove!
|
19
|
-
# #
|
20
|
-
# def search tokens, offset = 0
|
21
|
-
# results = nil
|
22
|
-
#
|
23
|
-
# duration = timed do
|
24
|
-
# results = execute(tokens, offset) || empty_results # TODO Does not work yet
|
25
|
-
# end
|
26
|
-
# results.duration = duration
|
27
|
-
#
|
28
|
-
# results
|
29
|
-
# end
|
30
|
-
|
31
16
|
#
|
32
17
|
#
|
33
18
|
def execute tokens, offset = 0
|
@@ -61,8 +46,6 @@ module Query
|
|
61
46
|
results.add similar: similar
|
62
47
|
end
|
63
48
|
|
64
|
-
# TODO
|
65
|
-
#
|
66
49
|
class << results
|
67
50
|
def to_log query
|
68
51
|
?* + super
|
data/lib/picky/query/token.rb
CHANGED
@@ -69,8 +69,8 @@ module Query
|
|
69
69
|
|
70
70
|
# If the text ends with *, partialize it. If with ", don't.
|
71
71
|
#
|
72
|
-
@@no_partial = /\"
|
73
|
-
@@partial =
|
72
|
+
@@no_partial = /\"\Z/
|
73
|
+
@@partial = /\*\Z/
|
74
74
|
def partialize
|
75
75
|
self.partial = false and return if @text =~ @@no_partial
|
76
76
|
self.partial = true if @text =~ @@partial
|
@@ -78,8 +78,8 @@ module Query
|
|
78
78
|
|
79
79
|
# If the text ends with ~ similarize it. If with ", don't.
|
80
80
|
#
|
81
|
-
@@no_similar = /\"
|
82
|
-
@@similar =
|
81
|
+
@@no_similar = /\"\Z/
|
82
|
+
@@similar = /\~\Z/
|
83
83
|
def similarize
|
84
84
|
self.similar = false and return if @text =~ @@no_similar
|
85
85
|
self.similar = true if @text =~ @@similar
|
@@ -118,35 +118,19 @@ module Query
|
|
118
118
|
def possible_combinations_in type
|
119
119
|
type.possible_combinations self
|
120
120
|
end
|
121
|
-
|
122
|
-
#
|
121
|
+
|
122
|
+
# Returns a token with the next similar text.
|
123
123
|
#
|
124
|
-
|
125
|
-
new_token = token.dup
|
126
|
-
new_token.instance_variable_set :@text, @text
|
127
|
-
new_token.instance_variable_set :@partial, @partial
|
128
|
-
new_token.instance_variable_set :@original, @original
|
129
|
-
new_token.instance_variable_set :@qualifier, @qualifier
|
130
|
-
# TODO
|
131
|
-
#
|
132
|
-
# token.instance_variable_set :@similarity, @similarity
|
133
|
-
new_token
|
134
|
-
end
|
135
|
-
|
136
|
-
# TODO Rewrite, also next_similar.
|
124
|
+
# TODO Rewrite this. It is hard to understand. Also spec performance.
|
137
125
|
#
|
138
|
-
def
|
139
|
-
token =
|
126
|
+
def next_similar_token category
|
127
|
+
token = self.dup
|
140
128
|
token if token.next_similar category.bundle_for(token)
|
141
129
|
end
|
142
|
-
|
143
130
|
# Sets and returns the next similar word.
|
144
131
|
#
|
145
132
|
def next_similar bundle
|
146
|
-
@text = similarity(bundle).
|
147
|
-
rescue StopIteration => stop_iteration
|
148
|
-
# reset_similar # TODO
|
149
|
-
nil # TODO
|
133
|
+
@text = (similarity(bundle).shift || return) if similar?
|
150
134
|
end
|
151
135
|
# Lazy similar reader.
|
152
136
|
#
|
@@ -155,8 +139,11 @@ module Query
|
|
155
139
|
end
|
156
140
|
# Returns an enumerator that traverses over the similar.
|
157
141
|
#
|
142
|
+
# Note: The dup isn't too nice – since it is needed on account of the shift, above.
|
143
|
+
# (We avoid a StopIteration exception. Which of both is less evil?)
|
144
|
+
#
|
158
145
|
def generate_similarity_for bundle
|
159
|
-
|
146
|
+
bundle.similar(@text).dup || []
|
160
147
|
end
|
161
148
|
|
162
149
|
# Generates a solr term from this token.
|
data/lib/picky/query/weights.rb
CHANGED
@@ -7,7 +7,7 @@ module Query
|
|
7
7
|
#
|
8
8
|
#
|
9
9
|
def initialize weights = {}
|
10
|
-
@weights_cache = {}
|
10
|
+
# @weights_cache = {} # TODO
|
11
11
|
@weights = prepare weights
|
12
12
|
end
|
13
13
|
|
@@ -47,5 +47,17 @@ module Query
|
|
47
47
|
weight_for combinations.map(&:category_name).clustered_uniq_fast
|
48
48
|
end
|
49
49
|
|
50
|
+
# Are there any weights defined?
|
51
|
+
#
|
52
|
+
def empty?
|
53
|
+
@weights.empty?
|
54
|
+
end
|
55
|
+
|
56
|
+
# Prints out a nice representation of the configured weights.
|
57
|
+
#
|
58
|
+
def to_s
|
59
|
+
@weights.to_s
|
60
|
+
end
|
61
|
+
|
50
62
|
end
|
51
63
|
end
|
data/lib/picky/results/base.rb
CHANGED
@@ -12,9 +12,16 @@ module Results # :nodoc:all
|
|
12
12
|
|
13
13
|
# Takes instances of Query::Allocations as param.
|
14
14
|
#
|
15
|
-
def initialize offset = 0, allocations =
|
15
|
+
def initialize offset = 0, allocations = Query::Allocations.new
|
16
16
|
@offset = offset
|
17
|
-
@allocations = allocations || Query::Allocations.new
|
17
|
+
@allocations = allocations # || Query::Allocations.new
|
18
|
+
end
|
19
|
+
# Create new results and calculate the ids.
|
20
|
+
#
|
21
|
+
def self.from offset, allocations
|
22
|
+
results = new offset, allocations
|
23
|
+
results.prepare!
|
24
|
+
results
|
18
25
|
end
|
19
26
|
|
20
27
|
#
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Adapters::Rack::Base do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@adapter = Adapters::Rack::Base.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
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Adapters::Rack::LiveParameters do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@live_parameters = stub :live_parameters
|
9
|
+
@adapter = Adapters::Rack::LiveParameters.new @live_parameters
|
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
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Adapters::Rack::Query do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@query = stub :query
|
9
|
+
@adapter = Adapters::Rack::Query.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 offset' do
|
26
|
+
@adapter.extracted('query' => 'some_query')[1].should == 0
|
27
|
+
end
|
28
|
+
it 'extracts a given offset' do
|
29
|
+
@adapter.extracted('query' => 'some_query', 'offset' => '123')[1].should == 123
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -10,11 +10,12 @@ describe Application do
|
|
10
10
|
class MinimalTestApplication < Application
|
11
11
|
books = index :books, Sources::DB.new('SELECT id, title FROM books', :file => 'app/db.yml')
|
12
12
|
books.define_category :title
|
13
|
-
|
14
13
|
|
15
14
|
full = Query::Full.new books
|
16
15
|
live = Query::Live.new books
|
17
16
|
|
17
|
+
rack_adapter.stub! :exclaim # Stopping it from exclaiming.
|
18
|
+
|
18
19
|
route %r{^/books/full} => full
|
19
20
|
route %r{^/books/live} => live
|
20
21
|
end
|
@@ -58,6 +59,8 @@ describe Application do
|
|
58
59
|
full = Query::Full.new books_index
|
59
60
|
live = Query::Live.new books_index
|
60
61
|
|
62
|
+
rack_adapter.stub! :exclaim # Stopping it from exclaiming.
|
63
|
+
|
61
64
|
route %r{^/books/full} => full
|
62
65
|
route %r{^/books/live} => live
|
63
66
|
end
|
@@ -65,30 +68,46 @@ describe Application do
|
|
65
68
|
end
|
66
69
|
end
|
67
70
|
|
71
|
+
describe 'finalize' do
|
72
|
+
before(:each) do
|
73
|
+
Application.stub! :check
|
74
|
+
end
|
75
|
+
it 'checks if all is ok' do
|
76
|
+
Application.should_receive(:check).once.with
|
77
|
+
|
78
|
+
Application.finalize
|
79
|
+
end
|
80
|
+
it 'tells the rack adapter to finalize' do
|
81
|
+
Application.rack_adapter.should_receive(:finalize).once.with
|
82
|
+
|
83
|
+
Application.finalize
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
68
87
|
describe 'delegation' do
|
69
88
|
it "should delegate route" do
|
70
|
-
Application.
|
89
|
+
Application.rack_adapter.should_receive(:route).once.with :path => :query
|
71
90
|
|
72
91
|
Application.route :path => :query
|
73
92
|
end
|
74
93
|
end
|
75
94
|
|
76
|
-
describe '
|
95
|
+
describe 'rack_adapter' do
|
77
96
|
it 'should be there' do
|
78
|
-
lambda { Application.
|
97
|
+
lambda { Application.rack_adapter }.should_not raise_error
|
79
98
|
end
|
80
|
-
it "should return a new
|
81
|
-
Application.
|
99
|
+
it "should return a new FrontendAdapters::Rack instance" do
|
100
|
+
Application.rack_adapter.should be_kind_of(FrontendAdapters::Rack)
|
82
101
|
end
|
83
102
|
it "should cache the instance" do
|
84
|
-
Application.
|
103
|
+
Application.rack_adapter.should == Application.rack_adapter
|
85
104
|
end
|
86
105
|
end
|
87
106
|
|
88
107
|
describe 'call' do
|
89
108
|
before(:each) do
|
90
109
|
@routes = stub :routes
|
91
|
-
Application.stub! :
|
110
|
+
Application.stub! :rack_adapter => @routes
|
92
111
|
end
|
93
112
|
it 'should delegate' do
|
94
113
|
@routes.should_receive(:call).once.with :env
|
data/spec/lib/cli_spec.rb
CHANGED
@@ -27,6 +27,15 @@ describe Picky::CLI do
|
|
27
27
|
it 'returns Statistics for stats' do
|
28
28
|
@cli.executor_class_for(:stats).should == [Picky::CLI::Statistics, "logfile, e.g. log/search.log", "port (optional)"]
|
29
29
|
end
|
30
|
+
it 'returns Live for live' do
|
31
|
+
@cli.executor_class_for(:live).should == [Picky::CLI::Live, "host:port/path (optional, default: localhost:8080/admin)", "port (optional)"]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe Picky::CLI::Live do
|
37
|
+
before(:each) do
|
38
|
+
@cli = Picky::CLI::Live.new
|
30
39
|
end
|
31
40
|
end
|
32
41
|
|
@@ -8,9 +8,7 @@ describe Symbol do
|
|
8
8
|
@token = (((0..9).to_a)*10).to_s.to_sym
|
9
9
|
end
|
10
10
|
it "should be fast" do
|
11
|
-
|
12
|
-
@token.each_subtoken do |subtoken| end
|
13
|
-
end.should < 0.0006
|
11
|
+
performance_of { @token.each_subtoken { |subtoken| } }.should < 0.00065
|
14
12
|
end
|
15
13
|
end
|
16
14
|
|