picky 2.2.0 → 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|