mongoid-haystack 1.2.1 → 1.3.0

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