mongoid-haystack 1.2.1 → 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/article +19 -0
- data/lib/mongoid-haystack.rb +8 -8
- data/lib/mongoid-haystack/index.rb +14 -1
- data/lib/mongoid-haystack/search.rb +22 -8
- data/lib/mongoid-haystack/stemming.rb +8 -4
- data/lib/mongoid-haystack/token.rb +1 -1
- data/lib/mongoid-haystack/util.rb +99 -8
- data/mongoid-haystack.gemspec +7 -6
- data/test/helper.rb +3 -0
- data/test/mongoid-haystack_test.rb +81 -36
- metadata +15 -13
data/article
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
good abstractions are the backbone of reusable code, and although most people
|
3
|
+
these days are abstracting via objects, class, and functional paradigms little
|
4
|
+
attention is paid to the lowly function signature.
|
5
|
+
|
6
|
+
a good one allows modular methods to be composed into compound ones without
|
7
|
+
fugly code contortions - keeping code nice and readable.
|
8
|
+
|
9
|
+
although many people spend time considering carefully their method names and
|
10
|
+
argument lists, few people stop to consider the role of the block on their
|
11
|
+
methods and how it affects reusability.
|
12
|
+
|
13
|
+
that's unfortunate since fully groking the block is what unleashes the
|
14
|
+
expressive power ruby's internal iterators provide.
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
let's say we have a simple function that parses text into paragraphs. a naive
|
19
|
+
implementation might look like:
|
data/lib/mongoid-haystack.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
module Mongoid
|
4
4
|
module Haystack
|
5
|
-
const_set
|
5
|
+
const_set(:Version, '1.3.0') unless const_defined?(:Version)
|
6
6
|
|
7
7
|
class << Haystack
|
8
8
|
def version
|
@@ -11,13 +11,13 @@
|
|
11
11
|
|
12
12
|
def dependencies
|
13
13
|
{
|
14
|
-
'mongoid' => [ 'mongoid' , '~> 3.0
|
15
|
-
'moped' => [ 'moped' , '~> 1.3
|
16
|
-
'origin' => [ 'origin' , '~> 1.0
|
17
|
-
'map' => [ 'map' , '~> 6.2'
|
18
|
-
'fattr' => [ 'fattr' , '~> 2.2'
|
19
|
-
'coerce' => [ 'coerce' , '~> 0.0
|
20
|
-
'unicode_utils' => [ 'unicode_utils' , '~> 1.4
|
14
|
+
'mongoid' => [ 'mongoid' , '~> 3.0' ] ,
|
15
|
+
'moped' => [ 'moped' , '~> 1.3' ] ,
|
16
|
+
'origin' => [ 'origin' , '~> 1.0' ] ,
|
17
|
+
'map' => [ 'map' , '~> 6.2' ] ,
|
18
|
+
'fattr' => [ 'fattr' , '~> 2.2' ] ,
|
19
|
+
'coerce' => [ 'coerce' , '~> 0.0' ] ,
|
20
|
+
'unicode_utils' => [ 'unicode_utils' , '~> 1.4' ] ,
|
21
21
|
}
|
22
22
|
end
|
23
23
|
|
@@ -174,23 +174,36 @@ module Mongoid
|
|
174
174
|
end
|
175
175
|
end
|
176
176
|
|
177
|
-
before_destroy
|
177
|
+
before_destroy do |index|
|
178
|
+
Index.subtract(index)
|
179
|
+
end
|
180
|
+
|
181
|
+
before_validation do |index|
|
182
|
+
index.size = tokens.count
|
183
|
+
end
|
178
184
|
|
179
185
|
belongs_to(:model, :polymorphic => true)
|
180
186
|
|
181
187
|
has_and_belongs_to_many(:tokens, :class_name => '::Mongoid::Haystack::Token', :inverse_of => nil)
|
182
188
|
|
189
|
+
field(:size, :type => Integer, :default => nil)
|
183
190
|
field(:score, :type => Integer, :default => 0)
|
184
191
|
field(:keyword_scores, :type => Hash, :default => proc{ Hash.new{|h,k| h[k] = 0} })
|
185
192
|
field(:fulltext_scores, :type => Hash, :default => proc{ Hash.new{|h,k| h[k] = 0} })
|
186
193
|
field(:facets, :type => Hash, :default => {})
|
187
194
|
|
195
|
+
%w( size score ).each do |f|
|
196
|
+
validates_presence_of(f)
|
197
|
+
end
|
198
|
+
|
188
199
|
index({:model_type => 1, :model_id => 1}, :unique => true)
|
189
200
|
|
190
201
|
index({:token_ids => 1})
|
191
202
|
index({:score => 1})
|
203
|
+
index({:size => 1})
|
192
204
|
index({:keyword_scores => 1})
|
193
205
|
index({:fulltext_scores => 1})
|
206
|
+
index({:facets => 1})
|
194
207
|
end
|
195
208
|
end
|
196
209
|
end
|
@@ -2,6 +2,10 @@ module Mongoid
|
|
2
2
|
module Haystack
|
3
3
|
module Search
|
4
4
|
ClassMethods = proc do
|
5
|
+
def mongoid_haystack_searchable?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
5
9
|
def search(*args, &block)
|
6
10
|
options = Map.options_for!(args)
|
7
11
|
options[:types] = Array(options[:types]).flatten.compact
|
@@ -52,8 +56,10 @@ module Mongoid
|
|
52
56
|
def Search.included(other)
|
53
57
|
super
|
54
58
|
ensure
|
55
|
-
other.
|
56
|
-
|
59
|
+
unless other.respond_to?(:mongoid_haystack_searchable?)
|
60
|
+
other.instance_eval(&ClassMethods)
|
61
|
+
other.class_eval(&InstanceMethods)
|
62
|
+
end
|
57
63
|
end
|
58
64
|
end
|
59
65
|
|
@@ -100,6 +106,8 @@ module Mongoid
|
|
100
106
|
order.push(["fulltext_scores.#{ token.id }", :desc])
|
101
107
|
end
|
102
108
|
|
109
|
+
order.push(["size", :asc])
|
110
|
+
|
103
111
|
#
|
104
112
|
if options[:facets]
|
105
113
|
conditions[:facets] = {'$elemMatch' => options[:facets]}
|
@@ -201,16 +209,22 @@ module Mongoid
|
|
201
209
|
|
202
210
|
def search_tokens_for(search)
|
203
211
|
values = Token.values_for(search.to_s)
|
204
|
-
tokens =
|
212
|
+
tokens = []
|
205
213
|
|
206
|
-
|
207
|
-
|
214
|
+
Token.where(:value.in => values).each do |token|
|
215
|
+
index = values.index(token.value)
|
216
|
+
tokens[index] = token
|
217
|
+
end
|
208
218
|
|
209
219
|
total = Token.total.to_f
|
210
220
|
|
211
|
-
|
212
|
-
|
213
|
-
|
221
|
+
rarity = {}
|
222
|
+
tokens.map{|token| rarity[token] = token.rarity_bin(total)}
|
223
|
+
|
224
|
+
position = {}
|
225
|
+
tokens.each_with_index{|token, i| position[token] = i + 1}
|
226
|
+
|
227
|
+
tokens.sort!{ |a, b| [rarity[b], position[a]] <=> [rarity[a], position[b]] }
|
214
228
|
|
215
229
|
tokens
|
216
230
|
end
|
@@ -3,17 +3,19 @@
|
|
3
3
|
module Mongoid
|
4
4
|
module Haystack
|
5
5
|
module Stemming
|
6
|
-
def stem(*args)
|
6
|
+
def stem(*args, &block)
|
7
7
|
string = args.join(' ')
|
8
8
|
words = Util.words_for(*args)
|
9
|
-
|
9
|
+
list = []
|
10
|
+
|
10
11
|
words.each do |word|
|
11
12
|
stem = word.stem.downcase
|
12
13
|
next if Stopwords.stopword?(word)
|
13
14
|
next if Stopwords.stopword?(stem)
|
14
|
-
|
15
|
+
block ? block.call(stem) : list.push(stem)
|
15
16
|
end
|
16
|
-
|
17
|
+
|
18
|
+
block ? nil : list
|
17
19
|
end
|
18
20
|
|
19
21
|
alias_method('for', 'stem')
|
@@ -37,6 +39,8 @@ module Mongoid
|
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
42
|
+
# TODO - this needs to be configurable...
|
43
|
+
#
|
40
44
|
unless defined?(All)
|
41
45
|
All = []
|
42
46
|
All.concat(List['english'])
|
@@ -3,8 +3,8 @@ module Mongoid
|
|
3
3
|
module Util
|
4
4
|
def models
|
5
5
|
[
|
6
|
-
Mongoid::Haystack::Token,
|
7
6
|
Mongoid::Haystack::Index,
|
7
|
+
Mongoid::Haystack::Token,
|
8
8
|
Mongoid::Haystack::Sequence
|
9
9
|
]
|
10
10
|
end
|
@@ -59,28 +59,119 @@ module Mongoid
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
def
|
62
|
+
def token_tree_for(*args, &block)
|
63
|
+
tree = []
|
64
|
+
|
65
|
+
phrases_for(*args) do |phrase|
|
66
|
+
#next if stopword?(phrase)
|
67
|
+
|
68
|
+
if block
|
69
|
+
block.call(:phrase, phrase)
|
70
|
+
else
|
71
|
+
tree.push([phrase, words = []])
|
72
|
+
end
|
73
|
+
|
74
|
+
words_for(phrase) do |word|
|
75
|
+
#next if phrase == word
|
76
|
+
#next if stopword?(word)
|
77
|
+
|
78
|
+
if block
|
79
|
+
block.call(:word, word)
|
80
|
+
else
|
81
|
+
words.push([word, stems = []])
|
82
|
+
end
|
83
|
+
|
84
|
+
stems_for(word) do |stem|
|
85
|
+
#next if word == stem
|
86
|
+
|
87
|
+
if block
|
88
|
+
block.call(:stem, stem)
|
89
|
+
else
|
90
|
+
stems.push(stem)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
block ? nil : tree
|
97
|
+
end
|
98
|
+
|
99
|
+
def tokens_for(*args, &block)
|
100
|
+
list = []
|
101
|
+
|
102
|
+
token_tree_for(*args).each do |phrase, words|
|
103
|
+
next if stopword?(phrase)
|
104
|
+
block ? block.call(phrase) : list.push(phrase)
|
105
|
+
|
106
|
+
words.each do |word, stems|
|
107
|
+
next if stopword?(word)
|
108
|
+
|
109
|
+
unless word == phrase
|
110
|
+
block ? block.call(word) : list.push(word)
|
111
|
+
end
|
112
|
+
|
113
|
+
stems.each do |stem|
|
114
|
+
next if stopword?(stem)
|
115
|
+
|
116
|
+
unless stem == phrase or stem == word
|
117
|
+
block ? block.call(stem) : list.push(stem)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
block ? nil : list
|
124
|
+
end
|
125
|
+
|
126
|
+
def phrases_for(*args, &block)
|
127
|
+
string = args.join(' ')
|
128
|
+
string.strip!
|
129
|
+
|
130
|
+
phrases = string.split(/\s+/)
|
131
|
+
|
132
|
+
list = []
|
133
|
+
|
134
|
+
phrases.each do |phrase|
|
135
|
+
strip!(phrase)
|
136
|
+
next if phrase.empty?
|
137
|
+
block ? block.call(phrase) : list.push(phrase)
|
138
|
+
end
|
139
|
+
|
140
|
+
block ? nil : list
|
141
|
+
end
|
142
|
+
|
143
|
+
def words_for(*args, &block)
|
63
144
|
string = args.join(' ')
|
64
145
|
string.gsub!(/_+/, '-')
|
65
146
|
string.gsub!(/[^\w]/, ' ')
|
66
147
|
|
67
|
-
|
148
|
+
list = []
|
68
149
|
|
69
150
|
UnicodeUtils.each_word(string) do |word|
|
70
|
-
|
71
|
-
word.gsub!(/\A(?:[^\w]|_|\s)+/, '') # leading punctuation/spaces
|
72
|
-
word.gsub!(/(?:[^\w]|_|\s+)+\Z/, '') # trailing punctuation/spaces
|
151
|
+
strip!(word)
|
73
152
|
next if word.empty?
|
74
|
-
|
153
|
+
block ? block.call(word) : list.push(word)
|
75
154
|
end
|
76
155
|
|
77
|
-
|
156
|
+
block ? nil : list
|
78
157
|
end
|
79
158
|
|
80
159
|
def stems_for(*args, &block)
|
81
160
|
Stemming.stem(*args, &block)
|
82
161
|
end
|
83
162
|
|
163
|
+
def stopword?(word)
|
164
|
+
word = UnicodeUtils.nfkd(word.to_s.strip.downcase)
|
165
|
+
word.empty? or Stemming::Stopwords.stopword?(word)
|
166
|
+
end
|
167
|
+
|
168
|
+
def strip!(word)
|
169
|
+
word.replace(UnicodeUtils.nfkd(word.to_s.strip))
|
170
|
+
word.gsub!(/\A(?:[^\w]|_|\s)+/, '') # leading punctuation/spaces
|
171
|
+
word.gsub!(/(?:[^\w]|_|\s+)+\Z/, '') # trailing punctuation/spaces
|
172
|
+
word
|
173
|
+
end
|
174
|
+
|
84
175
|
extend Util
|
85
176
|
end
|
86
177
|
|
data/mongoid-haystack.gemspec
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
Gem::Specification::new do |spec|
|
5
5
|
spec.name = "mongoid-haystack"
|
6
|
-
spec.version = "1.
|
6
|
+
spec.version = "1.3.0"
|
7
7
|
spec.platform = Gem::Platform::RUBY
|
8
8
|
spec.summary = "mongoid-haystack"
|
9
9
|
spec.description = "a mongoid 3 zero-config, zero-integration, POLS pure mongo fulltext solution"
|
@@ -12,6 +12,7 @@ Gem::Specification::new do |spec|
|
|
12
12
|
["HISTORY",
|
13
13
|
"README.md",
|
14
14
|
"Rakefile",
|
15
|
+
"article",
|
15
16
|
"lib",
|
16
17
|
"lib/app",
|
17
18
|
"lib/app/models",
|
@@ -57,19 +58,19 @@ Gem::Specification::new do |spec|
|
|
57
58
|
spec.test_files = nil
|
58
59
|
|
59
60
|
|
60
|
-
spec.add_dependency(*["mongoid", "~> 3.0
|
61
|
+
spec.add_dependency(*["mongoid", "~> 3.0"])
|
61
62
|
|
62
|
-
spec.add_dependency(*["moped", "~> 1.3
|
63
|
+
spec.add_dependency(*["moped", "~> 1.3"])
|
63
64
|
|
64
|
-
spec.add_dependency(*["origin", "~> 1.0
|
65
|
+
spec.add_dependency(*["origin", "~> 1.0"])
|
65
66
|
|
66
67
|
spec.add_dependency(*["map", "~> 6.2"])
|
67
68
|
|
68
69
|
spec.add_dependency(*["fattr", "~> 2.2"])
|
69
70
|
|
70
|
-
spec.add_dependency(*["coerce", "~> 0.0
|
71
|
+
spec.add_dependency(*["coerce", "~> 0.0"])
|
71
72
|
|
72
|
-
spec.add_dependency(*["unicode_utils", "~> 1.4
|
73
|
+
spec.add_dependency(*["unicode_utils", "~> 1.4"])
|
73
74
|
|
74
75
|
|
75
76
|
spec.extensions.push(*[])
|
data/test/helper.rb
CHANGED
@@ -11,6 +11,7 @@ Mongoid::Haystack.reset!
|
|
11
11
|
|
12
12
|
class A
|
13
13
|
include Mongoid::Document
|
14
|
+
include Mongoid::Haystack
|
14
15
|
field(:content, :type => String)
|
15
16
|
def to_s; content; end
|
16
17
|
|
@@ -21,6 +22,7 @@ end
|
|
21
22
|
|
22
23
|
class B
|
23
24
|
include Mongoid::Document
|
25
|
+
include Mongoid::Haystack
|
24
26
|
field(:content, :type => String)
|
25
27
|
def to_s; content; end
|
26
28
|
|
@@ -31,6 +33,7 @@ end
|
|
31
33
|
|
32
34
|
class C
|
33
35
|
include Mongoid::Document
|
36
|
+
include Mongoid::Haystack
|
34
37
|
field(:content, :type => String)
|
35
38
|
def to_s; content; end
|
36
39
|
|
@@ -48,6 +48,25 @@ Testing Mongoid::Haystack do
|
|
48
48
|
assert{ Mongoid::Haystack.search('cat dog').map(&:model) == [d, c, b, a] }
|
49
49
|
end
|
50
50
|
|
51
|
+
##
|
52
|
+
#
|
53
|
+
testing 'that word specificity affects the sort' do
|
54
|
+
a = A.create!(:content => 'cat@dog.com')
|
55
|
+
b = A.create!(:content => 'dogs')
|
56
|
+
c = A.create!(:content => 'dog')
|
57
|
+
d = A.create!(:content => 'cats')
|
58
|
+
e = A.create!(:content => 'cat')
|
59
|
+
|
60
|
+
assert{ Mongoid::Haystack.index(A) }
|
61
|
+
|
62
|
+
assert{ Mongoid::Haystack.search('cat@dog.com').map(&:model) == [a, e, d, c, b] }
|
63
|
+
assert{ Mongoid::Haystack.search('cat').map(&:model) == [e, d, a] }
|
64
|
+
assert{ Mongoid::Haystack.search('cats').map(&:model) == [d, e, a] }
|
65
|
+
assert{ Mongoid::Haystack.search('dog').map(&:model) == [c, b, a] }
|
66
|
+
assert{ Mongoid::Haystack.search('dogs').map(&:model) == [b, c, a] }
|
67
|
+
#assert{ Mongoid::Haystack.search('dog').map(&:model) == [c, b, a] }
|
68
|
+
end
|
69
|
+
|
51
70
|
##
|
52
71
|
#
|
53
72
|
testing 'that basic stemming can be performed' do
|
@@ -76,45 +95,59 @@ Testing Mongoid::Haystack do
|
|
76
95
|
|
77
96
|
assert{ Mongoid::Haystack.index(A) }
|
78
97
|
|
79
|
-
assert{ Mongoid::Haystack::Token.count ==
|
80
|
-
assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat dog ) }
|
81
|
-
assert{ Mongoid::Haystack::Token.total ==
|
98
|
+
assert{ Mongoid::Haystack::Token.count == 3 }
|
99
|
+
assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat dog dogs ) }
|
100
|
+
assert{ Mongoid::Haystack::Token.total == 4 }
|
82
101
|
end
|
83
102
|
|
84
103
|
testing 'that removing a model from the index decrements counts appropriately' do
|
85
|
-
|
86
|
-
|
87
|
-
|
104
|
+
2.times do |i|
|
105
|
+
A.destroy_all
|
106
|
+
|
107
|
+
a = A.create!(:content => 'dog')
|
108
|
+
b = A.create!(:content => 'cat')
|
109
|
+
c = A.create!(:content => 'cats dogs')
|
110
|
+
|
111
|
+
remove = proc do |model|
|
112
|
+
assert{
|
113
|
+
if i == 0
|
114
|
+
assert{ Mongoid::Haystack.unindex(model) }
|
115
|
+
else
|
116
|
+
assert{ model.destroy; true }
|
117
|
+
end
|
118
|
+
}
|
119
|
+
end
|
88
120
|
|
89
|
-
|
121
|
+
assert{ Mongoid::Haystack.index(A) }
|
90
122
|
|
91
|
-
|
123
|
+
%w( cat dog cats dogs ).each do |search|
|
124
|
+
assert{ Mongoid::Haystack.search(search).first }
|
125
|
+
end
|
92
126
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
assert{ Mongoid::Haystack::Token.where(:value => 'dog').first.count == 0 }
|
127
|
+
assert{ Mongoid::Haystack::Token.where(:value => 'cat').first.count == 2 }
|
128
|
+
assert{ Mongoid::Haystack::Token.where(:value => 'dog').first.count == 2 }
|
129
|
+
assert{ Mongoid::Haystack::Token.total == 6 }
|
130
|
+
assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat cats dog dogs ) }
|
131
|
+
|
132
|
+
remove[ c ]
|
133
|
+
assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat cats dog dogs ) }
|
134
|
+
assert{ Mongoid::Haystack::Token.total == 2 }
|
135
|
+
assert{ Mongoid::Haystack::Token.where(:value => 'cat').first.count == 1 }
|
136
|
+
assert{ Mongoid::Haystack::Token.where(:value => 'dog').first.count == 1 }
|
137
|
+
|
138
|
+
|
139
|
+
remove[ b ]
|
140
|
+
assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat cats dog dogs ) }
|
141
|
+
assert{ Mongoid::Haystack::Token.total == 1 }
|
142
|
+
assert{ Mongoid::Haystack::Token.where(:value => 'cat').first.count == 0 }
|
143
|
+
assert{ Mongoid::Haystack::Token.where(:value => 'dog').first.count == 1 }
|
144
|
+
|
145
|
+
remove[ a ]
|
146
|
+
assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat cats dog dogs ) }
|
147
|
+
assert{ Mongoid::Haystack::Token.total == 0 }
|
148
|
+
assert{ Mongoid::Haystack::Token.where(:value => 'cat').first.count == 0 }
|
149
|
+
assert{ Mongoid::Haystack::Token.where(:value => 'dog').first.count == 0 }
|
150
|
+
end
|
118
151
|
end
|
119
152
|
|
120
153
|
##
|
@@ -129,7 +162,7 @@ Testing Mongoid::Haystack do
|
|
129
162
|
##
|
130
163
|
#
|
131
164
|
testing 'that classes can export a custom [score|keywords|fulltext] for the search index' do
|
132
|
-
k = new_klass do
|
165
|
+
k = new_klass do
|
133
166
|
def to_haystack
|
134
167
|
colors.push(color = colors.shift)
|
135
168
|
|
@@ -148,6 +181,10 @@ Testing Mongoid::Haystack do
|
|
148
181
|
@score += 1
|
149
182
|
end
|
150
183
|
|
184
|
+
def self.score=(score)
|
185
|
+
@score = score.to_i
|
186
|
+
end
|
187
|
+
|
151
188
|
def score
|
152
189
|
self.class.score
|
153
190
|
end
|
@@ -169,11 +206,11 @@ Testing Mongoid::Haystack do
|
|
169
206
|
|
170
207
|
assert do
|
171
208
|
a.haystack_index.tokens.map(&:value).sort ==
|
172
|
-
["black", "cat", "good", "men", "time"]
|
209
|
+
["black", "cat", "cats", "good", "men", "time"]
|
173
210
|
end
|
174
211
|
assert do
|
175
212
|
b.haystack_index.tokens.map(&:value).sort ==
|
176
|
-
["cat", "good", "men", "time", "white"]
|
213
|
+
["cat", "cats", "good", "men", "time", "white"]
|
177
214
|
end
|
178
215
|
|
179
216
|
assert{ Mongoid::Haystack.search('cat').count == 2 }
|
@@ -363,6 +400,14 @@ Testing Mongoid::Haystack do
|
|
363
400
|
end
|
364
401
|
end
|
365
402
|
|
403
|
+
test '.tokens_for' do
|
404
|
+
{
|
405
|
+
'cats-and-dogs Cats!and?dogs foo-bar! The end. and trees' => %w( cats-and-dogs cats cat dogs dog Cats!and?dogs Cats cat dogs dog foo-bar foo bar end trees tree )
|
406
|
+
}.each do |src, dst|
|
407
|
+
assert{ Mongoid::Haystack.tokens_for(src) == dst }
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
366
411
|
protected
|
367
412
|
|
368
413
|
def new_klass(&block)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-haystack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-05-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mongoid
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 3.0
|
21
|
+
version: '3.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 3.0
|
29
|
+
version: '3.0'
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: moped
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 1.3
|
37
|
+
version: '1.3'
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 1.3
|
45
|
+
version: '1.3'
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: origin
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 1.0
|
53
|
+
version: '1.0'
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.0
|
61
|
+
version: '1.0'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: map
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
requirements:
|
99
99
|
- - ~>
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version: 0.0
|
101
|
+
version: '0.0'
|
102
102
|
type: :runtime
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -106,7 +106,7 @@ dependencies:
|
|
106
106
|
requirements:
|
107
107
|
- - ~>
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: 0.0
|
109
|
+
version: '0.0'
|
110
110
|
- !ruby/object:Gem::Dependency
|
111
111
|
name: unicode_utils
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,7 +114,7 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - ~>
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 1.4
|
117
|
+
version: '1.4'
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -122,7 +122,7 @@ dependencies:
|
|
122
122
|
requirements:
|
123
123
|
- - ~>
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: 1.4
|
125
|
+
version: '1.4'
|
126
126
|
description: a mongoid 3 zero-config, zero-integration, POLS pure mongo fulltext solution
|
127
127
|
email: ara.t.howard@gmail.com
|
128
128
|
executables: []
|
@@ -132,6 +132,7 @@ files:
|
|
132
132
|
- HISTORY
|
133
133
|
- README.md
|
134
134
|
- Rakefile
|
135
|
+
- article
|
135
136
|
- lib/app/models/mongoid/haystack/index.rb
|
136
137
|
- lib/app/models/mongoid/haystack/sequence.rb
|
137
138
|
- lib/app/models/mongoid/haystack/token.rb
|
@@ -180,8 +181,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
181
|
version: '0'
|
181
182
|
requirements: []
|
182
183
|
rubyforge_project: codeforpeople
|
183
|
-
rubygems_version: 1.8.
|
184
|
+
rubygems_version: 1.8.23
|
184
185
|
signing_key:
|
185
186
|
specification_version: 3
|
186
187
|
summary: mongoid-haystack
|
187
188
|
test_files: []
|
189
|
+
has_rdoc:
|