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 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:
@@ -2,7 +2,7 @@
2
2
  #
3
3
  module Mongoid
4
4
  module Haystack
5
- const_set :Version, '1.2.1'
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.14' ] ,
15
- 'moped' => [ 'moped' , '~> 1.3.1' ] ,
16
- 'origin' => [ 'origin' , '~> 1.0.11' ] ,
17
- 'map' => [ 'map' , '~> 6.2' ] ,
18
- 'fattr' => [ 'fattr' , '~> 2.2' ] ,
19
- 'coerce' => [ 'coerce' , '~> 0.0.3' ] ,
20
- 'unicode_utils' => [ 'unicode_utils' , '~> 1.4.0' ] ,
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{|index| Index.subtract(index)}
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.instance_eval(&ClassMethods)
56
- other.class_eval(&InstanceMethods)
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 = Token.where(:value.in => values).to_a
212
+ tokens = []
205
213
 
206
- positions = {}
207
- tokens.each_with_index{|token, index| positions[token] = index + 1}
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
- tokens.sort! do |a,b|
212
- [b.rarity_bin(total), positions[b]] <=> [a.rarity_bin(total), positions[a]]
213
- end
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
- stems = []
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
- stems.push(stem)
15
+ block ? block.call(stem) : list.push(stem)
15
16
  end
16
- stems
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'])
@@ -5,7 +5,7 @@ module Mongoid
5
5
 
6
6
  class << Token
7
7
  def values_for(*args)
8
- Haystack.stems_for(*args)
8
+ Haystack.tokens_for(*args)
9
9
  end
10
10
 
11
11
  def add(value)
@@ -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 words_for(*args)
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
- words = []
148
+ list = []
68
149
 
69
150
  UnicodeUtils.each_word(string) do |word|
70
- word = UnicodeUtils.nfkd(word.strip)
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
- words.push(word)
153
+ block ? block.call(word) : list.push(word)
75
154
  end
76
155
 
77
- words
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
 
@@ -3,7 +3,7 @@
3
3
 
4
4
  Gem::Specification::new do |spec|
5
5
  spec.name = "mongoid-haystack"
6
- spec.version = "1.2.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.14"])
61
+ spec.add_dependency(*["mongoid", "~> 3.0"])
61
62
 
62
- spec.add_dependency(*["moped", "~> 1.3.1"])
63
+ spec.add_dependency(*["moped", "~> 1.3"])
63
64
 
64
- spec.add_dependency(*["origin", "~> 1.0.11"])
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.3"])
71
+ spec.add_dependency(*["coerce", "~> 0.0"])
71
72
 
72
- spec.add_dependency(*["unicode_utils", "~> 1.4.0"])
73
+ spec.add_dependency(*["unicode_utils", "~> 1.4"])
73
74
 
74
75
 
75
76
  spec.extensions.push(*[])
@@ -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 == 2 }
80
- assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat dog ) }
81
- assert{ Mongoid::Haystack::Token.total == 3 }
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
- a = A.create!(:content => 'dog')
86
- b = A.create!(:content => 'cat')
87
- c = A.create!(:content => 'cats dogs')
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
- assert{ Mongoid::Haystack.index(A) }
121
+ assert{ Mongoid::Haystack.index(A) }
90
122
 
91
- assert{ Mongoid::Haystack.search('cat').first }
123
+ %w( cat dog cats dogs ).each do |search|
124
+ assert{ Mongoid::Haystack.search(search).first }
125
+ end
92
126
 
93
- assert{ Mongoid::Haystack::Token.where(:value => 'cat').first.count == 2 }
94
- assert{ Mongoid::Haystack::Token.where(:value => 'dog').first.count == 2 }
95
- assert{ Mongoid::Haystack::Token.total == 4 }
96
- assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat dog ) }
97
- assert{ Mongoid::Haystack.unindex(c) }
98
- assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat dog ) }
99
- assert{ Mongoid::Haystack::Token.total == 2 }
100
- assert{ Mongoid::Haystack::Token.where(:value => 'cat').first.count == 1 }
101
- assert{ Mongoid::Haystack::Token.where(:value => 'dog').first.count == 1 }
102
-
103
- assert{ Mongoid::Haystack::Token.total == 2 }
104
- assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat dog ) }
105
- assert{ Mongoid::Haystack.unindex(b) }
106
- assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat dog ) }
107
- assert{ Mongoid::Haystack::Token.total == 1 }
108
- assert{ Mongoid::Haystack::Token.where(:value => 'cat').first.count == 0 }
109
- assert{ Mongoid::Haystack::Token.where(:value => 'dog').first.count == 1 }
110
-
111
- assert{ Mongoid::Haystack::Token.total == 1 }
112
- assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat dog ) }
113
- assert{ Mongoid::Haystack.unindex(a) }
114
- assert{ Mongoid::Haystack::Token.all.map(&:value).sort == %w( cat dog ) }
115
- assert{ Mongoid::Haystack::Token.total == 0 }
116
- assert{ Mongoid::Haystack::Token.where(:value => 'cat').first.count == 0 }
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.2.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: 2012-12-12 00:00:00.000000000 Z
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.14
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.14
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.1
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.1
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.11
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.11
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.3
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.3
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.0
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.0
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.24
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: