algolia 2.0.4 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e2ba367e6308158bc455c60a0d0a5c16fbb1ed4565aaa3a6b8d4cca3e16f0c0d
4
- data.tar.gz: af53995633ba454c929265d5d81d311c67a99fcdd76e8eeec51f98aa8e89f778
3
+ metadata.gz: dc743bd03ca6ebc94d2ae61eec22670ccbaa3531d2a9b66c44858280c644a938
4
+ data.tar.gz: 9e5fb85f9d474d266de360c25b7ef3efafa0fe0b78765aa1cae32b402a0865ac
5
5
  SHA512:
6
- metadata.gz: 896b3821ad99f02449f652090c6b4249a932d454bd03e58879c2fad030d6179480b208c36bd07003dd3c58f96cd7630e28aa1afa026cc83f907a3bcf015f2f02
7
- data.tar.gz: bdc286d0c8df062b33fc6d25fd6d3d4348dc82cce74703d26a12d8374a91c5e378e3d7f03ff2d617a76beab88828a8004d3457997394df2a9832277ca308f411
6
+ metadata.gz: b343a5a32c22f73fd18b33235e9dfd4adcc4c6f3236bac881ad37160dce5af9a7b79e836643ba126e3c0f2943d0187ffb804fe1688fdd6f9599966d39950fa48
7
+ data.tar.gz: 98fea72cc28767839cead8d54d75f9d2ac262999bb92b5ba446d81abfb9d43ef7986c99bccc523c892916df6cf605b3e5fcf305935161bf9bdf371ab24e44196
data/.circleci/config.yml CHANGED
@@ -23,6 +23,13 @@ aliases:
23
23
  name: Run linting tool
24
24
  command: bundle exec rake rubocop
25
25
 
26
+ - &credentials
27
+ name: Retrieve temporary Algolia credentials if needed
28
+ command: |
29
+ if [ "$CIRCLE_PR_REPONAME" ]; then
30
+ curl -s https://algoliasearch-client-keygen.herokuapp.com | sh >> $BASH_ENV
31
+ fi
32
+
26
33
  - &run_tests
27
34
  name: Run unit and integration tests
28
35
  command: |
@@ -73,6 +80,7 @@ jobs:
73
80
  - restore_cache: *restore_cache
74
81
  - run: *install_bundler
75
82
  - save_cache: *save_cache
83
+ - run: *credentials
76
84
  - run: *run_tests
77
85
 
78
86
  test_jruby:
@@ -88,6 +96,7 @@ jobs:
88
96
  - restore_cache: *restore_cache
89
97
  - run: *install_bundler
90
98
  - save_cache: *save_cache
99
+ - run: *credentials
91
100
  - run: *run_tests
92
101
 
93
102
  release:
data/CHANGELOG.md CHANGED
@@ -1,6 +1,19 @@
1
1
  # ChangeLog
2
2
 
3
- ## [Unreleased](https://github.com/algolia/algoliasearch-client-ruby/compare/2.0.4...master)
3
+ ## [Unreleased](https://github.com/algolia/algoliasearch-client-ruby/compare/2.1.1..master)
4
+
5
+ ## [2.1.1](https://github.com/algolia/algoliasearch-client-ruby/compare/2.1.0...2.1.1) (2021-05-27)
6
+
7
+ ### Fix
8
+ - Bug with read/write nodes caching ([`#455`](https://github.com/algolia/algoliasearch-client-ruby/pull/455))
9
+
10
+ ## [2.1.0](https://github.com/algolia/algoliasearch-client-ruby/compare/2.0.4...2.1.0) (2021-03-30)
11
+
12
+ ### Feat
13
+ - Custom dictionaries methods
14
+
15
+ ### Fix
16
+ - The parameter `forwardToReplicas` should be handled independently in the `set_settings` method
4
17
 
5
18
  ## [2.0.4](https://github.com/algolia/algoliasearch-client-ruby/compare/2.0.3...2.0.4) (2021-01-05)
6
19
 
data/lib/algolia.rb CHANGED
@@ -20,6 +20,7 @@ require 'algolia/responses/indexing_response'
20
20
  require 'algolia/responses/add_api_key_response'
21
21
  require 'algolia/responses/update_api_key_response'
22
22
  require 'algolia/responses/delete_api_key_response'
23
+ require 'algolia/responses/dictionary_response'
23
24
  require 'algolia/responses/restore_api_key_response'
24
25
  require 'algolia/responses/multiple_batch_indexing_response'
25
26
  require 'algolia/responses/multiple_response'
@@ -82,4 +82,53 @@ module Helpers
82
82
  end
83
83
  res
84
84
  end
85
+
86
+ # Check the passed object to determine if it's an array
87
+ #
88
+ # @param object [Object]
89
+ #
90
+ def check_array(object)
91
+ raise Algolia::AlgoliaError, 'argument must be an array of objects' unless object.is_a?(Array)
92
+ end
93
+
94
+ # Check the passed object
95
+ #
96
+ # @param object [Object]
97
+ # @param in_array [Boolean] whether the object is an array or not
98
+ #
99
+ def check_object(object, in_array = false)
100
+ case object
101
+ when Array
102
+ raise Algolia::AlgoliaError, in_array ? 'argument must be an array of objects' : 'argument must not be an array'
103
+ when String, Integer, Float, TrueClass, FalseClass, NilClass
104
+ raise Algolia::AlgoliaError, "argument must be an #{'array of' if in_array} object, got: #{object.inspect}"
105
+ end
106
+ end
107
+
108
+ # Check if passed object has a objectID
109
+ #
110
+ # @param object [Object]
111
+ # @param object_id [String]
112
+ #
113
+ def get_object_id(object, object_id = nil)
114
+ check_object(object)
115
+ object_id ||= object[:objectID] || object['objectID']
116
+ raise Algolia::AlgoliaError, "Missing 'objectID'" if object_id.nil?
117
+ object_id
118
+ end
119
+
120
+ # Build a batch request
121
+ #
122
+ # @param action [String] action to perform on the engine
123
+ # @param objects [Array] objects on which build the action
124
+ # @param with_object_id [Boolean] if set to true, check if each object has an objectID set
125
+ #
126
+ def chunk(action, objects, with_object_id = false)
127
+ objects.map do |object|
128
+ check_object(object, true)
129
+ request = { action: action, body: object }
130
+ request[:objectID] = get_object_id(object).to_s if with_object_id
131
+ request
132
+ end
133
+ end
85
134
  end
@@ -9,9 +9,9 @@ module Algolia
9
9
  # @param logger [Object] logger used to log requests. Defaults to Algolia::LoggerHelper
10
10
  #
11
11
  def initialize(adapter, logger)
12
- @adapter = adapter
13
- @logger = logger
14
- @connection = nil
12
+ @adapter = adapter
13
+ @logger = logger
14
+ @connections = {}
15
15
  end
16
16
 
17
17
  # Sends request to the engine
@@ -65,7 +65,7 @@ module Algolia
65
65
  # @return [Faraday::Connection]
66
66
  #
67
67
  def connection(host)
68
- @connection ||= Faraday.new(build_url(host)) do |f|
68
+ @connections[host.accept] ||= Faraday.new(build_url(host)) do |f|
69
69
  f.adapter @adapter.to_sym
70
70
  end
71
71
  end
@@ -0,0 +1,33 @@
1
+ module Algolia
2
+ class DictionaryResponse < BaseResponse
3
+ include CallType
4
+
5
+ attr_reader :raw_response
6
+
7
+ # @param client [Search::Client] Algolia Search Client used for verification
8
+ # @param response [Hash] Raw response from the client
9
+ #
10
+ def initialize(client, response)
11
+ @client = client
12
+ @raw_response = response
13
+ @done = false
14
+ end
15
+
16
+ # Wait for the task to complete
17
+ #
18
+ # @param opts [Hash] contains extra parameters to send with your query
19
+ #
20
+ def wait(_opts = {})
21
+ until @done
22
+ res = @client.custom_request({}, path_encode('/1/task/%s', @raw_response[:taskID]), :GET, READ)
23
+ status = get_option(res, 'status')
24
+ if status == 'published'
25
+ @done = true
26
+ end
27
+ sleep(Defaults::WAIT_TASK_DEFAULT_TIME_BEFORE_RETRY / 1000)
28
+ end
29
+
30
+ self
31
+ end
32
+ end
33
+ end
@@ -80,7 +80,7 @@ module Algolia
80
80
  end
81
81
 
82
82
  # # # # # # # # # # # # # # # # # # # # #
83
- # MISC
83
+ # INDEX METHODS
84
84
  # # # # # # # # # # # # # # # # # # # # #
85
85
 
86
86
  # Initialize an index with a given name
@@ -594,12 +594,185 @@ module Algolia
594
594
  @transporter.read(:GET, '/1/clusters/mapping/pending' + handle_params({ getClusters: retrieve_mappings }), {}, request_options)
595
595
  end
596
596
 
597
- #
598
597
  # Aliases the pending_mappings? method
599
598
  #
600
599
  alias_method :has_pending_mappings, :pending_mappings?
601
600
 
601
+ # # # # # # # # # # # # # # # # # # # # #
602
+ # CUSTOM DICTIONARIES METHODS
603
+ # # # # # # # # # # # # # # # # # # # # #
604
+
605
+ # Save entries for a given dictionary
606
+ #
607
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
608
+ # @param dictionary_entries [Array<Hash>] array of dictionary entries
609
+ # @param opts [Hash] contains extra parameters to send with your query
610
+ #
611
+ # @return DictionaryResponse
612
+ #
613
+ def save_dictionary_entries(dictionary, dictionary_entries, opts = {})
614
+ response = @transporter.write(
615
+ :POST,
616
+ path_encode('/1/dictionaries/%s/batch', dictionary),
617
+ { clearExistingDictionaryEntries: false, requests: chunk('addEntry', dictionary_entries) },
618
+ opts
619
+ )
620
+
621
+ DictionaryResponse.new(self, response)
622
+ end
623
+
624
+ # Save entries for a given dictionary and wait for the task to finish
625
+ #
626
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
627
+ # @param dictionary_entries [Array<Hash>] array of dictionary entries
628
+ # @param opts [Hash] contains extra parameters to send with your query
629
+ #
630
+ def save_dictionary_entries!(dictionary, dictionary_entries, opts = {})
631
+ response = save_dictionary_entries(dictionary, dictionary_entries, opts)
632
+
633
+ response.wait(opts)
634
+ end
635
+
636
+ # Replace entries for a given dictionary
637
+ #
638
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
639
+ # @param dictionary_entries [Array<Hash>] array of dictionary entries
640
+ # @param opts [Hash] contains extra parameters to send with your query
641
+ #
642
+ # @return DictionaryResponse
643
+ #
644
+ def replace_dictionary_entries(dictionary, dictionary_entries, opts = {})
645
+ response = @transporter.write(
646
+ :POST,
647
+ path_encode('/1/dictionaries/%s/batch', dictionary),
648
+ { clearExistingDictionaryEntries: true, requests: chunk('addEntry', dictionary_entries) },
649
+ opts
650
+ )
651
+
652
+ DictionaryResponse.new(self, response)
653
+ end
654
+
655
+ # Replace entries for a given dictionary and wait for the task to finish
656
+ #
657
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
658
+ # @param dictionary_entries [Array<Hash>] array of dictionary entries
659
+ # @param opts [Hash] contains extra parameters to send with your query
660
+ #
661
+ def replace_dictionary_entries!(dictionary, dictionary_entries, opts = {})
662
+ response = replace_dictionary_entries(dictionary, dictionary_entries, opts)
663
+
664
+ response.wait(opts)
665
+ end
666
+
667
+ # Delete entries for a given dictionary
668
+ #
669
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
670
+ # @param object_ids [Array<Hash>] array of object ids
671
+ # @param opts [Hash] contains extra parameters to send with your query
672
+ #
673
+ # @return DictionaryResponse
674
+ #
675
+ def delete_dictionary_entries(dictionary, object_ids, opts = {})
676
+ request = object_ids.map do |object_id|
677
+ { objectID: object_id }
678
+ end
679
+ response = @transporter.write(
680
+ :POST,
681
+ path_encode('/1/dictionaries/%s/batch', dictionary),
682
+ { clearExistingDictionaryEntries: false, requests: chunk('deleteEntry', request) },
683
+ opts
684
+ )
685
+
686
+ DictionaryResponse.new(self, response)
687
+ end
688
+
689
+ # Delete entries for a given dictionary and wait for the task to finish
690
+ #
691
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
692
+ # @param object_ids [Array<Hash>] array of object ids
693
+ # @param opts [Hash] contains extra parameters to send with your query
602
694
  #
695
+ def delete_dictionary_entries!(dictionary, object_ids, opts = {})
696
+ response = delete_dictionary_entries(dictionary, object_ids, opts)
697
+
698
+ response.wait(opts)
699
+ end
700
+
701
+ # Clear all entries for a given dictionary
702
+ #
703
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
704
+ # @param opts [Hash] contains extra parameters to send with your query
705
+ #
706
+ # @return DictionaryResponse
707
+ #
708
+ def clear_dictionary_entries(dictionary, opts = {})
709
+ replace_dictionary_entries(dictionary, [], opts)
710
+ end
711
+
712
+ # Clear all entries for a given dictionary and wait for the task to finish
713
+ #
714
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
715
+ # @param opts [Hash] contains extra parameters to send with your query
716
+ #
717
+ def clear_dictionary_entries!(dictionary, opts = {})
718
+ response = replace_dictionary_entries(dictionary, [], opts)
719
+
720
+ response.wait(opts)
721
+ end
722
+
723
+ # Search entries for a given dictionary
724
+ #
725
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
726
+ # @param query [String] query to send
727
+ # @param opts [Hash] contains extra parameters to send with your query
728
+ #
729
+ def search_dictionary_entries(dictionary, query, opts = {})
730
+ @transporter.read(
731
+ :POST,
732
+ path_encode('/1/dictionaries/%s/search', dictionary),
733
+ { query: query },
734
+ opts
735
+ )
736
+ end
737
+
738
+ # Set settings for all the dictionaries
739
+ #
740
+ # @param dictionary_settings [Hash]
741
+ # @param opts [Hash] contains extra parameters to send with your query
742
+ #
743
+ # @return DictionaryResponse
744
+ #
745
+ def set_dictionary_settings(dictionary_settings, opts = {})
746
+ response = @transporter.write(:PUT, '/1/dictionaries/*/settings', dictionary_settings, opts)
747
+
748
+ DictionaryResponse.new(self, response)
749
+ end
750
+
751
+ # Set settings for all the dictionaries and wait for the task to finish
752
+ #
753
+ # @param dictionary_settings [Hash]
754
+ # @param opts [Hash] contains extra parameters to send with your query
755
+ #
756
+ # @return DictionaryResponse
757
+ #
758
+ def set_dictionary_settings!(dictionary_settings, opts = {})
759
+ response = set_dictionary_settings(dictionary_settings, opts)
760
+
761
+ response.wait(opts)
762
+ end
763
+
764
+ # Retrieve settings for all the dictionaries
765
+ #
766
+ # @param opts [Hash] contains extra parameters to send with your query
767
+ #
768
+ def get_dictionary_settings(opts = {})
769
+ @transporter.read(:GET, '/1/dictionaries/*/settings', {}, opts)
770
+ end
771
+
772
+ # # # # # # # # # # # # # # # # # # # # #
773
+ # MISC METHODS
774
+ # # # # # # # # # # # # # # # # # # # # #
775
+
603
776
  # Method available to make custom requests to the API
604
777
  #
605
778
  def custom_request(data, uri, method, call_type, opts = {})
@@ -987,7 +987,15 @@ module Algolia
987
987
  # @return [IndexingResponse]
988
988
  #
989
989
  def set_settings(settings, opts = {})
990
- response = @transporter.write(:PUT, path_encode('/1/indexes/%s/settings', @name), settings, opts)
990
+ request_options = symbolize_hash(opts)
991
+ forward_to_replicas = request_options.delete(:forwardToReplicas) || false
992
+
993
+ response = @transporter.write(
994
+ :PUT,
995
+ path_encode('/1/indexes/%s/settings', @name) + handle_params({ forwardToReplicas: forward_to_replicas }),
996
+ settings,
997
+ request_options
998
+ )
991
999
 
992
1000
  IndexingResponse.new(self, response)
993
1001
  end
@@ -1037,55 +1045,6 @@ module Algolia
1037
1045
 
1038
1046
  private
1039
1047
 
1040
- # Check the passed object to determine if it's an array
1041
- #
1042
- # @param object [Object]
1043
- #
1044
- def check_array(object)
1045
- raise AlgoliaError, 'argument must be an array of objects' unless object.is_a?(Array)
1046
- end
1047
-
1048
- # Check the passed object
1049
- #
1050
- # @param object [Object]
1051
- # @param in_array [Boolean] whether the object is an array or not
1052
- #
1053
- def check_object(object, in_array = false)
1054
- case object
1055
- when Array
1056
- raise AlgoliaError, in_array ? 'argument must be an array of objects' : 'argument must not be an array'
1057
- when String, Integer, Float, TrueClass, FalseClass, NilClass
1058
- raise AlgoliaError, "argument must be an #{'array of' if in_array} object, got: #{object.inspect}"
1059
- end
1060
- end
1061
-
1062
- # Check if passed object has a objectID
1063
- #
1064
- # @param object [Object]
1065
- # @param object_id [String]
1066
- #
1067
- def get_object_id(object, object_id = nil)
1068
- check_object(object)
1069
- object_id ||= object[:objectID] || object['objectID']
1070
- raise AlgoliaError, "Missing 'objectID'" if object_id.nil?
1071
- object_id
1072
- end
1073
-
1074
- # Build a batch request
1075
- #
1076
- # @param action [String] action to perform on the engine
1077
- # @param objects [Array] objects on which build the action
1078
- # @param with_object_id [Boolean] if set to true, check if each object has an objectID set
1079
- #
1080
- def chunk(action, objects, with_object_id = false)
1081
- objects.map do |object|
1082
- check_object(object, true)
1083
- request = { action: action, body: object }
1084
- request[:objectID] = get_object_id(object).to_s if with_object_id
1085
- request
1086
- end
1087
- end
1088
-
1089
1048
  def raw_batch(requests, opts)
1090
1049
  @transporter.write(:POST, path_encode('/1/indexes/%s/batch', @name), { requests: requests }, opts)
1091
1050
  end
@@ -1,3 +1,3 @@
1
1
  module Algolia
2
- VERSION = '2.0.4'.freeze
2
+ VERSION = '2.1.1'.freeze
3
3
  end
@@ -23,7 +23,9 @@ class AnalyticsClientTest < BaseTest
23
23
  endAt: tomorrow.strftime('%Y-%m-%dT%H:%M:%SZ')
24
24
  }
25
25
 
26
- response = client.add_ab_test(ab_test)
26
+ response = retry_test do
27
+ client.add_ab_test(ab_test)
28
+ end
27
29
  ab_test_id = response[:abTestID]
28
30
 
29
31
  index1.wait_task(response[:taskID])
@@ -86,7 +88,9 @@ class AnalyticsClientTest < BaseTest
86
88
  endAt: tomorrow.strftime('%Y-%m-%dT%H:%M:%SZ')
87
89
  }
88
90
 
89
- response = client.add_ab_test(ab_test)
91
+ response = retry_test do
92
+ client.add_ab_test(ab_test)
93
+ end
90
94
  ab_test_id = response[:abTestID]
91
95
 
92
96
  index.wait_task(response[:taskID])
@@ -1,3 +1,4 @@
1
+ require 'securerandom'
1
2
  require_relative 'base_test'
2
3
 
3
4
  class SearchClientTest < BaseTest
@@ -223,7 +224,9 @@ class SearchClientTest < BaseTest
223
224
  assert_includes api_keys, @api_key[:value]
224
225
 
225
226
  @@search_client.update_api_key!(@api_key[:value], { maxHitsPerQuery: 42 })
226
- updated_api_key = @@search_client.get_api_key(@api_key[:value])
227
+ updated_api_key = retry_test do
228
+ @@search_client.get_api_key(@api_key[:value], test: 'test')
229
+ end
227
230
  assert_equal 42, updated_api_key[:maxHitsPerQuery]
228
231
 
229
232
  @@search_client.delete_api_key!(@api_key[:value])
@@ -234,18 +237,13 @@ class SearchClientTest < BaseTest
234
237
 
235
238
  assert_equal 'Key does not exist', exception.message
236
239
 
237
- loop do
238
- begin
239
- @@search_client.restore_api_key!(@api_key[:value])
240
- break
241
- rescue Algolia::AlgoliaHttpError => e
242
- if e.code != 404
243
- raise StandardError
244
- end
245
- end
240
+ retry_test do
241
+ @@search_client.restore_api_key!(@api_key[:value])
246
242
  end
247
243
 
248
- restored_key = @@search_client.get_api_key(@api_key[:value])
244
+ restored_key = retry_test do
245
+ @@search_client.get_api_key(@api_key[:value])
246
+ end
249
247
 
250
248
  refute_nil restored_key
251
249
  end
@@ -334,7 +332,12 @@ class SearchClientTest < BaseTest
334
332
  secured_index1 = secured_client.init_index(@index1.name)
335
333
  secured_index2 = secured_client.init_index(@index2.name)
336
334
 
337
- secured_index1.search('')
335
+ res = retry_test do
336
+ secured_index1.search('')
337
+ end
338
+
339
+ assert_equal 1, res[:hits].length
340
+
338
341
  exception = assert_raises Algolia::AlgoliaHttpError do
339
342
  secured_index2.search('')
340
343
  end
@@ -367,5 +370,96 @@ class SearchClientTest < BaseTest
367
370
  assert_equal 'The SecuredAPIKey doesn\'t have a validUntil parameter.', exception.message
368
371
  end
369
372
  end
373
+
374
+ describe 'Custom Dictionaries' do
375
+ def before_all
376
+ @client = Algolia::Search::Client.create(APPLICATION_ID_2, ADMIN_KEY_2)
377
+ end
378
+
379
+ def test_stopwords_dictionaries
380
+ entry_id = SecureRandom.hex
381
+ assert_equal 0, @client.search_dictionary_entries('stopwords', entry_id)[:nbHits]
382
+
383
+ entry = {
384
+ objectID: entry_id,
385
+ language: 'en',
386
+ word: 'down'
387
+ }
388
+ @client.save_dictionary_entries!('stopwords', [entry])
389
+
390
+ stopwords = @client.search_dictionary_entries('stopwords', entry_id)
391
+ assert_equal 1, stopwords[:nbHits]
392
+ assert_equal stopwords[:hits][0][:objectID], entry[:objectID]
393
+ assert_equal stopwords[:hits][0][:word], entry[:word]
394
+
395
+ @client.delete_dictionary_entries!('stopwords', [entry_id])
396
+ assert_equal 0, @client.search_dictionary_entries('stopwords', entry_id)[:nbHits]
397
+
398
+ old_dictionary_state = @client.search_dictionary_entries('stopwords', '')
399
+ old_dictionary_entries = old_dictionary_state[:hits].map do |hit|
400
+ hit.reject { |key| key == :type }
401
+ end
402
+
403
+ @client.save_dictionary_entries!('stopwords', [entry])
404
+ assert_equal 1, @client.search_dictionary_entries('stopwords', entry_id)[:nbHits]
405
+
406
+ @client.replace_dictionary_entries!('stopwords', old_dictionary_entries)
407
+ assert_equal 0, @client.search_dictionary_entries('stopwords', entry_id)[:nbHits]
408
+
409
+ stopwords_settings = {
410
+ disableStandardEntries: {
411
+ stopwords: {
412
+ en: true
413
+ }
414
+ }
415
+ }
416
+
417
+ @client.set_dictionary_settings!(stopwords_settings)
418
+
419
+ assert_equal @client.get_dictionary_settings, stopwords_settings
420
+ end
421
+
422
+ def test_plurals_dictionaries
423
+ entry_id = SecureRandom.hex
424
+ assert_equal 0, @client.search_dictionary_entries('plurals', entry_id)[:nbHits]
425
+
426
+ entry = {
427
+ objectID: entry_id,
428
+ language: 'fr',
429
+ words: %w(cheval chevaux)
430
+ }
431
+ @client.save_dictionary_entries!('plurals', [entry])
432
+
433
+ plurals = @client.search_dictionary_entries('plurals', entry_id)
434
+ assert_equal 1, plurals[:nbHits]
435
+ assert_equal plurals[:hits][0][:objectID], entry[:objectID]
436
+ assert_equal plurals[:hits][0][:words], entry[:words]
437
+
438
+ @client.delete_dictionary_entries!('plurals', [entry_id])
439
+ assert_equal 0, @client.search_dictionary_entries('plurals', entry_id)[:nbHits]
440
+ end
441
+
442
+ def test_compounds_dictionaries
443
+ entry_id = SecureRandom.hex
444
+ assert_equal 0, @client.search_dictionary_entries('compounds', entry_id)[:nbHits]
445
+
446
+ entry = {
447
+ objectID: entry_id,
448
+ language: 'de',
449
+ word: 'kopfschmerztablette',
450
+ decomposition: %w(kopf schmerz tablette)
451
+ }
452
+ @client.save_dictionary_entries!('compounds', [entry])
453
+
454
+ compounds = @client.search_dictionary_entries('compounds', entry_id)
455
+ assert_equal 1, compounds[:nbHits]
456
+ assert_equal compounds[:hits][0][:objectID], entry[:objectID]
457
+ assert_equal compounds[:hits][0][:word], entry[:word]
458
+ assert_equal compounds[:hits][0][:decomposition], entry[:decomposition]
459
+
460
+ @client.delete_dictionary_entries!('compounds', [entry_id])
461
+ assert_equal 0, @client.search_dictionary_entries('compounds', entry_id)[:nbHits]
462
+ end
463
+ end
370
464
  end
371
465
  end
@@ -274,6 +274,9 @@ class SearchIndexTest < BaseTest
274
274
  @index.set_settings!(settings)
275
275
 
276
276
  assert_equal @index.get_settings, settings
277
+
278
+ # check that the forwardToReplicas parameter is passed correctly
279
+ assert @index.set_settings!(settings, { forwardToReplicas: true })
277
280
  end
278
281
  end
279
282
 
data/test/test_helper.rb CHANGED
@@ -87,3 +87,15 @@ def rule_without_metadata(rule)
87
87
  rule.delete(:_metadata)
88
88
  rule
89
89
  end
90
+
91
+ def retry_test(delay = 0.1, max_retries = 30)
92
+ (1...max_retries).each do |i|
93
+ begin
94
+ return yield
95
+ rescue Algolia::AlgoliaHttpError
96
+ sleep delay * i
97
+ end
98
+ end
99
+
100
+ raise StandardError, 'reached the maximum number of retries'
101
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: algolia
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.4
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Algolia
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-05 00:00:00.000000000 Z
11
+ date: 2021-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -238,6 +238,7 @@ files:
238
238
  - lib/algolia/responses/add_api_key_response.rb
239
239
  - lib/algolia/responses/base_response.rb
240
240
  - lib/algolia/responses/delete_api_key_response.rb
241
+ - lib/algolia/responses/dictionary_response.rb
241
242
  - lib/algolia/responses/indexing_response.rb
242
243
  - lib/algolia/responses/multiple_batch_indexing_response.rb
243
244
  - lib/algolia/responses/multiple_response.rb
@@ -304,7 +305,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
304
305
  - !ruby/object:Gem::Version
305
306
  version: '0'
306
307
  requirements: []
307
- rubygems_version: 3.1.4
308
+ rubygems_version: 3.0.6
308
309
  signing_key:
309
310
  specification_version: 4
310
311
  summary: A simple Ruby client for the algolia.com REST API