algoliasearch-rails 1.7.0 → 1.7.1
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.
- checksums.yaml +4 -4
- data/ChangeLog +5 -0
- data/Gemfile +4 -1
- data/Gemfile.lock +23 -1
- data/README.md +93 -0
- data/Rakefile +0 -18
- data/VERSION +1 -1
- data/algoliasearch-rails.gemspec +1 -1
- data/lib/algoliasearch-rails.rb +139 -82
- data/spec/spec_helper.rb +2 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2aa68e2724bc3f0c7b43545b8d5156ae476acfde
|
4
|
+
data.tar.gz: 4e3d1a69ce8cff145fc91b69f845cb2c38bde8bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e685c99823cb8f047b1bfd8d390a5b2a535df639586f6e7e8d92fe5eb60b546370f2697bfbc07a3afbfc067195ec23ad7b81a17645699ac93b974dbb2331811
|
7
|
+
data.tar.gz: bf4848ce707351534dbe3fe03f952419a721a3ce4e37b7ecaf84c90c574721a1edae0373ec74eab936bf0146ee267fbbcc700a84eefeb13e02a1d1f7b3dce916
|
data/ChangeLog
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
|
3
|
+
2014-01-31 1.7.1
|
4
|
+
|
5
|
+
* Ensure methods are not conflicting with already defined ones (use algolia_METHOD_NAME)
|
6
|
+
* Add ```:if``` and ```:unless``` options to control objects indexing
|
7
|
+
|
3
8
|
2014-01-07 1.7.0
|
4
9
|
|
5
10
|
* Updated algoliasearch to 1.2 (httpclient instead of curb as underlying HTTP layer)
|
data/Gemfile
CHANGED
@@ -7,7 +7,10 @@ gem 'rubysl', '~> 2.0', platform: :rbx
|
|
7
7
|
group :test do
|
8
8
|
gem 'rspec', '>= 2.5.0'
|
9
9
|
gem 'activerecord', '>= 3.0.7'
|
10
|
-
gem 'sqlite3'
|
10
|
+
gem 'sqlite3', platform: [:rbx, :ruby]
|
11
|
+
gem 'jdbc-sqlite3', platform: :jruby
|
12
|
+
gem 'activerecord-jdbc-adapter', platform: :jruby
|
13
|
+
gem 'activerecord-jdbcsqlite3-adapter', platform: :jruby
|
11
14
|
gem 'autotest'
|
12
15
|
gem 'autotest-fsevent'
|
13
16
|
gem 'redgreen'
|
data/Gemfile.lock
CHANGED
@@ -17,6 +17,11 @@ GEM
|
|
17
17
|
activesupport (= 4.0.2)
|
18
18
|
arel (~> 4.0.0)
|
19
19
|
activerecord-deprecated_finders (1.0.3)
|
20
|
+
activerecord-jdbc-adapter (1.3.4)
|
21
|
+
activerecord (>= 2.2)
|
22
|
+
activerecord-jdbcsqlite3-adapter (1.3.4)
|
23
|
+
activerecord-jdbc-adapter (~> 1.3.4)
|
24
|
+
jdbc-sqlite3 (~> 3.7.2)
|
20
25
|
activesupport (4.0.2)
|
21
26
|
i18n (~> 0.6, >= 0.6.4)
|
22
27
|
minitest (~> 4.2)
|
@@ -29,12 +34,13 @@ GEM
|
|
29
34
|
json (>= 1.5.1)
|
30
35
|
arel (4.0.1)
|
31
36
|
atomic (1.1.14)
|
37
|
+
atomic (1.1.14-java)
|
32
38
|
autotest (4.4.6)
|
33
39
|
ZenTest (>= 4.4.1)
|
34
40
|
autotest-fsevent (0.2.9)
|
35
41
|
sys-uname
|
36
42
|
autotest-growl (0.2.16)
|
37
|
-
backports (3.
|
43
|
+
backports (3.4.0)
|
38
44
|
builder (3.1.4)
|
39
45
|
coderay (1.1.0)
|
40
46
|
diff-lcs (1.2.5)
|
@@ -47,6 +53,7 @@ GEM
|
|
47
53
|
faraday_middleware (0.9.0)
|
48
54
|
faraday (>= 0.7.4, < 0.9)
|
49
55
|
ffi (1.9.3)
|
56
|
+
ffi (1.9.3-java)
|
50
57
|
ffi2-generators (0.1.1)
|
51
58
|
gh (0.13.0)
|
52
59
|
addressable
|
@@ -58,7 +65,9 @@ GEM
|
|
58
65
|
highline (1.6.20)
|
59
66
|
httpclient (2.3.4.1)
|
60
67
|
i18n (0.6.9)
|
68
|
+
jdbc-sqlite3 (3.7.2.1)
|
61
69
|
json (1.8.1)
|
70
|
+
json (1.8.1-java)
|
62
71
|
kaminari (0.15.0)
|
63
72
|
actionpack (>= 3.0.0)
|
64
73
|
activesupport (>= 3.0.0)
|
@@ -75,6 +84,11 @@ GEM
|
|
75
84
|
coderay (~> 1.0)
|
76
85
|
method_source (~> 0.8)
|
77
86
|
slop (~> 3.4)
|
87
|
+
pry (0.9.12.4-java)
|
88
|
+
coderay (~> 1.0)
|
89
|
+
method_source (~> 0.8)
|
90
|
+
slop (~> 3.4)
|
91
|
+
spoon (~> 0.0)
|
78
92
|
pusher-client (0.4.0)
|
79
93
|
websocket (~> 1.0.0)
|
80
94
|
rack (1.5.2)
|
@@ -295,11 +309,15 @@ GEM
|
|
295
309
|
rubysl-yaml (2.0.4)
|
296
310
|
rubysl-zlib (2.0.1)
|
297
311
|
slop (3.4.7)
|
312
|
+
spoon (0.0.4)
|
313
|
+
ffi
|
298
314
|
sqlite3 (1.3.8)
|
299
315
|
sys-uname (0.9.2)
|
300
316
|
ffi (>= 1.0.0)
|
301
317
|
thread_safe (0.1.3)
|
302
318
|
atomic
|
319
|
+
thread_safe (0.1.3-java)
|
320
|
+
atomic
|
303
321
|
travis (1.6.6)
|
304
322
|
addressable (~> 2.3)
|
305
323
|
backports
|
@@ -318,14 +336,18 @@ GEM
|
|
318
336
|
will_paginate (3.0.5)
|
319
337
|
|
320
338
|
PLATFORMS
|
339
|
+
java
|
321
340
|
ruby
|
322
341
|
|
323
342
|
DEPENDENCIES
|
324
343
|
activerecord (>= 3.0.7)
|
344
|
+
activerecord-jdbc-adapter
|
345
|
+
activerecord-jdbcsqlite3-adapter
|
325
346
|
algoliasearch (~> 1.2)
|
326
347
|
autotest
|
327
348
|
autotest-fsevent
|
328
349
|
autotest-growl
|
350
|
+
jdbc-sqlite3
|
329
351
|
json (>= 1.5.1)
|
330
352
|
kaminari
|
331
353
|
rake
|
data/README.md
CHANGED
@@ -16,6 +16,7 @@ Table of Content
|
|
16
16
|
1. [Setup](#setup)
|
17
17
|
1. [Quick Start](#quick-start)
|
18
18
|
1. [Options](#options)
|
19
|
+
1. [Configuration example](#configuration-example)
|
19
20
|
1. [Indexing](#indexing)
|
20
21
|
1. [Tags](#tags)
|
21
22
|
1. [Geo-search](#geo-search)
|
@@ -105,6 +106,14 @@ end
|
|
105
106
|
p Contact.search("jon doe")
|
106
107
|
```
|
107
108
|
|
109
|
+
**Notes:** All methods injected by the ```AlgoliaSearch``` include are prefixed by ```algolia_``` and aliased to the associated short names if they aren't already defined.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
Contact.algolia_reindex! # <=> Contact.reindex!
|
113
|
+
|
114
|
+
Contact.algolia_search("jon doe") # <=> Contact.search("jon doe")
|
115
|
+
```
|
116
|
+
|
108
117
|
Options
|
109
118
|
----------
|
110
119
|
|
@@ -194,6 +203,90 @@ class UniqUser < ActiveRecord::Base
|
|
194
203
|
end
|
195
204
|
```
|
196
205
|
|
206
|
+
You can add constraints controlling if a record must be indexed by using options the ```:if``` or ```:unless``` options.
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
class Post < ActiveRecord::Base
|
210
|
+
include AlgoliaSearch
|
211
|
+
|
212
|
+
algoliasearch if: :published?, unless: :deleted? do
|
213
|
+
end
|
214
|
+
|
215
|
+
def published?
|
216
|
+
# [...]
|
217
|
+
end
|
218
|
+
|
219
|
+
def deleted?
|
220
|
+
# [...]
|
221
|
+
end
|
222
|
+
end
|
223
|
+
```
|
224
|
+
|
225
|
+
Configuration example
|
226
|
+
---------------------
|
227
|
+
|
228
|
+
Here is a real-word configuration example (from [HN Search](https://github.com/algolia/hn-search)):
|
229
|
+
|
230
|
+
```ruby
|
231
|
+
class Item < ActiveRecord::Base
|
232
|
+
include AlgoliaSearch
|
233
|
+
|
234
|
+
algoliasearch per_environment: true do
|
235
|
+
# the list of attributes sent to Algolia's API
|
236
|
+
attribute :created_at, :title, :url, :author, :points, :story_text, :comment_text, :author, :num_comments, :story_id, :story_title, :
|
237
|
+
|
238
|
+
# integer version of the created_at datetime field, to use numerical filtering
|
239
|
+
attribute :created_at_i do
|
240
|
+
created_at.to_i
|
241
|
+
end
|
242
|
+
|
243
|
+
# `title` is more important than `{story,comment}_text`, `{story,comment}_text` more than `url`, `url` more than `author`
|
244
|
+
# btw, do not take into account position in most fields to avoid first word match boost
|
245
|
+
attributesToIndex ['unordered(title)', 'unordered(story_text)', 'unordered(comment_text)', 'unordered(url)', 'author', 'created_at_i']
|
246
|
+
|
247
|
+
# list of attributes to highlight
|
248
|
+
attributesToHighlight ['title', 'story_text', 'comment_text', 'url', 'story_url', 'author', 'story_title']
|
249
|
+
|
250
|
+
# tags used for filtering
|
251
|
+
tags do
|
252
|
+
[item_type, "author_#{author}", "story_#{story_id}"]
|
253
|
+
end
|
254
|
+
|
255
|
+
# use associated number of HN points to sort results (last sort criteria)
|
256
|
+
customRanking ['desc(points)', 'desc(num_comments)']
|
257
|
+
|
258
|
+
# controls the way results are sorted sorting on the following 4 criteria (one after another)
|
259
|
+
# I removed the 'exact' match critera (improve 1-words query relevance, doesn't fit HNSearch needs)
|
260
|
+
ranking ['typo', 'proximity', 'attribute', 'custom']
|
261
|
+
|
262
|
+
# google+, $1.5M raises, C#: we love you
|
263
|
+
separatorsToIndex '+#$'
|
264
|
+
end
|
265
|
+
|
266
|
+
def story_text
|
267
|
+
item_type_cd != Item.comment ? text : nil
|
268
|
+
end
|
269
|
+
|
270
|
+
def story_title
|
271
|
+
comment? && story ? story.title : nil
|
272
|
+
end
|
273
|
+
|
274
|
+
def story_url
|
275
|
+
comment? && story ? story.url : nil
|
276
|
+
end
|
277
|
+
|
278
|
+
def comment_text
|
279
|
+
comment? ? text : nil
|
280
|
+
end
|
281
|
+
|
282
|
+
def comment?
|
283
|
+
item_type_cd == Item.comment
|
284
|
+
end
|
285
|
+
|
286
|
+
# [...]
|
287
|
+
end
|
288
|
+
```
|
289
|
+
|
197
290
|
Indexing
|
198
291
|
---------
|
199
292
|
|
data/Rakefile
CHANGED
@@ -1,24 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
3
|
|
4
|
-
begin
|
5
|
-
require 'jeweler'
|
6
|
-
Jeweler::Tasks.new do |gem|
|
7
|
-
gem.name = "algoliasearch-rails"
|
8
|
-
gem.summary = %Q{AlgoliaSearch integration to your favorite ORM}
|
9
|
-
gem.description = %Q{AlgoliaSearch integration to your favorite ORM}
|
10
|
-
gem.homepage = "http://github.com/algolia/algoliasearch-rails"
|
11
|
-
gem.email = "contact@algolia.com"
|
12
|
-
gem.authors = ["Algolia"]
|
13
|
-
gem.files.exclude 'spec/integration_spec.rb'
|
14
|
-
gem.license = "MIT"
|
15
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
-
end
|
17
|
-
Jeweler::RubygemsDotOrgTasks.new
|
18
|
-
rescue LoadError
|
19
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
|
-
end
|
21
|
-
|
22
4
|
require 'rdoc/task'
|
23
5
|
Rake::RDocTask.new do |rdoc|
|
24
6
|
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.7.
|
1
|
+
1.7.1
|
data/algoliasearch-rails.gemspec
CHANGED
data/lib/algoliasearch-rails.rb
CHANGED
@@ -36,8 +36,10 @@ module AlgoliaSearch
|
|
36
36
|
@included_in << klass
|
37
37
|
@included_in.uniq!
|
38
38
|
|
39
|
-
klass.
|
40
|
-
|
39
|
+
klass.class_eval do
|
40
|
+
extend ClassMethods
|
41
|
+
include InstanceMethods
|
42
|
+
end
|
41
43
|
end
|
42
44
|
|
43
45
|
end
|
@@ -49,7 +51,8 @@ module AlgoliaSearch
|
|
49
51
|
:minWordSizefor2Typos, :hitsPerPage, :attributesToRetrieve,
|
50
52
|
:attributesToHighlight, :attributesToSnippet, :attributesToIndex,
|
51
53
|
:ranking, :customRanking, :queryType, :attributesForFaceting,
|
52
|
-
:separatorsToIndex, :optionalWords, :attributeForDistinct
|
54
|
+
:separatorsToIndex, :optionalWords, :attributeForDistinct,
|
55
|
+
:if, :unless]
|
53
56
|
OPTIONS.each do |k|
|
54
57
|
define_method k do |v|
|
55
58
|
instance_variable_set("@#{k}", v)
|
@@ -117,126 +120,145 @@ module AlgoliaSearch
|
|
117
120
|
# these are the class methods added when AlgoliaSearch is included
|
118
121
|
module ClassMethods
|
119
122
|
|
123
|
+
def self.extended(base)
|
124
|
+
class <<base
|
125
|
+
alias_method :without_auto_index, :algolia_without_auto_index unless method_defined? :without_auto_index
|
126
|
+
alias_method :reindex!, :algolia_reindex! unless method_defined? :reindex!
|
127
|
+
alias_method :index!, :algolia_index! unless method_defined? :index!
|
128
|
+
alias_method :remove_from_index!, :algolia_remove_from_index! unless method_defined? :remove_from_index!
|
129
|
+
alias_method :clear_index!, :algolia_clear_index! unless method_defined? :clear_index!
|
130
|
+
alias_method :search, :algolia_search unless method_defined? :search
|
131
|
+
alias_method :index, :algolia_index unless method_defined? :index
|
132
|
+
alias_method :index_name, :algolia_index_name unless method_defined? :index_name
|
133
|
+
alias_method :must_reindex?, :algolia_must_reindex? unless method_defined? :must_reindex?
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
120
137
|
def algoliasearch(options = {}, &block)
|
121
|
-
@
|
122
|
-
@
|
123
|
-
@
|
138
|
+
@algolia_index_settings = IndexSettings.new(block_given? ? Proc.new : nil)
|
139
|
+
@algolia_settings = @algolia_index_settings.to_settings
|
140
|
+
@algolia_options = { type: algolia_full_const_get(model_name.to_s), per_page: @algolia_index_settings.get_setting(:hitsPerPage) || 10, page: 1 }.merge(options)
|
124
141
|
|
125
142
|
attr_accessor :highlight_result
|
126
143
|
|
127
144
|
if options[:synchronous] == true
|
128
|
-
after_validation :
|
145
|
+
after_validation :algolia_mark_synchronous if respond_to?(:before_validation)
|
129
146
|
end
|
130
147
|
unless options[:auto_index] == false
|
131
|
-
after_validation :
|
132
|
-
before_save :
|
133
|
-
after_save :
|
148
|
+
after_validation :algolia_mark_must_reindex if respond_to?(:after_validation)
|
149
|
+
before_save :algolia_mark_for_auto_indexing if respond_to?(:before_save)
|
150
|
+
after_save :algolia_perform_index_tasks if respond_to?(:after_save)
|
134
151
|
end
|
135
152
|
unless options[:auto_remove] == false
|
136
153
|
after_destroy { |searchable| searchable.remove_from_index! } if respond_to?(:after_destroy)
|
137
154
|
end
|
138
155
|
end
|
139
156
|
|
140
|
-
def
|
141
|
-
@
|
157
|
+
def algolia_without_auto_index(&block)
|
158
|
+
@algolia_without_auto_index_scope = true
|
142
159
|
begin
|
143
160
|
yield
|
144
161
|
ensure
|
145
|
-
@
|
162
|
+
@algolia_without_auto_index_scope = false
|
146
163
|
end
|
147
164
|
end
|
148
165
|
|
149
|
-
def
|
150
|
-
return if @
|
151
|
-
|
166
|
+
def algolia_reindex!(batch_size = 1000, synchronous = false)
|
167
|
+
return if @algolia_without_auto_index_scope
|
168
|
+
algolia_ensure_init
|
152
169
|
last_task = nil
|
153
170
|
find_in_batches(batch_size: batch_size) do |group|
|
154
|
-
|
155
|
-
|
171
|
+
group.select! { |o| algolia_indexable?(o) } if algolia_conditional_index?
|
172
|
+
objects = group.map { |o| @algolia_index_settings.get_attributes(o).merge 'objectID' => algolia_object_id_of(o) }
|
173
|
+
last_task = @algolia_index.save_objects(objects)
|
156
174
|
end
|
157
|
-
@
|
175
|
+
@algolia_index.wait_task(last_task["taskID"]) if last_task and synchronous == true
|
158
176
|
end
|
159
177
|
|
160
|
-
def
|
161
|
-
return if @
|
162
|
-
|
178
|
+
def algolia_index!(object, synchronous = false)
|
179
|
+
return if @algolia_without_auto_index_scope || !algolia_indexable?(object)
|
180
|
+
algolia_ensure_init
|
163
181
|
if synchronous
|
164
|
-
@
|
182
|
+
@algolia_index.add_object!(@algolia_index_settings.get_attributes(object), algolia_object_id_of(object))
|
165
183
|
else
|
166
|
-
@
|
184
|
+
@algolia_index.add_object(@algolia_index_settings.get_attributes(object), algolia_object_id_of(object))
|
167
185
|
end
|
168
186
|
end
|
169
187
|
|
170
|
-
def
|
171
|
-
return if @
|
172
|
-
|
188
|
+
def algolia_remove_from_index!(object, synchronous = false)
|
189
|
+
return if @algolia_without_auto_index_scope
|
190
|
+
algolia_ensure_init
|
173
191
|
if synchronous
|
174
|
-
@
|
192
|
+
@algolia_index.delete_object!(algolia_object_id_of(object))
|
175
193
|
else
|
176
|
-
@
|
194
|
+
@algolia_index.delete_object(algolia_object_id_of(object))
|
177
195
|
end
|
178
196
|
end
|
179
197
|
|
180
|
-
def
|
181
|
-
|
182
|
-
synchronous ? @
|
183
|
-
@
|
198
|
+
def algolia_clear_index!(synchronous = false)
|
199
|
+
algolia_ensure_init
|
200
|
+
synchronous ? @algolia_index.clear! : @algolia_index.clear
|
201
|
+
@algolia_index = nil
|
184
202
|
end
|
185
203
|
|
186
|
-
def
|
187
|
-
|
188
|
-
json = @
|
204
|
+
def algolia_search(q, settings = {})
|
205
|
+
algolia_ensure_init
|
206
|
+
json = @algolia_index.search(q, Hash[settings.map { |k,v| [k.to_s, v.to_s] }])
|
189
207
|
results = json['hits'].map do |hit|
|
190
|
-
o = @
|
191
|
-
o
|
192
|
-
|
193
|
-
|
194
|
-
|
208
|
+
o = @algolia_options[:type].where(algolia_object_id_method => hit['objectID']).first
|
209
|
+
if o
|
210
|
+
o.highlight_result = hit['_highlightResult']
|
211
|
+
o
|
212
|
+
end
|
213
|
+
end.compact
|
214
|
+
AlgoliaSearch::Pagination.create(results, json['nbHits'].to_i, @algolia_options)
|
195
215
|
end
|
196
216
|
|
197
|
-
def
|
198
|
-
|
199
|
-
@
|
200
|
-
current_settings = @index.get_settings rescue nil # if the index doesn't exist
|
201
|
-
@index.set_settings(@settings) if index_settings_changed?(current_settings, @settings)
|
217
|
+
def algolia_index
|
218
|
+
algolia_ensure_init
|
219
|
+
@algolia_index
|
202
220
|
end
|
203
221
|
|
204
|
-
def
|
205
|
-
|
206
|
-
@
|
222
|
+
def algolia_index_name
|
223
|
+
name = @algolia_options[:index_name] || model_name.to_s.gsub('::', '_')
|
224
|
+
name = "#{name}_#{Rails.env.to_s}" if @algolia_options[:per_environment]
|
225
|
+
name
|
207
226
|
end
|
208
227
|
|
209
|
-
def
|
210
|
-
return true if
|
211
|
-
@
|
228
|
+
def algolia_must_reindex?(object)
|
229
|
+
return true if algolia_object_id_changed?(object)
|
230
|
+
@algolia_index_settings.get_attributes(object).each do |k, v|
|
212
231
|
changed_method = "#{k}_changed?"
|
213
232
|
return true if object.respond_to?(changed_method) && object.send(changed_method)
|
214
233
|
end
|
215
234
|
return false
|
216
235
|
end
|
217
236
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
237
|
+
protected
|
238
|
+
|
239
|
+
def algolia_ensure_init
|
240
|
+
return if @algolia_index
|
241
|
+
@algolia_index = Algolia::Index.new(algolia_index_name)
|
242
|
+
current_settings = @algolia_index.get_settings rescue nil # if the index doesn't exist
|
243
|
+
@algolia_index.set_settings(@algolia_settings) if algolia_index_settings_changed?(current_settings, @algolia_settings)
|
222
244
|
end
|
223
245
|
|
224
246
|
private
|
225
247
|
|
226
|
-
def
|
227
|
-
@
|
248
|
+
def algolia_object_id_method
|
249
|
+
@algolia_options[:id] || @algolia_options[:object_id] || :id
|
228
250
|
end
|
229
251
|
|
230
|
-
def
|
231
|
-
o.send(
|
252
|
+
def algolia_object_id_of(o)
|
253
|
+
o.send(algolia_object_id_method).to_s
|
232
254
|
end
|
233
255
|
|
234
|
-
def
|
235
|
-
m = "#{
|
256
|
+
def algolia_object_id_changed?(o)
|
257
|
+
m = "#{algolia_object_id_method}_changed?"
|
236
258
|
o.respond_to?(m) ? o.send(m) : false
|
237
259
|
end
|
238
260
|
|
239
|
-
def
|
261
|
+
def algolia_index_settings_changed?(prev, current)
|
240
262
|
return true if prev.nil?
|
241
263
|
current.each do |k, v|
|
242
264
|
prev_v = prev[k.to_s]
|
@@ -250,7 +272,7 @@ module AlgoliaSearch
|
|
250
272
|
false
|
251
273
|
end
|
252
274
|
|
253
|
-
def
|
275
|
+
def algolia_full_const_get(name)
|
254
276
|
list = name.split('::')
|
255
277
|
list.shift if list.first.blank?
|
256
278
|
obj = self
|
@@ -262,43 +284,78 @@ module AlgoliaSearch
|
|
262
284
|
obj
|
263
285
|
end
|
264
286
|
|
287
|
+
def algolia_conditional_index?
|
288
|
+
@algolia_options[:if].present? || @algolia_options[:unless].present?
|
289
|
+
end
|
290
|
+
|
291
|
+
def algolia_indexable?(object)
|
292
|
+
if_passes = @algolia_options[:if].blank? || algolia_constraint_passes?(object, @algolia_options[:if])
|
293
|
+
unless_passes = @algolia_options[:unless].blank? || !algolia_constraint_passes?(object, @algolia_options[:unless])
|
294
|
+
if_passes && unless_passes
|
295
|
+
end
|
296
|
+
|
297
|
+
def algolia_constraint_passes?(object, constraint)
|
298
|
+
case constraint
|
299
|
+
when Symbol
|
300
|
+
object.send(constraint)
|
301
|
+
when String
|
302
|
+
object.send(constraint.to_sym)
|
303
|
+
when Enumerable
|
304
|
+
# All constraints must pass
|
305
|
+
constraint.all? { |inner_constraint| algolia_constraint_passes?(object, inner_constraint) }
|
306
|
+
else
|
307
|
+
if constraint.respond_to?(:call) # Proc
|
308
|
+
constraint.call(object)
|
309
|
+
else
|
310
|
+
raise ArgumentError, "Unknown constraint type: #{constraint} (#{constraint.class})"
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
265
314
|
end
|
266
315
|
|
267
316
|
# these are the instance methods included
|
268
317
|
module InstanceMethods
|
269
|
-
|
270
|
-
|
318
|
+
|
319
|
+
def self.included(base)
|
320
|
+
base.instance_eval do
|
321
|
+
alias_method :index!, :algolia_index! unless method_defined? :index!
|
322
|
+
alias_method :remove_from_index!, :algolia_remove_from_index! unless method_defined? :remove_from_index!
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
def algolia_index!
|
327
|
+
self.class.algolia_index!(self, algolia_synchronous?)
|
271
328
|
end
|
272
329
|
|
273
|
-
def
|
274
|
-
self.class.
|
330
|
+
def algolia_remove_from_index!
|
331
|
+
self.class.algolia_remove_from_index!(self, algolia_synchronous?)
|
275
332
|
end
|
276
333
|
|
277
334
|
private
|
278
335
|
|
279
|
-
def
|
280
|
-
@
|
336
|
+
def algolia_synchronous?
|
337
|
+
@algolia_synchronous == true
|
281
338
|
end
|
282
339
|
|
283
|
-
def
|
284
|
-
@
|
340
|
+
def algolia_mark_synchronous
|
341
|
+
@algolia_synchronous = true
|
285
342
|
end
|
286
343
|
|
287
|
-
def
|
288
|
-
@
|
344
|
+
def algolia_mark_for_auto_indexing
|
345
|
+
@algolia_auto_indexing = true
|
289
346
|
end
|
290
347
|
|
291
|
-
def
|
292
|
-
@
|
348
|
+
def algolia_mark_must_reindex
|
349
|
+
@algolia_must_reindex = new_record? || self.class.algolia_must_reindex?(self)
|
293
350
|
true
|
294
351
|
end
|
295
352
|
|
296
|
-
def
|
297
|
-
return if !@
|
298
|
-
|
299
|
-
remove_instance_variable(:@
|
300
|
-
remove_instance_variable(:@
|
301
|
-
remove_instance_variable(:@
|
353
|
+
def algolia_perform_index_tasks
|
354
|
+
return if !@algolia_auto_indexing || @algolia_must_reindex == false
|
355
|
+
algolia_index!
|
356
|
+
remove_instance_variable(:@algolia_auto_indexing) if instance_variable_defined?(:@algolia_auto_indexing)
|
357
|
+
remove_instance_variable(:@algolia_synchronous) if instance_variable_defined?(:@algolia_synchronous)
|
358
|
+
remove_instance_variable(:@algolia_must_reindex) if instance_variable_defined?(:@algolia_must_reindex)
|
302
359
|
end
|
303
360
|
end
|
304
361
|
end
|
data/spec/spec_helper.rb
CHANGED