algoliasearch 1.23.2 → 1.24.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 898fdf039d30438b0bccedd74cef5c7a4b665d92c351f63ce779db7be8b29256
4
- data.tar.gz: 7ccdd7ccd3ebddb4f7ab10aaa4ce2d403e55e1032e16f4864b6a3802857e2809
3
+ metadata.gz: 6656588b81231ae7bff38c4b5fc55bb36194233505bc493107dd3dd9526ae86d
4
+ data.tar.gz: c64bf649901a0ea9f5ac1997b55f9917cc719bf59a956ea0db7b751268838700
5
5
  SHA512:
6
- metadata.gz: a1046362fa13b0646f799eeeb26bf1dbef4f0de91433a7a882aa59f65637b6501f488dbfca44b745fb4164e388c09f65185c100bdc4f792c46f095233cd433c8
7
- data.tar.gz: e390cc59d90d8685801bd359b5c5a2721040f1a733ab54eb9202fa8f38995e7e43151f48d994deacaf22fdd4d004537c038b92c83872f9e4359d848260e6d1de
6
+ metadata.gz: c19eb997c9a08b5e1219296756d99c61f9d22af53d06c9589537418d94755e030def9ebebbf8357670b081e1229d77cc674c795fa33c953bb7dc6dde6d3f26c6
7
+ data.tar.gz: 025ba93db32d9d3b6aa478dd638207ad84ec97df681c5807dbfc858ff88a8e2e77ef637e7eaa2b02738d6b47859c5b923cf02d3a74afa1b917062e7b8ba757cd
@@ -1,3 +1,9 @@
1
+ ## [1.24.0](https://github.com/algolia/algoliasearch-client-ruby/releases/tag/1.24.0) (2018-11-28)
2
+
3
+ * Feat(adds-account-client-copy-index): adds `copy_index` to account client ([#324](https://github.com/algolia/algoliasearch-client-ruby/pull/324))
4
+ * Feat(replace-all-methods): adds `replace_all_rules`, `replace_all_objects` and `replace_all_synonyms` to search index ([#323](https://github.com/algolia/algoliasearch-client-ruby/pull/323))
5
+ * Feat(scoped-copy-methods): adds `copy_settings`, `copy_synonyms` and `copy_rules` to search client ([#322](https://github.com/algolia/algoliasearch-client-ruby/pull/322))
6
+
1
7
  ## [1.23.2](https://github.com/algolia/algoliasearch-client-ruby/releases/tag/1.23.2) (2018-06-19)
2
8
 
3
9
  * Fix(analytics): gem without new analytics class (#306)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- algoliasearch (1.23.1)
4
+ algoliasearch (1.23.2)
5
5
  httpclient (~> 2.8, >= 2.8.3)
6
6
  json (>= 1.5.1)
7
7
 
@@ -9,24 +9,24 @@ GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
11
  addressable (2.4.0)
12
- backports (3.11.2)
13
- coveralls (0.7.2)
14
- multi_json (~> 1.3)
15
- rest-client (= 1.6.7)
16
- simplecov (>= 0.7)
17
- term-ansicolor (= 1.2.2)
18
- thor (= 0.18.1)
12
+ backports (3.11.4)
13
+ coveralls (0.8.22)
14
+ json (>= 1.8, < 3)
15
+ simplecov (~> 0.16.1)
16
+ term-ansicolor (~> 1.3)
17
+ thor (~> 0.19.4)
18
+ tins (~> 1.6)
19
19
  crack (0.4.3)
20
20
  safe_yaml (~> 1.0.0)
21
21
  diff-lcs (1.3)
22
- docile (1.3.0)
22
+ docile (1.3.1)
23
23
  ethon (0.11.0)
24
24
  ffi (>= 1.3.0)
25
- faraday (0.14.0)
25
+ faraday (0.15.3)
26
26
  multipart-post (>= 1.2, < 3)
27
27
  faraday_middleware (0.12.2)
28
28
  faraday (>= 0.7.4, < 1.0)
29
- ffi (1.9.23)
29
+ ffi (1.9.25)
30
30
  ffi2-generators (0.1.1)
31
31
  gh (0.15.1)
32
32
  addressable (~> 2.4.0)
@@ -36,12 +36,11 @@ GEM
36
36
  net-http-persistent (~> 2.9)
37
37
  net-http-pipeline
38
38
  hashdiff (0.3.7)
39
- highline (1.6.21)
39
+ highline (1.7.10)
40
40
  httpclient (2.8.3)
41
41
  json (2.1.0)
42
42
  launchy (2.4.3)
43
43
  addressable (~> 2.3)
44
- mime-types (1.25.1)
45
44
  multi_json (1.13.1)
46
45
  multipart-post (2.0.0)
47
46
  net-http-persistent (2.9.4)
@@ -50,22 +49,20 @@ GEM
50
49
  json
51
50
  websocket (~> 1.0)
52
51
  rake (12.3.1)
53
- rdoc (6.0.3)
54
- rest-client (1.6.7)
55
- mime-types (>= 1.16)
56
- rspec (3.7.0)
57
- rspec-core (~> 3.7.0)
58
- rspec-expectations (~> 3.7.0)
59
- rspec-mocks (~> 3.7.0)
60
- rspec-core (3.7.1)
61
- rspec-support (~> 3.7.0)
62
- rspec-expectations (3.7.0)
52
+ rdoc (6.0.4)
53
+ rspec (3.8.0)
54
+ rspec-core (~> 3.8.0)
55
+ rspec-expectations (~> 3.8.0)
56
+ rspec-mocks (~> 3.8.0)
57
+ rspec-core (3.8.0)
58
+ rspec-support (~> 3.8.0)
59
+ rspec-expectations (3.8.2)
63
60
  diff-lcs (>= 1.2.0, < 2.0)
64
- rspec-support (~> 3.7.0)
65
- rspec-mocks (3.7.0)
61
+ rspec-support (~> 3.8.0)
62
+ rspec-mocks (3.8.0)
66
63
  diff-lcs (>= 1.2.0, < 2.0)
67
- rspec-support (~> 3.7.0)
68
- rspec-support (3.7.1)
64
+ rspec-support (~> 3.8.0)
65
+ rspec-support (3.8.0)
69
66
  rubysl (2.2.0)
70
67
  rubysl-abbrev (~> 2.0)
71
68
  rubysl-base64 (~> 2.0)
@@ -246,7 +243,7 @@ GEM
246
243
  rubysl-singleton (2.0.0)
247
244
  rubysl-socket (2.2.1)
248
245
  rubysl-fcntl (~> 2.0)
249
- rubysl-stringio (2.2)
246
+ rubysl-stringio (2.3)
250
247
  rubysl-strscan (2.0.0)
251
248
  rubysl-sync (2.0.0)
252
249
  rubysl-syslog (2.1.0)
@@ -274,11 +271,11 @@ GEM
274
271
  json (>= 1.8, < 3)
275
272
  simplecov-html (~> 0.10.0)
276
273
  simplecov-html (0.10.2)
277
- term-ansicolor (1.2.2)
278
- tins (~> 0.8)
279
- thor (0.18.1)
280
- tins (0.13.2)
281
- travis (1.8.8)
274
+ term-ansicolor (1.7.0)
275
+ tins (~> 1.0)
276
+ thor (0.19.4)
277
+ tins (1.20.2)
278
+ travis (1.8.9)
282
279
  backports
283
280
  faraday (~> 0.9)
284
281
  faraday_middleware (~> 0.9, >= 0.9.1)
@@ -289,11 +286,11 @@ GEM
289
286
  typhoeus (~> 0.6, >= 0.6.8)
290
287
  typhoeus (0.8.0)
291
288
  ethon (>= 0.8.0)
292
- webmock (3.3.0)
289
+ webmock (3.4.2)
293
290
  addressable (>= 2.3.6)
294
291
  crack (>= 0.3.2)
295
292
  hashdiff
296
- websocket (1.2.5)
293
+ websocket (1.2.8)
297
294
 
298
295
  PLATFORMS
299
296
  ruby
@@ -310,4 +307,4 @@ DEPENDENCIES
310
307
  webmock
311
308
 
312
309
  BUNDLED WITH
313
- 1.16.2
310
+ 1.17.1
data/README.md CHANGED
@@ -173,7 +173,7 @@ var search = instantsearch({
173
173
  appId: 'YourApplicationID',
174
174
  apiKey: 'YourSearchOnlyAPIKey', // search only API key, no ADMIN key
175
175
  indexName: 'contacts',
176
- urlSync: true,
176
+ routing: true,
177
177
  searchParameters: {
178
178
  hitsPerPage: 10
179
179
  }
@@ -209,10 +209,10 @@ search.start();
209
209
 
210
210
  ### Search
211
211
 
212
- - [Search an index](https://algolia.com/doc/api-reference/api-methods/search/?language=ruby)
212
+ - [Search index](https://algolia.com/doc/api-reference/api-methods/search/?language=ruby)
213
213
  - [Search for facet values](https://algolia.com/doc/api-reference/api-methods/search-for-facet-values/?language=ruby)
214
214
  - [Search multiple indexes](https://algolia.com/doc/api-reference/api-methods/multiple-queries/?language=ruby)
215
- - [Browse an index](https://algolia.com/doc/api-reference/api-methods/browse/?language=ruby)
215
+ - [Browse index](https://algolia.com/doc/api-reference/api-methods/browse/?language=ruby)
216
216
 
217
217
 
218
218
 
@@ -276,12 +276,12 @@ search.start();
276
276
 
277
277
  ### Query rules
278
278
 
279
- - [Save a single rule](https://algolia.com/doc/api-reference/api-methods/rules-save/?language=ruby)
280
- - [Batch save multiple rules](https://algolia.com/doc/api-reference/api-methods/rules-save-batch/?language=ruby)
281
- - [Get a rule](https://algolia.com/doc/api-reference/api-methods/rules-get/?language=ruby)
282
- - [Delete a single rule](https://algolia.com/doc/api-reference/api-methods/rules-delete/?language=ruby)
283
- - [Clear all rules](https://algolia.com/doc/api-reference/api-methods/rules-clear/?language=ruby)
284
- - [Search for rules](https://algolia.com/doc/api-reference/api-methods/rules-search/?language=ruby)
279
+ - [Save rule](https://algolia.com/doc/api-reference/api-methods/rules-save/?language=ruby)
280
+ - [Batch rules](https://algolia.com/doc/api-reference/api-methods/rules-save-batch/?language=ruby)
281
+ - [Get rule](https://algolia.com/doc/api-reference/api-methods/rules-get/?language=ruby)
282
+ - [Delete rule](https://algolia.com/doc/api-reference/api-methods/rules-delete/?language=ruby)
283
+ - [Clear rules](https://algolia.com/doc/api-reference/api-methods/rules-clear/?language=ruby)
284
+ - [Search rules](https://algolia.com/doc/api-reference/api-methods/rules-search/?language=ruby)
285
285
  - [Export rules](https://algolia.com/doc/api-reference/api-methods/rules-export/?language=ruby)
286
286
 
287
287
 
@@ -289,11 +289,11 @@ search.start();
289
289
 
290
290
  ### A/B Test
291
291
 
292
- - [Add an A/B test](https://algolia.com/doc/api-reference/api-methods/add-ab-test/?language=ruby)
293
- - [Get an A/B test](https://algolia.com/doc/api-reference/api-methods/get-ab-test/?language=ruby)
294
- - [List A/B tests](https://algolia.com/doc/api-reference/api-methods/get-ab-tests/?language=ruby)
295
- - [Stop an A/B test](https://algolia.com/doc/api-reference/api-methods/stop-ab-test/?language=ruby)
296
- - [Delete an A/B test](https://algolia.com/doc/api-reference/api-methods/delete-ab-test/?language=ruby)
292
+ - [Add A/B test](https://algolia.com/doc/api-reference/api-methods/add-ab-test/?language=ruby)
293
+ - [Get A/B test](https://algolia.com/doc/api-reference/api-methods/get-ab-test/?language=ruby)
294
+ - [List A/B tests](https://algolia.com/doc/api-reference/api-methods/list-ab-tests/?language=ruby)
295
+ - [Stop A/B test](https://algolia.com/doc/api-reference/api-methods/stop-ab-test/?language=ruby)
296
+ - [Delete A/B test](https://algolia.com/doc/api-reference/api-methods/delete-ab-test/?language=ruby)
297
297
 
298
298
 
299
299
 
@@ -43,6 +43,7 @@ Gem::Specification.new do |s|
43
43
  "algoliasearch.gemspec",
44
44
  "contacts.json",
45
45
  "lib/algolia/analytics.rb",
46
+ "lib/algolia/account_client.rb",
46
47
  "lib/algolia/client.rb",
47
48
  "lib/algolia/error.rb",
48
49
  "lib/algolia/index.rb",
@@ -51,6 +52,7 @@ Gem::Specification.new do |s|
51
52
  "lib/algolia/webmock.rb",
52
53
  "lib/algoliasearch.rb",
53
54
  "resources/ca-bundle.crt",
55
+ "spec/account_client_spec.rb",
54
56
  "spec/client_spec.rb",
55
57
  "spec/mock_spec.rb",
56
58
  "spec/spec_helper.rb",
@@ -0,0 +1,99 @@
1
+ require 'algolia/error'
2
+
3
+ module Algolia
4
+ #
5
+ # A class which encapsulates the HTTPS communication with the Algolia
6
+ # API server for cross-app operations.
7
+ #
8
+ class AccountClient
9
+ class << self
10
+ #
11
+ # Copies settings, synonyms, rules and objects from the source index to the
12
+ # destination index. The replicas of the source index should not be copied.
13
+ #
14
+ # Throw an exception if the destination index already exists
15
+ # Throw an exception if the indices are on the same application
16
+ #
17
+ # @param source_index the source index object
18
+ # @param destination_index the destination index object
19
+ # @param request_options contains extra parameters to send with your query
20
+ #
21
+ def copy_index(source_index, destination_index, request_options = {})
22
+ raise AlgoliaError.new('The indexes are in the same application. Use Algolia::Client.copy_index instead.') if source_index.client.application_id == destination_index.client.application_id
23
+
24
+ begin
25
+ settings = destination_index.get_settings()
26
+ rescue AlgoliaError
27
+ # Destination index does not exists. We can proceed.
28
+ else
29
+ raise AlgoliaError.new("Destination index already exists. Please delete it before copying index across applications.")
30
+ end
31
+
32
+ responses = []
33
+
34
+ settings = source_index.get_settings()
35
+ responses << destination_index.set_settings(settings, {}, request_options)
36
+
37
+ synonyms = []
38
+ source_index.export_synonyms(100, request_options) do |synonym|
39
+ synonym.delete('_highlightResult')
40
+ synonyms << synonym
41
+ end
42
+
43
+ responses << destination_index.batch_synonyms(synonyms, false, false, request_options)
44
+
45
+ rules = []
46
+ source_index.export_rules(100, request_options) do |rule|
47
+ rule.delete('_highlightResult')
48
+ rules << rule
49
+ end
50
+ responses << destination_index.batch_rules(rules, false, false, request_options)
51
+
52
+ # Copy objects
53
+ responses = []
54
+ batch = []
55
+ batch_size = 1000
56
+ count = 0
57
+
58
+ source_index.browse()['hits'].each do |obj|
59
+ batch << obj
60
+ count += 1
61
+
62
+ if count == batch_size
63
+ responses << destination_index.save_objects(batch, request_options)
64
+ batch = []
65
+ count = 0
66
+ end
67
+ end
68
+
69
+ if batch.any?
70
+ responses << destination_index.save_objects(batch, request_options)
71
+ end
72
+
73
+ responses
74
+ end
75
+
76
+ #
77
+ # The method copy settings, synonyms, rules and objects from the source index
78
+ # to the destination index and wait end of indexing. The replicas of the
79
+ # source index should not be copied
80
+ #
81
+ # Throw an exception if the destination index already exists
82
+ # Throw an exception if the indices are on the same application
83
+ #
84
+ # @param source_index the source index object
85
+ # @param destination_index the destination index object
86
+ # @param request_options contains extra parameters to send with your query
87
+ #
88
+ def copy_index!(source_index, destination_index, request_options = {})
89
+ responses = self.copy_index(source_index, destination_index, request_options)
90
+
91
+ responses.each do |res|
92
+ destination_index.wait_task(res['taskID'], WAIT_TASK_DEFAULT_TIME_BEFORE_RETRY, request_options)
93
+ end
94
+
95
+ responses
96
+ end
97
+ end
98
+ end
99
+ end
@@ -208,6 +208,78 @@ module Algolia
208
208
  res
209
209
  end
210
210
 
211
+ #
212
+ # Copy an existing index settings.
213
+ #
214
+ # @param src_index the name of index to copy.
215
+ # @param dst_index the new index name that will contains a copy of srcIndexName's settings (destination's settings will be overriten if it already exist).
216
+ # @param request_options contains extra parameters to send with your query
217
+ #
218
+ def copy_settings(src_index, dst_index, request_options = {})
219
+ copy_index(src_index, dst_index, ['settings'], request_options)
220
+ end
221
+
222
+ #
223
+ # Copy an existing index settings and wait until the copy has been processed.
224
+ #
225
+ # @param src_index the name of index to copy.
226
+ # @param dst_index the new index name that will contains a copy of srcIndexName settings (destination settings will be overriten if it already exist).
227
+ # @param request_options contains extra parameters to send with your query
228
+ #
229
+ def copy_settings!(src_index, dst_index, request_options = {})
230
+ res = copy_settings(src_index, dst_index, request_options)
231
+ wait_task(dst_index, res['taskID'], WAIT_TASK_DEFAULT_TIME_BEFORE_RETRY, request_options)
232
+ res
233
+ end
234
+
235
+ #
236
+ # Copy an existing index synonyms.
237
+ #
238
+ # @param src_index the name of index to copy.
239
+ # @param dst_index the new index name that will contains a copy of srcIndexName's synonyms (destination's synonyms will be overriten if it already exist).
240
+ # @param request_options contains extra parameters to send with your query
241
+ #
242
+ def copy_synonyms(src_index, dst_index, request_options = {})
243
+ copy_index(src_index, dst_index, ['synonyms'], request_options)
244
+ end
245
+
246
+ #
247
+ # Copy an existing index synonyms and wait until the copy has been processed.
248
+ #
249
+ # @param src_index the name of index to copy.
250
+ # @param dst_index the new index name that will contains a copy of srcIndexName synonyms (destination synonyms will be overriten if it already exist).
251
+ # @param request_options contains extra parameters to send with your query
252
+ #
253
+ def copy_synonyms!(src_index, dst_index, request_options = {})
254
+ res = copy_synonyms(src_index, dst_index, request_options)
255
+ wait_task(dst_index, res['taskID'], WAIT_TASK_DEFAULT_TIME_BEFORE_RETRY, request_options)
256
+ res
257
+ end
258
+
259
+ #
260
+ # Copy an existing index rules.
261
+ #
262
+ # @param src_index the name of index to copy.
263
+ # @param dst_index the new index name that will contains a copy of srcIndexName's rules (destination's rules will be overriten if it already exist).
264
+ # @param request_options contains extra parameters to send with your query
265
+ #
266
+ def copy_rules(src_index, dst_index, request_options = {})
267
+ copy_index(src_index, dst_index, ['rules'], request_options)
268
+ end
269
+
270
+ #
271
+ # Copy an existing index rules and wait until the copy has been processed.
272
+ #
273
+ # @param src_index the name of index to copy.
274
+ # @param dst_index the new index name that will contains a copy of srcIndexName rules (destination rules will be overriten if it already exist).
275
+ # @param request_options contains extra parameters to send with your query
276
+ #
277
+ def copy_rules!(src_index, dst_index, request_options = {})
278
+ res = copy_rules(src_index, dst_index, request_options)
279
+ wait_task(dst_index, res['taskID'], WAIT_TASK_DEFAULT_TIME_BEFORE_RETRY, request_options)
280
+ res
281
+ end
282
+
211
283
  #
212
284
  # Delete an index
213
285
  # @param name the name of the index to delete
@@ -740,6 +812,72 @@ module Algolia
740
812
  Algolia.client.copy_index!(src_index, dst_index, scope, request_options)
741
813
  end
742
814
 
815
+ #
816
+ # Copy an existing index settings.
817
+ #
818
+ # @param src_index the name of index to copy.
819
+ # @param dst_index the new index name that will contains a copy of src_index_name settings (destination settings will be overriten if it already exist).
820
+ # @param request_options contains extra parameters to send with your query
821
+ #
822
+ def Algolia.copy_settings(src_index, dst_index, request_options = {})
823
+ Algolia.client.copy_settings(src_index, dst_index, request_options)
824
+ end
825
+
826
+ #
827
+ # Copy an existing index settings and wait until the copy has been processed.
828
+ #
829
+ # @param src_index the name of index to copy.
830
+ # @param dst_index the new index name that will contains a copy of src_index_name settings (destination settings will be overriten if it already exist).
831
+ # @param request_options contains extra parameters to send with your query
832
+ #
833
+ def Algolia.copy_settings!(src_index, dst_index, request_options = {})
834
+ Algolia.client.copy_settings!(src_index, dst_index, request_options)
835
+ end
836
+
837
+ #
838
+ # Copy an existing index synonyms.
839
+ #
840
+ # @param src_index the name of index to copy.
841
+ # @param dst_index the new index name that will contains a copy of src_index_name synonyms (destination synonyms will be overriten if it already exist).
842
+ # @param request_options contains extra parameters to send with your query
843
+ #
844
+ def Algolia.copy_synonyms(src_index, dst_index, request_options = {})
845
+ Algolia.client.copy_synonyms(src_index, dst_index, request_options)
846
+ end
847
+
848
+ #
849
+ # Copy an existing index synonyms and wait until the copy has been processed.
850
+ #
851
+ # @param src_index the name of index to copy.
852
+ # @param dst_index the new index name that will contains a copy of src_index_name synonyms (destination synonyms will be overriten if it already exist).
853
+ # @param request_options contains extra parameters to send with your query
854
+ #
855
+ def Algolia.copy_synonyms!(src_index, dst_index, request_options = {})
856
+ Algolia.client.copy_synonyms!(src_index, dst_index, request_options)
857
+ end
858
+
859
+ #
860
+ # Copy an existing index rules.
861
+ #
862
+ # @param src_index the name of index to copy.
863
+ # @param dst_index the new index name that will contains a copy of src_index_name rules (destination rules will be overriten if it already exist).
864
+ # @param request_options contains extra parameters to send with your query
865
+ #
866
+ def Algolia.copy_rules(src_index, dst_index, request_options = {})
867
+ Algolia.client.copy_rules(src_index, dst_index, request_options)
868
+ end
869
+
870
+ #
871
+ # Copy an existing index rules and wait until the copy has been processed.
872
+ #
873
+ # @param src_index the name of index to copy.
874
+ # @param dst_index the new index name that will contains a copy of src_index_name rules (destination rules will be overriten if it already exist).
875
+ # @param request_options contains extra parameters to send with your query
876
+ #
877
+ def Algolia.copy_rules!(src_index, dst_index, request_options = {})
878
+ Algolia.client.copy_rules!(src_index, dst_index, request_options)
879
+ end
880
+
743
881
  #
744
882
  # Delete an index
745
883
  #
@@ -333,6 +333,76 @@ module Algolia
333
333
  res
334
334
  end
335
335
 
336
+ #
337
+ # Override the current objects by the given array of objects and wait end of indexing. Settings,
338
+ # synonyms and query rules are untouched. The objects are replaced without any downtime.
339
+ #
340
+ # @param objects the array of objects to save
341
+ # @param request_options contains extra parameters to send with your query
342
+ #
343
+ def replace_all_objects(objects, request_options = {})
344
+ safe = request_options[:safe] || request_options['safe'] || false
345
+ request_options.delete(:safe)
346
+ request_options.delete('safe')
347
+
348
+ tmp_index = @client.init_index(@name + '_tmp_' + rand(10000000).to_s)
349
+
350
+ responses = []
351
+
352
+ scope = ['settings', 'synonyms', 'rules']
353
+ res = @client.copy_index(@name, tmp_index.name, scope, request_options)
354
+ responses << res
355
+
356
+ if safe
357
+ wait_task(res['taskID'], WAIT_TASK_DEFAULT_TIME_BEFORE_RETRY, request_options)
358
+ end
359
+
360
+ batch = []
361
+ batch_size = 1000
362
+ count = 0
363
+
364
+ objects.each do |object|
365
+ batch << object
366
+ count += 1
367
+ if count == batch_size
368
+ res = tmp_index.add_objects(batch, request_options)
369
+ responses << res
370
+ batch = []
371
+ count = 0
372
+ end
373
+ end
374
+
375
+ if batch.any?
376
+ res = tmp_index.add_objects(batch, request_options)
377
+ responses << res
378
+ end
379
+
380
+ if safe
381
+ responses.each do |res|
382
+ tmp_index.wait_task(res['taskID'], WAIT_TASK_DEFAULT_TIME_BEFORE_RETRY, request_options)
383
+ end
384
+ end
385
+
386
+ res = @client.move_index(tmp_index.name, @name, request_options)
387
+ responses << res
388
+
389
+ if safe
390
+ wait_task(res['taskID'], WAIT_TASK_DEFAULT_TIME_BEFORE_RETRY, request_options)
391
+ end
392
+
393
+ responses
394
+ end
395
+
396
+ #
397
+ # Override the current objects by the given array of objects and wait end of indexing
398
+ #
399
+ # @param objects the array of objects to save
400
+ # @param request_options contains extra parameters to send with your query
401
+ #
402
+ def replace_all_objects!(objects, request_options = {})
403
+ replace_all_objects(objects, request_options.merge(:safe => true))
404
+ end
405
+
336
406
  #
337
407
  # Update partially an object (only update attributes passed in argument)
338
408
  #
@@ -915,6 +985,29 @@ module Algolia
915
985
  res
916
986
  end
917
987
 
988
+ #
989
+ # Replace synonyms in the index by the given array of synonyms
990
+ #
991
+ # @param synonyms the array of synonyms to add
992
+ # @param request_options contains extra parameters to send with your query
993
+ #
994
+ def replace_all_synonyms(synonyms, request_options = {})
995
+ forward_to_replicas = request_options[:forwardToReplicas] || request_options['forwardToReplicas'] || false
996
+ batch_synonyms(synonyms, forward_to_replicas, true, request_options)
997
+ end
998
+
999
+ #
1000
+ # Replace synonyms in the index by the given array of synonyms and wait the end of indexing
1001
+ #
1002
+ # @param synonyms the array of synonyms to add
1003
+ # @param request_options contains extra parameters to send with your query
1004
+ #
1005
+ def replace_all_synonyms!(synonyms, request_options = {})
1006
+ res = replace_all_synonyms(synonyms, request_options)
1007
+ wait_task(res['taskID'], WAIT_TASK_DEFAULT_TIME_BEFORE_RETRY, request_options)
1008
+ res
1009
+ end
1010
+
918
1011
  #
919
1012
  # Export the full list of synonyms
920
1013
  # Accepts an optional block to which it will pass each synonym
@@ -1069,6 +1162,29 @@ module Algolia
1069
1162
  return res
1070
1163
  end
1071
1164
 
1165
+ #
1166
+ # Replace rules in the index by the given array of rules
1167
+ #
1168
+ # @param rules the array of rules to add
1169
+ # @param request_options contains extra parameters to send with your query
1170
+ #
1171
+ def replace_all_rules(rules, request_options = {})
1172
+ forward_to_replicas = request_options[:forwardToReplicas] || request_options['forwardToReplicas'] || false
1173
+ batch_rules(rules, forward_to_replicas, true, request_options)
1174
+ end
1175
+
1176
+ #
1177
+ # Replace rules in the index by the given array of rules and wait the end of indexing
1178
+ #
1179
+ # @param rules the array of rules to add
1180
+ # @param request_options contains extra parameters to send with your query
1181
+ #
1182
+ def replace_all_rules!(rules, request_options = {})
1183
+ res = replace_all_rules(rules, request_options)
1184
+ wait_task(res['taskID'], WAIT_TASK_DEFAULT_TIME_BEFORE_RETRY, request_options)
1185
+ res
1186
+ end
1187
+
1072
1188
  #
1073
1189
  # Export the full list of rules
1074
1190
  # Accepts an optional block to which it will pass each rule
@@ -1,3 +1,3 @@
1
1
  module Algolia
2
- VERSION = "1.23.2"
2
+ VERSION = "1.24.0"
3
3
  end
@@ -22,3 +22,4 @@ $:.unshift(cwd.to_s) unless $:.include?(cwd.to_s) || $:.include?(cwd.expand_path
22
22
 
23
23
  require 'algolia/index'
24
24
  require 'algolia/analytics'
25
+ require 'algolia/account_client'
@@ -0,0 +1,92 @@
1
+ # encoding: UTF-8
2
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
3
+ require 'securerandom'
4
+
5
+ describe 'Account client' do
6
+ before(:all) do
7
+ client_1 = Algolia::Client.new({
8
+ :application_id => ENV['ALGOLIA_APPLICATION_ID_1'],
9
+ :api_key => ENV['ALGOLIA_ADMIN_KEY_1']
10
+ })
11
+
12
+ @index_1 = client_1.init_index(index_name('account_client_1'))
13
+
14
+ client_2 = Algolia::Client.new({
15
+ :application_id => ENV['ALGOLIA_APPLICATION_ID_1'],
16
+ :api_key => ENV['ALGOLIA_ADMIN_KEY_1']
17
+ })
18
+
19
+ @index_2 = client_2.init_index(index_name('account_client_2'))
20
+
21
+ client_3 = Algolia::Client.new({
22
+ :application_id => ENV['ALGOLIA_APPLICATION_ID_2'],
23
+ :api_key => ENV['ALGOLIA_ADMIN_KEY_2']
24
+ })
25
+
26
+ @index_3 = client_3.init_index(index_name('account_client_3'))
27
+
28
+ @index_1.delete_index rescue 'not fatal'
29
+ @index_2.delete_index rescue 'not fatal'
30
+ @index_3.delete_index rescue 'not fatal'
31
+ end
32
+
33
+ after(:all) do
34
+ @index_1.delete_index rescue 'not fatal'
35
+ @index_2.delete_index rescue 'not fatal'
36
+ @index_3.delete_index rescue 'not fatal'
37
+ end
38
+
39
+ it 'should not allow operations in the same application' do
40
+ expect {
41
+ Algolia::AccountClient.copy_index!(@index_1, @index_2)
42
+ }.to raise_exception(
43
+ Algolia::AlgoliaError,
44
+ 'The indexes are in the same application. Use Algolia::Client.copy_index instead.'
45
+ )
46
+ end
47
+
48
+ it 'should perform a cross app copy index and assert that destination must not exist' do
49
+
50
+ @index_1.save_objects! ([
51
+ {:objectID => 'one'},
52
+ ])
53
+
54
+ @index_1.batch_rules! ([
55
+ {
56
+ :objectID => 'one',
57
+ :condition => {:pattern => 'test', :anchoring => 'contains'},
58
+ :consequence => {:params => {:query => 'this is better'}}
59
+ }
60
+ ])
61
+
62
+ @index_1.batch_synonyms! ([
63
+ {:objectID => 'one', :type => 'synonym', :synonyms => ['San Francisco', 'SF']}
64
+ ])
65
+
66
+ @index_1.set_settings! ({:searchableAttributes => ['objectID']})
67
+
68
+ Algolia::AccountClient.copy_index!(@index_1, @index_3)
69
+
70
+ res = @index_3.search('');
71
+ res['nbHits'].should eq(1)
72
+ res['hits'][0]['objectID'].should eq('one')
73
+
74
+ res = @index_3.search_rules('')['hits']
75
+ res.size.should eq(1)
76
+ res[0]['objectID'].should eq('one')
77
+
78
+ res = @index_3.search_synonyms('')['hits']
79
+ res.size.should eq(1)
80
+ res[0]['objectID'].should eq('one')
81
+
82
+ @index_3.get_settings['searchableAttributes'].should eq(['objectID'])
83
+
84
+ expect {
85
+ Algolia::AccountClient.copy_index!(@index_1, @index_3)
86
+ }.to raise_exception(
87
+ Algolia::AlgoliaError,
88
+ 'Destination index already exists. Please delete it before copying index across applications.'
89
+ )
90
+ end
91
+ end
92
+
@@ -249,6 +249,17 @@ describe 'Client' do
249
249
  res["hits"].length.should eq(2)
250
250
  end
251
251
 
252
+ it "should replace all objects" do
253
+ @index.save_objects!([{:objectID => '1'}, {:objectID => '2'}])
254
+ @index.replace_all_objects!([{'color' => 'black'}, {:objectID => '4', 'color' => 'green'}])
255
+
256
+ res = @index.search('')
257
+ res["hits"].length.should eq(2)
258
+ res = @index.search('black')
259
+ res["hits"][0]['color'].should eq('black')
260
+ @index.get_object('4')['color'].should eq('green')
261
+ end
262
+
252
263
  it "should throw an exception if invalid argument" do
253
264
  expect { @index.add_object!([ {:name => "test"} ]) }.to raise_error(ArgumentError)
254
265
  expect { @index.add_objects!([ [ {:name => "test"} ] ]) }.to raise_error(ArgumentError)
@@ -262,6 +273,10 @@ describe 'Client' do
262
273
  end
263
274
 
264
275
  it "should be thread safe" do
276
+ @index.clear!
277
+ @index.add_object!({ :name => "John Doe", :email => "john@doe.org" })
278
+ @index.add_object!({ :name => "John Doe", :email => "john@doe.org" })
279
+
265
280
  threads = []
266
281
  64.times do
267
282
  t = Thread.new do
@@ -430,6 +445,66 @@ describe 'Client' do
430
445
  index.delete_index!
431
446
  end
432
447
 
448
+ it "should copy only settings" do
449
+ index = Algolia::Index.new(safe_index_name("àlgol?à"))
450
+ begin
451
+ @index.clear_index
452
+ Algolia.delete_index index.name
453
+ rescue
454
+ end
455
+
456
+ res = @index.set_settings!({
457
+ 'searchableAttributes' => ['one'],
458
+ })
459
+
460
+ @index.wait_task(res['taskID'])
461
+ Algolia.copy_settings!(@index.name, index.name)
462
+ @index.delete_index!
463
+
464
+ index.get_settings['searchableAttributes'].should eq(['one'])
465
+ index.delete_index!
466
+ end
467
+
468
+ it "should copy only synonyms" do
469
+ index = Algolia::Index.new(safe_index_name("àlgol?à"))
470
+ begin
471
+ @index.clear_index
472
+ Algolia.delete_index index.name
473
+ rescue
474
+ end
475
+
476
+ @index.save_synonym!('foo', {
477
+ :objectID => 'foo', :synonyms => ['car', 'vehicle', 'auto'], :type => 'synonym',
478
+ })
479
+
480
+ Algolia.copy_synonyms!(@index.name, index.name)
481
+ @index.delete_index!
482
+
483
+ index.get_synonym('foo')['objectID'].should eq('foo')
484
+ index.delete_index!
485
+ end
486
+
487
+ it "should copy only rules" do
488
+ index = Algolia::Index.new(safe_index_name("àlgol?à"))
489
+ begin
490
+ @index.clear_index
491
+ Algolia.delete_index index.name
492
+ rescue
493
+ end
494
+
495
+ @index.save_rule!('bar', {
496
+ :objectID => 'bar',
497
+ :condition => {:pattern => 'test', :anchoring => 'contains'},
498
+ :consequence => {:params => {:query => 'this is better'}}
499
+ })
500
+
501
+ Algolia.copy_rules!(@index.name, index.name)
502
+ @index.delete_index!
503
+
504
+ index.get_rule('bar')['objectID'].should eq('bar')
505
+ index.delete_index!
506
+ end
507
+
433
508
  it "should copy parts of the index only" do
434
509
  index = Algolia::Index.new(safe_index_name("àlgol?à"))
435
510
  begin
@@ -1056,6 +1131,22 @@ describe 'Client' do
1056
1131
  @index.search_synonyms('')['nbHits'].should eq(0)
1057
1132
  end
1058
1133
 
1134
+ it "should replace all synonyms" do
1135
+ @index.batch_synonyms! ([
1136
+ {:objectID => '1', :type => 'synonym', :synonyms => ['San Francisco', 'SF']},
1137
+ {:objectID => '2', :type => 'altCorrection1', :word => 'foo', :corrections => ['st']}
1138
+ ])
1139
+
1140
+ @index.replace_all_synonyms! ([
1141
+ {:objectID => '3', :type => 'synonym', :synonyms => ['San Francisco', 'SF']},
1142
+ {:objectID => '4', :type => 'altCorrection1', :word => 'bar', :corrections => ['st']}
1143
+ ])
1144
+
1145
+ synonym = @index.get_synonym('4')['objectID'].should eq('4')
1146
+ synonyms_search = @index.search_synonyms('')['hits']
1147
+ synonyms_search.size.should eq(2)
1148
+ end
1149
+
1059
1150
  it 'should test Query Rules' do
1060
1151
  rule_1 = {
1061
1152
  :objectID => '42',
@@ -1100,6 +1191,29 @@ describe 'Client' do
1100
1191
  @index.search_rules('')['nbHits'].should eq(0)
1101
1192
  end
1102
1193
 
1194
+ it "should replace all rules" do
1195
+ rule_1 = {
1196
+ :objectID => '1',
1197
+ :condition => {:pattern => 'test', :anchoring => 'contains'},
1198
+ :consequence => {:params => {:query => 'this is better'}}
1199
+ }
1200
+ rule_2 = {
1201
+ :objectID => '2',
1202
+ :condition => {:pattern => 'Pura', :anchoring => 'contains'},
1203
+ :consequence => {:params => {:query => 'Pura Vida'}}
1204
+ }
1205
+
1206
+ @index.batch_rules! [rule_1, rule_2]
1207
+
1208
+ rule_1[:objectID] = '3'
1209
+ rule_2[:objectID] = '4'
1210
+ @index.replace_all_rules!([rule_1, rule_2])
1211
+
1212
+ @index.get_rule('4')['objectID'].should eq('4')
1213
+ rules_search = @index.search_rules('')['hits']
1214
+ rules_search.size.should eq(2)
1215
+ end
1216
+
1103
1217
  it 'should not save a query rule with an empty objectID' do
1104
1218
  rule = {
1105
1219
  :objectID => '',
@@ -44,6 +44,15 @@ def safe_index_name(name)
44
44
  "TRAVIS_RUBY_#{name}-#{id}"
45
45
  end
46
46
 
47
+ # avoid concurrent access to the same index and follows the CTS standards.
48
+ def index_name(name)
49
+ date = DateTime.now.strftime('%Y-%m-%d_%H:%M:%S')
50
+
51
+ instance = ENV['TRAVIS'].to_s == 'true' ? ENV['TRAVIS_JOB_NUMBER'] : 'unknown'
52
+
53
+ 'ruby_%s_%s_%s' % [date, instance, name]
54
+ end
55
+
47
56
  def auto_retry(options = {})
48
57
  return if !block_given?
49
58
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: algoliasearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.23.2
4
+ version: 1.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Algolia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-19 00:00:00.000000000 Z
11
+ date: 2018-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpclient
@@ -105,6 +105,7 @@ files:
105
105
  - Rakefile
106
106
  - algoliasearch.gemspec
107
107
  - contacts.json
108
+ - lib/algolia/account_client.rb
108
109
  - lib/algolia/analytics.rb
109
110
  - lib/algolia/client.rb
110
111
  - lib/algolia/error.rb
@@ -114,6 +115,7 @@ files:
114
115
  - lib/algolia/webmock.rb
115
116
  - lib/algoliasearch.rb
116
117
  - resources/ca-bundle.crt
118
+ - spec/account_client_spec.rb
117
119
  - spec/client_spec.rb
118
120
  - spec/mock_spec.rb
119
121
  - spec/spec_helper.rb
@@ -143,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
145
  version: '0'
144
146
  requirements: []
145
147
  rubyforge_project:
146
- rubygems_version: 2.7.6
148
+ rubygems_version: 2.7.8
147
149
  signing_key:
148
150
  specification_version: 4
149
151
  summary: A simple Ruby client for the algolia.com REST API