algoliasearch-rails 1.7.0 → 1.7.1
Sign up to get free protection for your applications and to get access to all the features.
- 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