algoliasearch 1.23.2 → 1.24.0

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
  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