picky 2.2.0 → 2.2.1
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/application.rb +53 -45
- data/lib/picky/index/base.rb +57 -35
- data/lib/picky/internals/indexed/bundle/base.rb +0 -2
- data/lib/picky/internals/indexed/categories.rb +0 -2
- data/lib/picky/internals/indexed/index.rb +0 -4
- data/lib/picky/internals/indexed/wrappers/exact_first.rb +0 -6
- data/lib/picky/internals/indexers/serial.rb +3 -14
- data/lib/picky/internals/indexing/bundle/redis.rb +14 -14
- data/lib/picky/internals/query/tokens.rb +4 -2
- data/lib/picky/internals/tokenizers/base.rb +1 -1
- data/spec/aux/picky/cli_spec.rb +0 -2
- data/spec/lib/index/base_spec.rb +9 -0
- data/spec/lib/internals/indexed/wrappers/exact_first_spec.rb +15 -15
- metadata +2 -2
data/lib/picky/application.rb
CHANGED
@@ -13,14 +13,16 @@
|
|
13
13
|
# will generate an example <tt>project_name/app/application.rb</tt> file for you
|
14
14
|
# with some example code inside.
|
15
15
|
#
|
16
|
-
# == Index::Memory.new(name
|
16
|
+
# == Index::Memory.new(name)
|
17
17
|
#
|
18
18
|
# Next, define where your data comes from. You use the <tt>Index::Memory.new</tt> method for that:
|
19
|
-
# my_index = Index::Memory.new :some_index_name
|
19
|
+
# my_index = Index::Memory.new :some_index_name
|
20
20
|
# You give the index a name (or identifier), and a source (see Sources), where its data comes from. Let's do that:
|
21
21
|
# class MyGreatSearch < Application
|
22
22
|
#
|
23
|
-
# books = Index::Memory.new :books
|
23
|
+
# books = Index::Memory.new :books do
|
24
|
+
# source Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
|
25
|
+
# end
|
24
26
|
#
|
25
27
|
# end
|
26
28
|
# Now we have an index <tt>books</tt>.
|
@@ -29,7 +31,7 @@
|
|
29
31
|
#
|
30
32
|
# Note that a Redis index is also available: Index::Redis.new.
|
31
33
|
#
|
32
|
-
# ==
|
34
|
+
# == category(identifier, options = {})
|
33
35
|
#
|
34
36
|
# Picky needs us to define categories on the data.
|
35
37
|
#
|
@@ -39,8 +41,10 @@
|
|
39
41
|
# Let's go ahead and define a category:
|
40
42
|
# class MyGreatSearch < Application
|
41
43
|
#
|
42
|
-
# books = Index::Memory.new :books
|
43
|
-
#
|
44
|
+
# books = Index::Memory.new :books do
|
45
|
+
# source Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
|
46
|
+
# category :title
|
47
|
+
# end
|
44
48
|
#
|
45
49
|
# end
|
46
50
|
# Now we could already run the indexer:
|
@@ -52,7 +56,7 @@
|
|
52
56
|
#
|
53
57
|
# == Search.new(*indexes, options = {})
|
54
58
|
#
|
55
|
-
# We need somebody who asks the index (a Query object, also see http://github.com/floere/picky/wiki/Queries-Configuration)
|
59
|
+
# We need somebody who asks the index (a Query object, also see http://github.com/floere/picky/wiki/Queries-Configuration):
|
56
60
|
# books_search = Search.new books
|
57
61
|
#
|
58
62
|
# Now we have somebody we can ask about the index. But no external interface.
|
@@ -64,8 +68,10 @@
|
|
64
68
|
# In full glory:
|
65
69
|
# class MyGreatSearch < Application
|
66
70
|
#
|
67
|
-
# books = index :books
|
68
|
-
#
|
71
|
+
# books = index :books do
|
72
|
+
# source Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
|
73
|
+
# category :title
|
74
|
+
# end
|
69
75
|
#
|
70
76
|
# route %r{^/books$} => Search.new(books)
|
71
77
|
#
|
@@ -82,19 +88,19 @@
|
|
82
88
|
#
|
83
89
|
# Maybe you don't find everything. We need to process the data before it goes into the index.
|
84
90
|
#
|
85
|
-
# ==
|
91
|
+
# == indexing(options = {})
|
86
92
|
#
|
87
|
-
# That's what the <tt>
|
88
|
-
#
|
93
|
+
# That's what the <tt>indexing</tt> method is for:
|
94
|
+
# indexing options
|
89
95
|
# Read more about the options here: http://github.com/floere/picky/wiki/Indexing-configuration
|
90
96
|
#
|
91
97
|
# Same thing with the search text – we need to process that as well.
|
92
98
|
#
|
93
|
-
# ==
|
99
|
+
# == searching(options = {})
|
94
100
|
#
|
95
|
-
# Analog to the
|
96
|
-
#
|
97
|
-
# Read more about the options here: http://github.com/floere/picky/wiki/
|
101
|
+
# Analog to the indexing method, we use the <tt>searching</tt> method.
|
102
|
+
# searching options
|
103
|
+
# Read more about the options here: http://github.com/floere/picky/wiki/Searching-Configuration
|
98
104
|
#
|
99
105
|
# And that's all there is. It's incredibly powerful though, as you can combine, weigh, refine to the max.
|
100
106
|
#
|
@@ -109,35 +115,37 @@
|
|
109
115
|
# Our example, fully fleshed out with indexing, querying, and weights:
|
110
116
|
# class MyGreatSearch < Application
|
111
117
|
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
# books = Index::Memory.new :books
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
# route %r{^/books$} => Search.new(books
|
118
|
+
# indexing removes_characters: /[^a-zA-Z0-9\.]/,
|
119
|
+
# stopwords: /\b(and|or|in|on|is|has)\b/,
|
120
|
+
# splits_text_on: /\s/,
|
121
|
+
# removes_characters_after_splitting: /\./,
|
122
|
+
# substitutes_characters_with: CharacterSubstituters::WestEuropean.new,
|
123
|
+
# normalizes_words: [
|
124
|
+
# [/(.*)hausen/, 'hn'],
|
125
|
+
# [/\b(\w*)str(eet)?/, 'st']
|
126
|
+
# ]
|
127
|
+
#
|
128
|
+
# searching removes_characters: /[^a-zA-Z0-9\s\/\-\,\&\"\~\*\:]/,
|
129
|
+
# stopwords: /\b(and|the|of|it|in|for)\b/,
|
130
|
+
# splits_text_on: /[\s\/\-\,\&]+/,
|
131
|
+
# removes_characters_after_splitting: /\./,
|
132
|
+
# substitutes_characters_with: CharacterSubstituters::WestEuropean.new,
|
133
|
+
# maximum_tokens: 4
|
134
|
+
#
|
135
|
+
# books = Index::Memory.new :books do
|
136
|
+
# source Sources::CSV.new(:title, :author, :isbn, file:'app/library.csv')
|
137
|
+
# category :title,
|
138
|
+
# qualifiers: [:t, :title, :titre],
|
139
|
+
# partial: Partial::Substring.new(:from => 1),
|
140
|
+
# similarity: Similarity::DoubleMetaphone.new(2)
|
141
|
+
# category :author,
|
142
|
+
# partial: Partial::Substring.new(:from => -2)
|
143
|
+
# category :isbn
|
144
|
+
# end
|
145
|
+
#
|
146
|
+
# route %r{^/books$} => Search.new(books) do
|
147
|
+
# boost [:title, :author] => +3, [:author, :title] => -1
|
148
|
+
# end
|
141
149
|
#
|
142
150
|
# end
|
143
151
|
# That's actually already a full-blown Picky App!
|
data/lib/picky/index/base.rb
CHANGED
@@ -15,15 +15,15 @@ module Index
|
|
15
15
|
#
|
16
16
|
# === Parameters
|
17
17
|
# * name: A name that will be used for the index directory and in the Picky front end.
|
18
|
-
# * source: Where the data comes from, e.g. Sources::CSV.new(...). Optional, can be defined in the block using #source.
|
19
18
|
#
|
20
19
|
# === Options
|
20
|
+
# * source: Where the data comes from, e.g. Sources::CSV.new(...). Optional, can be defined in the block using #source.
|
21
21
|
# * result_identifier: Use if you'd like a different identifier/name in the results than the name of the index.
|
22
22
|
# * after_indexing: As of this writing only used in the db source. Executes the given after_indexing as SQL after the indexing process.
|
23
|
-
# * tokenizer: The tokenizer to use for this index.
|
23
|
+
# * tokenizer: The tokenizer to use for this index. Optional, can be defined in the block using #indexing.
|
24
24
|
#
|
25
25
|
# Examples:
|
26
|
-
# my_index = Index::Memory.new(:my_index, some_source) do
|
26
|
+
# my_index = Index::Memory.new(:my_index, source: some_source) do
|
27
27
|
# category :bla
|
28
28
|
# end
|
29
29
|
#
|
@@ -64,10 +64,10 @@ module Index
|
|
64
64
|
raise ArgumentError.new(<<-NAME
|
65
65
|
|
66
66
|
|
67
|
-
The index identifier (you gave "#{name}") for Index::Memory/Index::Redis should be a String
|
67
|
+
The index identifier (you gave "#{name}") for Index::Memory/Index::Redis should be a Symbol/String,
|
68
68
|
Examples:
|
69
|
-
Index::Memory.new(:my_cool_index
|
70
|
-
Index::Redis.new("a-redis-index"
|
69
|
+
Index::Memory.new(:my_cool_index) # Recommended
|
70
|
+
Index::Redis.new("a-redis-index")
|
71
71
|
NAME
|
72
72
|
|
73
73
|
|
@@ -121,12 +121,12 @@ INDEX
|
|
121
121
|
|
122
122
|
# Define an index tokenizer on the index.
|
123
123
|
#
|
124
|
-
# Parameters are the exact same as for
|
124
|
+
# Parameters are the exact same as for indexing.
|
125
125
|
#
|
126
|
-
def
|
126
|
+
def indexing options = {}
|
127
127
|
internal_indexing.define_indexing options
|
128
128
|
end
|
129
|
-
alias indexing
|
129
|
+
alias define_indexing indexing
|
130
130
|
|
131
131
|
# Define a source on the index.
|
132
132
|
#
|
@@ -134,10 +134,10 @@ INDEX
|
|
134
134
|
# anything responding to #each and returning objects that
|
135
135
|
# respond to id and the category names (or the category from option).
|
136
136
|
#
|
137
|
-
def
|
137
|
+
def source source
|
138
138
|
internal_indexing.define_source source
|
139
139
|
end
|
140
|
-
alias source
|
140
|
+
alias define_source source
|
141
141
|
|
142
142
|
# Defines a searchable category on the index.
|
143
143
|
#
|
@@ -152,7 +152,7 @@ INDEX
|
|
152
152
|
# * source: Use a different source than the index uses. If you think you need that, there might be a better solution to your problem. Please post to the mailing list first with your application.rb :)
|
153
153
|
# * from: Take the data from the data category with this name. Example: You have a source Sources::CSV.new(:title, file:'some_file.csv') but you want the category to be called differently. The you use from: define_category(:similar_title, :from => :title).
|
154
154
|
#
|
155
|
-
def
|
155
|
+
def category category_name, options = {}
|
156
156
|
category_name = category_name.to_sym
|
157
157
|
|
158
158
|
indexing_category = internal_indexing.define_category category_name, options
|
@@ -162,11 +162,10 @@ INDEX
|
|
162
162
|
|
163
163
|
self
|
164
164
|
end
|
165
|
-
alias category
|
165
|
+
alias define_category category
|
166
166
|
|
167
|
-
#
|
168
|
-
#
|
169
|
-
# Make this category range searchable with a fixed range. If you need other ranges, define another category with a different range value.
|
167
|
+
# Make this category range searchable with a fixed range. If you need other
|
168
|
+
# ranges, define another category with a different range value.
|
170
169
|
#
|
171
170
|
# Example:
|
172
171
|
# You have data values inside 1..100, and you want to have Picky return
|
@@ -174,22 +173,27 @@ INDEX
|
|
174
173
|
# 45, 46, or 47.2, 48.9, in a range of 2 around 47, so (45..49).
|
175
174
|
#
|
176
175
|
# Then you use:
|
177
|
-
#
|
176
|
+
# ranged_category :values_inside_1_100, 2
|
178
177
|
#
|
179
178
|
# Optionally, you give it a precision value to reduce the error margin
|
180
179
|
# around 47 (Picky is a bit liberal).
|
181
|
-
#
|
180
|
+
# Index::Memory.new :range do
|
181
|
+
# ranged_category :values_inside_1_100, 2, precision: 5
|
182
|
+
# end
|
182
183
|
#
|
183
184
|
# This will force Picky to maximally be wrong 5% of the given range value
|
184
185
|
# (5% of 2 = 0.1) instead of the default 20% (20% of 2 = 0.4).
|
185
186
|
#
|
186
|
-
# We suggest not to use much more than 5 as a higher precision is more
|
187
|
+
# We suggest not to use much more than 5 as a higher precision is more
|
188
|
+
# performance intensive for less and less precision gain.
|
187
189
|
#
|
188
190
|
# == Protip 1
|
189
191
|
#
|
190
192
|
# Create two ranged categories to make an area search:
|
191
|
-
#
|
192
|
-
#
|
193
|
+
# Index::Memory.new :area do
|
194
|
+
# ranged_category :x, 1
|
195
|
+
# ranged_category :y, 1
|
196
|
+
# end
|
193
197
|
#
|
194
198
|
# Search for it using for example:
|
195
199
|
# x:133, y:120
|
@@ -223,7 +227,7 @@ INDEX
|
|
223
227
|
# * precision: Default is 1 (20% error margin, very fast), up to 5 (5% error margin, slower) makes sense.
|
224
228
|
# * ... all options of #define_category.
|
225
229
|
#
|
226
|
-
def
|
230
|
+
def ranged_category category_name, range, options = {}
|
227
231
|
precision = options[:precision] || 1
|
228
232
|
|
229
233
|
options = { partial: Partial::None.new }.merge options
|
@@ -233,17 +237,18 @@ INDEX
|
|
233
237
|
Internals::Indexed::Wrappers::Category::Location.install_on indexed_category, range, precision
|
234
238
|
end
|
235
239
|
end
|
236
|
-
alias ranged_category
|
240
|
+
alias define_ranged_category ranged_category
|
237
241
|
|
238
242
|
# HIGHLY EXPERIMENTAL Not correctly working yet. Try it if you feel "beta".
|
239
243
|
#
|
240
|
-
# Also a range search see #
|
244
|
+
# Also a range search see #ranged_category, but on the earth's surface.
|
241
245
|
#
|
242
246
|
# Parameters:
|
243
|
-
# *
|
247
|
+
# * lat_name: The latitude's name as used in #define_category.
|
248
|
+
# * lng_name: The longitude's name as used in #define_category.
|
244
249
|
# * radius: The distance (in km) around the query point which we search for results.
|
245
250
|
#
|
246
|
-
# Note: Picky uses a square, not a circle.
|
251
|
+
# Note: Picky uses a square, not a circle. That should be ok for most usages.
|
247
252
|
#
|
248
253
|
# -----------------------------
|
249
254
|
# | |
|
@@ -261,23 +266,40 @@ INDEX
|
|
261
266
|
#
|
262
267
|
# Options
|
263
268
|
# * precision: Default 1 (20% error margin, very fast), up to 5 (5% error margin, slower) makes sense.
|
264
|
-
# *
|
269
|
+
# * lat_from: The data category to take the data for the latitude from.
|
270
|
+
# * lng_from: The data category to take the data for the longitude from.
|
265
271
|
#
|
266
|
-
# TODO
|
272
|
+
# TODO Will have to write a wrapper that combines two categories that are
|
273
|
+
# indexed simultaneously, since lat/lng are correlated.
|
267
274
|
#
|
268
|
-
def
|
269
|
-
|
275
|
+
def geo_categories lat_name, lng_name, radius, options = {} # :nodoc:
|
276
|
+
|
277
|
+
# Extract lat/lng specific options.
|
270
278
|
#
|
271
|
-
|
279
|
+
lat_from = options.delete :lat_from
|
280
|
+
lng_from = options.delete :lng_from
|
281
|
+
|
282
|
+
# One can be a normal ranged_category.
|
283
|
+
#
|
284
|
+
ranged_category lat_name, radius*0.00898312, options.merge(from: lat_from)
|
285
|
+
|
286
|
+
# The other needs to adapt the radius depending on the one.
|
287
|
+
#
|
288
|
+
# Depending on the latitude, the radius of the longitude
|
289
|
+
# needs to enlarge, the closer we get to the pole.
|
290
|
+
#
|
291
|
+
# In our simplified case, the radius is given as if all the
|
292
|
+
# locations were on the 45 degree line.
|
272
293
|
#
|
273
294
|
# This calculates km -> longitude (degrees).
|
274
295
|
#
|
275
|
-
# A degree on the
|
276
|
-
# So a km on the
|
296
|
+
# A degree on the 45 degree line is equal to ~222.6398 km.
|
297
|
+
# So a km on the 45 degree line is equal to 0.01796624 degrees.
|
277
298
|
#
|
278
|
-
|
299
|
+
ranged_category lng_name, radius*0.01796624, options.merge(from: lng_from)
|
300
|
+
|
279
301
|
end
|
280
|
-
alias
|
302
|
+
alias define_geo_categories geo_categories
|
281
303
|
end
|
282
304
|
|
283
305
|
end
|
@@ -105,8 +105,6 @@ module Internals
|
|
105
105
|
# (Also none of the categories matched, but the ignore unassigned
|
106
106
|
# tokens option is true)
|
107
107
|
#
|
108
|
-
# TODO Could use Combinations class here and remove the inject.
|
109
|
-
#
|
110
108
|
def possible_for token, preselected_categories = nil
|
111
109
|
possible = (preselected_categories || possible_categories(token)).inject([]) do |combinations, category|
|
112
110
|
combination = category.combination_for token
|
@@ -12,8 +12,6 @@ module Internals
|
|
12
12
|
:analyze,
|
13
13
|
:to => :categories
|
14
14
|
|
15
|
-
# TODO Externalize?
|
16
|
-
#
|
17
15
|
def initialize name, options = {}
|
18
16
|
@name = name
|
19
17
|
|
@@ -24,8 +22,6 @@ module Internals
|
|
24
22
|
@categories = Categories.new ignore_unassigned_tokens: ignore_unassigned_tokens
|
25
23
|
end
|
26
24
|
|
27
|
-
# TODO Doc. Externalize?
|
28
|
-
#
|
29
25
|
def define_category category_name, options = {}
|
30
26
|
options = default_category_options.merge options
|
31
27
|
|
@@ -4,15 +4,11 @@ module Internals
|
|
4
4
|
#
|
5
5
|
module Indexed
|
6
6
|
|
7
|
-
# TODO Spec
|
8
|
-
#
|
9
7
|
module Wrappers
|
10
8
|
|
11
9
|
# This index combines an exact and partial index.
|
12
10
|
# It serves to order the results such that exact hits are found first.
|
13
11
|
#
|
14
|
-
# TODO Need to use the right subtokens. Bake in?
|
15
|
-
#
|
16
12
|
class ExactFirst < Indexed::Bundle::Base
|
17
13
|
|
18
14
|
delegate :similar,
|
@@ -42,8 +38,6 @@ module Internals
|
|
42
38
|
new index_or_category
|
43
39
|
end
|
44
40
|
end
|
45
|
-
# TODO Do not extract categories!
|
46
|
-
#
|
47
41
|
def self.wrap_each_of categories
|
48
42
|
categories.categories.collect! { |category| new(category) }
|
49
43
|
end
|
@@ -6,8 +6,6 @@ module Indexers
|
|
6
6
|
#
|
7
7
|
# Note: It is called serial since it indexes each
|
8
8
|
#
|
9
|
-
# FIXME Giving the serial a category would be enough, since it already contains an index!
|
10
|
-
#
|
11
9
|
class Serial < Base
|
12
10
|
|
13
11
|
attr_reader :category
|
@@ -24,22 +22,13 @@ module Indexers
|
|
24
22
|
@tokenizer ||= category.tokenizer
|
25
23
|
end
|
26
24
|
|
25
|
+
# Harvest the data from the source, tokenize,
|
26
|
+
# and write to an intermediate "prepared index" file.
|
27
|
+
#
|
27
28
|
def process
|
28
29
|
comma = ?,
|
29
30
|
newline = ?\n
|
30
31
|
|
31
|
-
# TODO Move open to config?
|
32
|
-
#
|
33
|
-
# @category.prepared_index do |file|
|
34
|
-
# source.harvest(@index, @category) do |indexed_id, text|
|
35
|
-
# tokenizer.tokenize(text).each do |token_text|
|
36
|
-
# next unless token_text
|
37
|
-
# file.buffer indexed_id << comma << token_text << newline
|
38
|
-
# end
|
39
|
-
# file.write_maybe
|
40
|
-
# end
|
41
|
-
# end
|
42
|
-
#
|
43
32
|
local_tokenizer = tokenizer
|
44
33
|
category.prepared_index_file do |file|
|
45
34
|
result = []
|
@@ -3,26 +3,26 @@
|
|
3
3
|
module Internals
|
4
4
|
|
5
5
|
module Indexing # :nodoc:all
|
6
|
-
|
6
|
+
|
7
7
|
module Bundle
|
8
|
-
|
9
|
-
# The
|
10
|
-
#
|
8
|
+
|
9
|
+
# The Redis version dumps its generated indexes to
|
10
|
+
# the Redis backend.
|
11
11
|
#
|
12
12
|
class Redis < Base
|
13
|
-
|
13
|
+
|
14
14
|
attr_reader :backend
|
15
|
-
|
16
|
-
def initialize name,
|
17
|
-
super name,
|
18
|
-
|
19
|
-
@backend = Internals::Index::Redis.new name,
|
15
|
+
|
16
|
+
def initialize name, category, *args
|
17
|
+
super name, category, *args
|
18
|
+
|
19
|
+
@backend = Internals::Index::Redis.new name, category
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
end
|
@@ -44,10 +44,12 @@ module Internals
|
|
44
44
|
# [combination, combination] # of token 3
|
45
45
|
# ]
|
46
46
|
#
|
47
|
-
def possible_combinations_in
|
47
|
+
def possible_combinations_in index
|
48
48
|
@tokens.inject([]) do |combinations, token|
|
49
|
-
possible_combinations = token.possible_combinations_in
|
49
|
+
possible_combinations = token.possible_combinations_in index
|
50
50
|
|
51
|
+
# TODO Could move the ignore_unassigned_tokens here!
|
52
|
+
#
|
51
53
|
# Note: Optimization for ignoring tokens that allocate to nothing and
|
52
54
|
# can be ignored.
|
53
55
|
# For example in a special search, where "florian" is not
|
@@ -117,7 +117,7 @@ Case sensitive? #{@case_sensitive ? "Yes." : "-"}
|
|
117
117
|
|
118
118
|
# Reject tokens after tokenizing based on the given criteria.
|
119
119
|
#
|
120
|
-
# Note: Currently only for indexing.
|
120
|
+
# Note: Currently only for indexing.
|
121
121
|
#
|
122
122
|
def reject_token_if &condition
|
123
123
|
@reject_condition = condition
|
data/spec/aux/picky/cli_spec.rb
CHANGED
data/spec/lib/index/base_spec.rb
CHANGED
@@ -53,6 +53,15 @@ ERROR
|
|
53
53
|
context 'unit' do
|
54
54
|
let(:api) { described_class.new :some_index_name, source: some_source }
|
55
55
|
|
56
|
+
describe 'geo_categories' do
|
57
|
+
it 'delegates correctly' do
|
58
|
+
api.should_receive(:ranged_category).once.with :some_lat, 0.00898312, from: :some_lat_from
|
59
|
+
api.should_receive(:ranged_category).once.with :some_lng, 0.01796624, from: :some_lng_from
|
60
|
+
|
61
|
+
api.geo_categories :some_lat, :some_lng, 1, :lat_from => :some_lat_from, :lng_from => :some_lng_from
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
56
65
|
describe 'define_source' do
|
57
66
|
it 'delegates to the internal indexing' do
|
58
67
|
indexing = stub :indexing
|
@@ -11,22 +11,22 @@ describe Internals::Indexed::Wrappers::ExactFirst do
|
|
11
11
|
end
|
12
12
|
|
13
13
|
describe "self.wrap" do
|
14
|
-
context "
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
it "returns the
|
26
|
-
|
27
|
-
|
14
|
+
context "index" do
|
15
|
+
it "wraps each category" do
|
16
|
+
index = Internals::Indexed::Index.new :index_name
|
17
|
+
index.define_category :some_category
|
18
|
+
|
19
|
+
Internals::Indexed::Wrappers::ExactFirst.wrap index
|
20
|
+
|
21
|
+
index.categories.categories.each do |category|
|
22
|
+
category.should be_kind_of(Internals::Indexed::Wrappers::ExactFirst)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
it "returns the index" do
|
26
|
+
index = Internals::Indexed::Index.new :index_name
|
27
|
+
index.define_category :some_category
|
28
28
|
|
29
|
-
described_class.wrap(
|
29
|
+
described_class.wrap(index).should == index
|
30
30
|
end
|
31
31
|
end
|
32
32
|
context "category" do
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: picky
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 2.2.
|
5
|
+
version: 2.2.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Florian Hanke
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-04-
|
13
|
+
date: 2011-04-15 00:00:00 +10:00
|
14
14
|
default_executable: picky
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|