searchkick 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 84aa6414f91ce1c76d0c247e9a11dfce4417c2ee
4
- data.tar.gz: f072c08de08bac3808112ad165199b98b5b2e507
3
+ metadata.gz: 93348e8748debeefc0be073340665c5024b961af
4
+ data.tar.gz: a4c73f4e8147ba2120d7e3388205fa056128d392
5
5
  SHA512:
6
- metadata.gz: b866b6ba7f26bca01b13043c42ae1e9917b664be9bf77ce0c269dde30298fc8d2a08a54ce247dd465e500ebe8e122e804685ab4855984c1a09088b46422900e7
7
- data.tar.gz: ab9bae0de9a80123cb85e0a34f221b6dce56efc91471c3037fbce10b2c7e284635291704965c1894c419e3b7610da8e1ffa4d83cde4a76039a530ef0b26e7407
6
+ metadata.gz: 1f75f44631fee7348ff9aaf3d24f99b1954d5cef1868cc17f73c44c1dc17918f6eaa158dd35c46a582b31ec7d226384782421cd3c15f33b5a5e1b1f426266d90
7
+ data.tar.gz: 6be3ea5ed0ac0002b4628ad3cc067c0352b4724b9318836e2affe2c05c167132113e00b1ea8515f9e806054a57e3d7cb98a6f3c904f549885960fad72caa4e98
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.4.2
2
+
3
+ - Added `should_index?` method to control which records are indexed
4
+ - Added ability to temporarily disable callbacks
5
+ - Added custom mappings
6
+
1
7
  ## 0.4.1
2
8
 
3
9
  - Fixed issue w/ inheritance mapping
data/README.md CHANGED
@@ -72,6 +72,8 @@ Query like SQL
72
72
  Product.search "2% Milk", where: {in_stock: true}, limit: 10, offset: 50
73
73
  ```
74
74
 
75
+ **Note:** If you prefer the Elasticsearch DSL, see the [Advanced section](#advanced)
76
+
75
77
  Search specific fields
76
78
 
77
79
  ```ruby
@@ -195,6 +197,16 @@ class Product < ActiveRecord::Base
195
197
  end
196
198
  ```
197
199
 
200
+ By default, all records are indexed. To control which records are indexed, use the `should_index?` method.
201
+
202
+ ```ruby
203
+ class Product < ActiveRecord::Base
204
+ def should_index?
205
+ active # only index active records
206
+ end
207
+ end
208
+ ```
209
+
198
210
  ### To Reindex, or Not to Reindex
199
211
 
200
212
  #### Reindex
@@ -494,6 +506,30 @@ Then deploy and reindex:
494
506
  rake searchkick:reindex CLASS=Product
495
507
  ```
496
508
 
509
+ ## Advanced
510
+
511
+ Prefer to use the [Elasticsearch DSL](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-queries.html) but still want awesome features like zero-downtime reindexing?
512
+
513
+ Create a custom mapping:
514
+
515
+ ```ruby
516
+ class Product < ActiveRecord::Base
517
+ searchkick mappings: {
518
+ product: {
519
+ properties: {
520
+ name: {type: "string", analyzer: "keyword"}
521
+ }
522
+ }
523
+ }
524
+ end
525
+ ```
526
+
527
+ And use the `query` option to search:
528
+
529
+ ```ruby
530
+ Product.search query: {match: {name: "milk"}}
531
+ ```
532
+
497
533
  ## Reference
498
534
 
499
535
  Searchkick requires Elasticsearch `0.90.0` or higher.
@@ -527,7 +563,7 @@ class Product < ActiveRecord::Base
527
563
  end
528
564
  ```
529
565
 
530
- Turn off callbacks
566
+ Turn off callbacks permanently
531
567
 
532
568
  ```ruby
533
569
  class Product < ActiveRecord::Base
@@ -535,6 +571,15 @@ class Product < ActiveRecord::Base
535
571
  end
536
572
  ```
537
573
 
574
+ or temporarily
575
+
576
+ ```ruby
577
+ Product.disable_search_callbacks # use Searchkick.disable_callbacks for all models
578
+ ExpensiveProductsTask.execute
579
+ Product.enable_search_callbacks
580
+ Product.reindex
581
+ ```
582
+
538
583
  Eager load associations
539
584
 
540
585
  ```ruby
@@ -8,6 +8,7 @@ module Searchkick
8
8
  class_variable_set :@@searchkick_options, options.dup
9
9
  class_variable_set :@@searchkick_env, ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
10
10
  class_variable_set :@@searchkick_klass, self
11
+ class_variable_set :@@searchkick_callbacks, options[:callbacks] != false
11
12
 
12
13
  # set index name
13
14
  # TODO support proc
@@ -18,19 +19,34 @@ module Searchkick
18
19
  extend Searchkick::Reindex
19
20
  include Searchkick::Similar
20
21
 
21
- def reindex
22
- index = self.class.searchkick_index
23
- if destroyed?
24
- index.remove self
25
- else
26
- index.store self
27
- end
22
+ after_save :reindex
23
+ after_destroy :reindex
24
+
25
+ def self.enable_search_callbacks
26
+ class_variable_set :@@searchkick_callbacks, true
27
+ end
28
+
29
+ def self.disable_search_callbacks
30
+ class_variable_set :@@searchkick_callbacks, false
31
+ end
32
+
33
+ def self.search_callbacks?
34
+ class_variable_get(:@@searchkick_callbacks) && Searchkick.callbacks?
35
+ end
36
+
37
+ def should_index?
38
+ true
28
39
  end
29
40
 
30
- unless options[:callbacks] == false
31
- # TODO ability to temporarily disable
32
- after_save :reindex
33
- after_destroy :reindex
41
+ def reindex
42
+ if self.class.search_callbacks?
43
+ index = self.class.searchkick_index
44
+ if destroyed? or !should_index?
45
+ index.remove self
46
+ else
47
+ index.store self
48
+ end
49
+ end
34
50
  end
35
51
 
36
52
  def search_data
@@ -62,14 +62,14 @@ module Searchkick
62
62
  scope = scope.search_import if scope.respond_to?(:search_import)
63
63
  if scope.respond_to?(:find_in_batches)
64
64
  scope.find_in_batches do |batch|
65
- index.import batch
65
+ index.import batch.select{|item| item.should_index? }
66
66
  end
67
67
  else
68
68
  # https://github.com/karmi/tire/blob/master/lib/tire/model/import.rb
69
69
  # use cursor for Mongoid
70
70
  items = []
71
71
  scope.all.each do |item|
72
- items << item
72
+ items << item if item.should_index?
73
73
  if items.length % 1000 == 0
74
74
  index.import items
75
75
  items = []
@@ -82,174 +82,179 @@ module Searchkick
82
82
  def searchkick_index_options
83
83
  options = searchkick_options
84
84
 
85
- settings = {
86
- analysis: {
87
- analyzer: {
88
- searchkick_keyword: {
89
- type: "custom",
90
- tokenizer: "keyword",
91
- filter: ["lowercase", "snowball"]
92
- },
93
- default_index: {
94
- type: "custom",
95
- tokenizer: "standard",
96
- # synonym should come last, after stemming and shingle
97
- # shingle must come before snowball
98
- filter: ["standard", "lowercase", "asciifolding", "stop", "searchkick_index_shingle", "snowball"]
99
- },
100
- searchkick_search: {
101
- type: "custom",
102
- tokenizer: "standard",
103
- filter: ["standard", "lowercase", "asciifolding", "stop", "searchkick_search_shingle", "snowball"]
104
- },
105
- searchkick_search2: {
106
- type: "custom",
107
- tokenizer: "standard",
108
- filter: ["standard", "lowercase", "asciifolding", "stop", "snowball"]
109
- },
110
- # https://github.com/leschenko/elasticsearch_autocomplete/blob/master/lib/elasticsearch_autocomplete/analyzers.rb
111
- searchkick_autocomplete_index: {
112
- type: "custom",
113
- tokenizer: "searchkick_autocomplete_ngram",
114
- filter: ["lowercase", "asciifolding"]
115
- },
116
- searchkick_autocomplete_search: {
117
- type: "custom",
118
- tokenizer: "keyword",
119
- filter: ["lowercase", "asciifolding"]
120
- },
121
- searchkick_suggest_index: {
122
- type: "custom",
123
- tokenizer: "standard",
124
- filter: ["lowercase", "asciifolding", "searchkick_suggest_shingle"]
125
- }
126
- },
127
- filter: {
128
- searchkick_index_shingle: {
129
- type: "shingle",
130
- token_separator: ""
85
+ if options[:mappings]
86
+ settings = options[:settings] || {}
87
+ mappings = options[:mappings]
88
+ else
89
+ settings = {
90
+ analysis: {
91
+ analyzer: {
92
+ searchkick_keyword: {
93
+ type: "custom",
94
+ tokenizer: "keyword",
95
+ filter: ["lowercase", "snowball"]
96
+ },
97
+ default_index: {
98
+ type: "custom",
99
+ tokenizer: "standard",
100
+ # synonym should come last, after stemming and shingle
101
+ # shingle must come before snowball
102
+ filter: ["standard", "lowercase", "asciifolding", "stop", "searchkick_index_shingle", "snowball"]
103
+ },
104
+ searchkick_search: {
105
+ type: "custom",
106
+ tokenizer: "standard",
107
+ filter: ["standard", "lowercase", "asciifolding", "stop", "searchkick_search_shingle", "snowball"]
108
+ },
109
+ searchkick_search2: {
110
+ type: "custom",
111
+ tokenizer: "standard",
112
+ filter: ["standard", "lowercase", "asciifolding", "stop", "snowball"]
113
+ },
114
+ # https://github.com/leschenko/elasticsearch_autocomplete/blob/master/lib/elasticsearch_autocomplete/analyzers.rb
115
+ searchkick_autocomplete_index: {
116
+ type: "custom",
117
+ tokenizer: "searchkick_autocomplete_ngram",
118
+ filter: ["lowercase", "asciifolding"]
119
+ },
120
+ searchkick_autocomplete_search: {
121
+ type: "custom",
122
+ tokenizer: "keyword",
123
+ filter: ["lowercase", "asciifolding"]
124
+ },
125
+ searchkick_suggest_index: {
126
+ type: "custom",
127
+ tokenizer: "standard",
128
+ filter: ["lowercase", "asciifolding", "searchkick_suggest_shingle"]
129
+ }
131
130
  },
132
- # lucky find http://web.archiveorange.com/archive/v/AAfXfQ17f57FcRINsof7
133
- searchkick_search_shingle: {
134
- type: "shingle",
135
- token_separator: "",
136
- output_unigrams: false,
137
- output_unigrams_if_no_shingles: true
131
+ filter: {
132
+ searchkick_index_shingle: {
133
+ type: "shingle",
134
+ token_separator: ""
135
+ },
136
+ # lucky find http://web.archiveorange.com/archive/v/AAfXfQ17f57FcRINsof7
137
+ searchkick_search_shingle: {
138
+ type: "shingle",
139
+ token_separator: "",
140
+ output_unigrams: false,
141
+ output_unigrams_if_no_shingles: true
142
+ },
143
+ searchkick_suggest_shingle: {
144
+ type: "shingle",
145
+ max_shingle_size: 5
146
+ }
138
147
  },
139
- searchkick_suggest_shingle: {
140
- type: "shingle",
141
- max_shingle_size: 5
142
- }
143
- },
144
- tokenizer: {
145
- searchkick_autocomplete_ngram: {
146
- type: "edgeNGram",
147
- min_gram: 1,
148
- max_gram: 50
148
+ tokenizer: {
149
+ searchkick_autocomplete_ngram: {
150
+ type: "edgeNGram",
151
+ min_gram: 1,
152
+ max_gram: 50
153
+ }
149
154
  }
150
155
  }
151
156
  }
152
- }
153
157
 
154
- if searchkick_env == "test"
155
- settings.merge!(number_of_shards: 1, number_of_replicas: 0)
156
- end
158
+ if searchkick_env == "test"
159
+ settings.merge!(number_of_shards: 1, number_of_replicas: 0)
160
+ end
157
161
 
158
- settings.merge!(options[:settings] || {})
162
+ settings.merge!(options[:settings] || {})
159
163
 
160
- # synonyms
161
- synonyms = options[:synonyms] || []
162
- if synonyms.any?
163
- settings[:analysis][:filter][:searchkick_synonym] = {
164
- type: "synonym",
165
- synonyms: synonyms.select{|s| s.size > 1 }.map{|s| s.join(",") }
166
- }
167
- # choosing a place for the synonym filter when stemming is not easy
168
- # https://groups.google.com/forum/#!topic/elasticsearch/p7qcQlgHdB8
169
- # TODO use a snowball stemmer on synonyms when creating the token filter
164
+ # synonyms
165
+ synonyms = options[:synonyms] || []
166
+ if synonyms.any?
167
+ settings[:analysis][:filter][:searchkick_synonym] = {
168
+ type: "synonym",
169
+ synonyms: synonyms.select{|s| s.size > 1 }.map{|s| s.join(",") }
170
+ }
171
+ # choosing a place for the synonym filter when stemming is not easy
172
+ # https://groups.google.com/forum/#!topic/elasticsearch/p7qcQlgHdB8
173
+ # TODO use a snowball stemmer on synonyms when creating the token filter
170
174
 
171
- # http://elasticsearch-users.115913.n3.nabble.com/synonym-multi-words-search-td4030811.html
172
- # I find the following approach effective if you are doing multi-word synonyms (synonym phrases):
173
- # - Only apply the synonym expansion at index time
174
- # - Don't have the synonym filter applied search
175
- # - Use directional synonyms where appropriate. You want to make sure that you're not injecting terms that are too general.
176
- settings[:analysis][:analyzer][:default_index][:filter].insert(4, "searchkick_synonym")
177
- settings[:analysis][:analyzer][:default_index][:filter] << "searchkick_synonym"
178
- end
175
+ # http://elasticsearch-users.115913.n3.nabble.com/synonym-multi-words-search-td4030811.html
176
+ # I find the following approach effective if you are doing multi-word synonyms (synonym phrases):
177
+ # - Only apply the synonym expansion at index time
178
+ # - Don't have the synonym filter applied search
179
+ # - Use directional synonyms where appropriate. You want to make sure that you're not injecting terms that are too general.
180
+ settings[:analysis][:analyzer][:default_index][:filter].insert(4, "searchkick_synonym")
181
+ settings[:analysis][:analyzer][:default_index][:filter] << "searchkick_synonym"
182
+ end
179
183
 
180
- if options[:special_characters] == false
181
- settings[:analysis][:analyzer].each do |analyzer, analyzer_settings|
182
- analyzer_settings[:filter].reject!{|f| f == "asciifolding" }
184
+ if options[:special_characters] == false
185
+ settings[:analysis][:analyzer].each do |analyzer, analyzer_settings|
186
+ analyzer_settings[:filter].reject!{|f| f == "asciifolding" }
187
+ end
183
188
  end
184
- end
185
189
 
186
- mapping = {}
190
+ mapping = {}
187
191
 
188
- # conversions
189
- if options[:conversions]
190
- mapping[:conversions] = {
191
- type: "nested",
192
- properties: {
193
- query: {type: "string", analyzer: "searchkick_keyword"},
194
- count: {type: "integer"}
192
+ # conversions
193
+ if options[:conversions]
194
+ mapping[:conversions] = {
195
+ type: "nested",
196
+ properties: {
197
+ query: {type: "string", analyzer: "searchkick_keyword"},
198
+ count: {type: "integer"}
199
+ }
195
200
  }
196
- }
197
- end
201
+ end
198
202
 
199
- # autocomplete and suggest
200
- autocomplete = (options[:autocomplete] || []).map(&:to_s)
201
- suggest = (options[:suggest] || []).map(&:to_s)
202
- (autocomplete + suggest).uniq.each do |field|
203
- field_mapping = {
204
- type: "multi_field",
205
- fields: {
206
- field => {type: "string", index: "not_analyzed"},
207
- "analyzed" => {type: "string", index: "analyzed"}
208
- # term_vector: "with_positions_offsets" for fast / correct highlighting
209
- # http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-highlighting.html#_fast_vector_highlighter
203
+ # autocomplete and suggest
204
+ autocomplete = (options[:autocomplete] || []).map(&:to_s)
205
+ suggest = (options[:suggest] || []).map(&:to_s)
206
+ (autocomplete + suggest).uniq.each do |field|
207
+ field_mapping = {
208
+ type: "multi_field",
209
+ fields: {
210
+ field => {type: "string", index: "not_analyzed"},
211
+ "analyzed" => {type: "string", index: "analyzed"}
212
+ # term_vector: "with_positions_offsets" for fast / correct highlighting
213
+ # http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-highlighting.html#_fast_vector_highlighter
214
+ }
210
215
  }
211
- }
212
- if autocomplete.include?(field)
213
- field_mapping[:fields]["autocomplete"] = {type: "string", index: "analyzed", analyzer: "searchkick_autocomplete_index"}
214
- end
215
- if suggest.include?(field)
216
- field_mapping[:fields]["suggest"] = {type: "string", index: "analyzed", analyzer: "searchkick_suggest_index"}
216
+ if autocomplete.include?(field)
217
+ field_mapping[:fields]["autocomplete"] = {type: "string", index: "analyzed", analyzer: "searchkick_autocomplete_index"}
218
+ end
219
+ if suggest.include?(field)
220
+ field_mapping[:fields]["suggest"] = {type: "string", index: "analyzed", analyzer: "searchkick_suggest_index"}
221
+ end
222
+ mapping[field] = field_mapping
217
223
  end
218
- mapping[field] = field_mapping
219
- end
220
224
 
221
- (options[:locations] || []).each do |field|
222
- mapping[field] = {
223
- type: "geo_point"
224
- }
225
- end
225
+ (options[:locations] || []).each do |field|
226
+ mapping[field] = {
227
+ type: "geo_point"
228
+ }
229
+ end
226
230
 
227
- mappings = {
228
- _default_: {
229
- properties: mapping,
230
- # https://gist.github.com/kimchy/2898285
231
- dynamic_templates: [
232
- {
233
- string_template: {
234
- match: "*",
235
- match_mapping_type: "string",
236
- mapping: {
237
- # http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
238
- type: "multi_field",
239
- fields: {
240
- # analyzed field must be the default field for include_in_all
231
+ mappings = {
232
+ _default_: {
233
+ properties: mapping,
234
+ # https://gist.github.com/kimchy/2898285
235
+ dynamic_templates: [
236
+ {
237
+ string_template: {
238
+ match: "*",
239
+ match_mapping_type: "string",
240
+ mapping: {
241
241
  # http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
242
- # however, we can include the not_analyzed field in _all
243
- # and the _all index analyzer will take care of it
244
- "{name}" => {type: "string", index: "not_analyzed"},
245
- "analyzed" => {type: "string", index: "analyzed"}
242
+ type: "multi_field",
243
+ fields: {
244
+ # analyzed field must be the default field for include_in_all
245
+ # http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
246
+ # however, we can include the not_analyzed field in _all
247
+ # and the _all index analyzer will take care of it
248
+ "{name}" => {type: "string", index: "not_analyzed"},
249
+ "analyzed" => {type: "string", index: "analyzed"}
250
+ }
246
251
  }
247
252
  }
248
253
  }
249
- }
250
- ]
254
+ ]
255
+ }
251
256
  }
252
- }
257
+ end
253
258
 
254
259
  {
255
260
  settings: settings,
@@ -2,7 +2,13 @@ module Searchkick
2
2
  module Search
3
3
 
4
4
  def search(term, options = {})
5
- term = term.to_s
5
+ if term.is_a?(Hash)
6
+ options = term
7
+ term = nil
8
+ else
9
+ term = term.to_s
10
+ end
11
+
6
12
  fields =
7
13
  if options[:fields]
8
14
  if options[:autocomplete]
@@ -35,7 +41,9 @@ module Searchkick
35
41
 
36
42
  all = term == "*"
37
43
 
38
- if options[:similar]
44
+ if options[:query]
45
+ payload = options[:query]
46
+ elsif options[:similar]
39
47
  payload = {
40
48
  more_like_this: {
41
49
  fields: fields,
@@ -1,3 +1,3 @@
1
1
  module Searchkick
2
- VERSION = "0.4.1"
2
+ VERSION = "0.4.2"
3
3
  end
data/lib/searchkick.rb CHANGED
@@ -8,6 +8,22 @@ require "searchkick/model"
8
8
  require "searchkick/tasks"
9
9
  require "searchkick/logger" if defined?(Rails)
10
10
 
11
+ module Searchkick
12
+ @callbacks = true
13
+
14
+ def self.enable_callbacks
15
+ @callbacks = true
16
+ end
17
+
18
+ def self.disable_callbacks
19
+ @callbacks = false
20
+ end
21
+
22
+ def self.callbacks?
23
+ @callbacks
24
+ end
25
+ end
26
+
11
27
  # TODO find better ActiveModel hook
12
28
  ActiveModel::Callbacks.send(:include, Searchkick::Model)
13
29
  ActiveRecord::Base.send(:extend, Searchkick::Model) if defined?(ActiveRecord)
data/test/index_test.rb CHANGED
@@ -26,4 +26,10 @@ class TestIndex < Minitest::Unit::TestCase
26
26
  assert !old_index.exists?
27
27
  end
28
28
 
29
+ def test_mapping
30
+ store_names ["Dollar Tree"], Store
31
+ assert_equal [], Store.search(query: {match: {name: "dollar"}}).map(&:name)
32
+ assert_equal ["Dollar Tree"], Store.search(query: {match: {name: "Dollar Tree"}}).map(&:name)
33
+ end
34
+
29
35
  end
@@ -2,11 +2,6 @@ require_relative "test_helper"
2
2
 
3
3
  class TestInheritance < Minitest::Unit::TestCase
4
4
 
5
- def setup
6
- super
7
- Animal.destroy_all
8
- end
9
-
10
5
  def test_child_reindex
11
6
  store_names ["Max"], Cat
12
7
  assert Dog.reindex
@@ -0,0 +1,35 @@
1
+ require_relative "test_helper"
2
+
3
+ class TestModel < Minitest::Unit::TestCase
4
+
5
+ def test_disable_callbacks_model
6
+ store_names ["product a"]
7
+
8
+ Product.disable_search_callbacks
9
+ assert !Product.search_callbacks?
10
+
11
+ store_names ["product b"]
12
+ assert_search "product", ["product a"]
13
+
14
+ Product.enable_search_callbacks
15
+ Product.reindex
16
+
17
+ assert_search "product", ["product a", "product b"]
18
+ end
19
+
20
+ def test_disable_callbacks_global
21
+ store_names ["product a"]
22
+
23
+ Searchkick.disable_callbacks
24
+ assert !Searchkick.callbacks?
25
+
26
+ store_names ["product b"]
27
+ assert_search "product", ["product a"]
28
+
29
+ Searchkick.enable_callbacks
30
+ Product.reindex
31
+
32
+ assert_search "product", ["product a", "product b"]
33
+ end
34
+
35
+ end
@@ -0,0 +1,34 @@
1
+ require_relative "test_helper"
2
+
3
+ class TestShouldIndex < Minitest::Unit::TestCase
4
+
5
+ def test_basic
6
+ store_names ["INDEX", "DO NOT INDEX"]
7
+ assert_search "index", ["INDEX"]
8
+ end
9
+
10
+ def test_default_true
11
+ assert Animal.new.should_index?
12
+ end
13
+
14
+ def test_change_to_true
15
+ store_names ["DO NOT INDEX"]
16
+ assert_search "index", []
17
+ product = Product.first
18
+ product.name = "INDEX"
19
+ product.save!
20
+ Product.searchkick_index.refresh
21
+ assert_search "index", ["INDEX"]
22
+ end
23
+
24
+ def test_change_to_false
25
+ store_names ["INDEX"]
26
+ assert_search "index", ["INDEX"]
27
+ product = Product.first
28
+ product.name = "DO NOT INDEX"
29
+ product.save!
30
+ Product.searchkick_index.refresh
31
+ assert_search "index", []
32
+ end
33
+
34
+ end
data/test/test_helper.rb CHANGED
@@ -33,6 +33,8 @@ if defined?(Mongoid)
33
33
 
34
34
  class Store
35
35
  include Mongoid::Document
36
+
37
+ field :name
36
38
  end
37
39
 
38
40
  class Animal
@@ -73,6 +75,7 @@ else
73
75
  end
74
76
 
75
77
  ActiveRecord::Migration.create_table :stores, :force => true do |t|
78
+ t.string :name
76
79
  end
77
80
 
78
81
  ActiveRecord::Migration.create_table :animals, :force => true do |t|
@@ -119,6 +122,20 @@ class Product
119
122
  def search_data
120
123
  serializable_hash.merge conversions: conversions, user_ids: user_ids, location: [latitude, longitude], multiple_locations: [[latitude, longitude], [0, 0]]
121
124
  end
125
+
126
+ def should_index?
127
+ name != "DO NOT INDEX"
128
+ end
129
+ end
130
+
131
+ class Store
132
+ searchkick mappings: {
133
+ store: {
134
+ properties: {
135
+ name: {type: "string", analyzer: "keyword"}
136
+ }
137
+ }
138
+ }
122
139
  end
123
140
 
124
141
  class Animal
@@ -129,12 +146,14 @@ Product.searchkick_index.delete if Product.searchkick_index.exists?
129
146
  Product.reindex
130
147
  Product.reindex # run twice for both index paths
131
148
 
149
+ Store.reindex
132
150
  Animal.reindex
133
151
 
134
152
  class Minitest::Unit::TestCase
135
153
 
136
154
  def setup
137
155
  Product.destroy_all
156
+ Animal.destroy_all
138
157
  end
139
158
 
140
159
  protected
@@ -151,16 +170,16 @@ class Minitest::Unit::TestCase
151
170
  end
152
171
 
153
172
  # no order
154
- def assert_search(term, expected, options = {})
155
- assert_equal expected.sort, Product.search(term, options).map(&:name).sort
173
+ def assert_search(term, expected, options = {}, klass = Product)
174
+ assert_equal expected.sort, klass.search(term, options).map(&:name).sort
156
175
  end
157
176
 
158
- def assert_order(term, expected, options = {})
159
- assert_equal expected, Product.search(term, options).map(&:name)
177
+ def assert_order(term, expected, options = {}, klass = Product)
178
+ assert_equal expected, klass.search(term, options).map(&:name)
160
179
  end
161
180
 
162
- def assert_first(term, expected, options = {})
163
- assert_equal expected, Product.search(term, options).map(&:name).first
181
+ def assert_first(term, expected, options = {}, klass = Product)
182
+ assert_equal expected, klass.search(term, options).map(&:name).first
164
183
  end
165
184
 
166
185
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: searchkick
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-20 00:00:00.000000000 Z
11
+ date: 2013-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tire
@@ -141,6 +141,8 @@ files:
141
141
  - test/index_test.rb
142
142
  - test/inheritance_test.rb
143
143
  - test/match_test.rb
144
+ - test/model_test.rb
145
+ - test/should_index_test.rb
144
146
  - test/similar_test.rb
145
147
  - test/sql_test.rb
146
148
  - test/suggest_test.rb
@@ -178,6 +180,8 @@ test_files:
178
180
  - test/index_test.rb
179
181
  - test/inheritance_test.rb
180
182
  - test/match_test.rb
183
+ - test/model_test.rb
184
+ - test/should_index_test.rb
181
185
  - test/similar_test.rb
182
186
  - test/sql_test.rb
183
187
  - test/suggest_test.rb