algolia 2.0.4 → 2.2.2

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: 5c2f4626569fa71c66f1801a6608a0d66bdd7afc5d2d42342856d8083281d0ee
4
+ data.tar.gz: bbc716503ac0354dd80a1e5d1196cfc8ff5e8d80c3c166c196bd1ec5e227a446
5
5
  SHA512:
6
- metadata.gz: 896b3821ad99f02449f652090c6b4249a932d454bd03e58879c2fad030d6179480b208c36bd07003dd3c58f96cd7630e28aa1afa026cc83f907a3bcf015f2f02
7
- data.tar.gz: bdc286d0c8df062b33fc6d25fd6d3d4348dc82cce74703d26a12d8374a91c5e378e3d7f03ff2d617a76beab88828a8004d3457997394df2a9832277ca308f411
6
+ metadata.gz: bd82583938e41074786a9f6e3518256af5f54c6946e8224a9e2ecc40952f211475dbec10ba5d054058764bdccbdceff80a9147c195a8c3f62a5ab4f033c11757
7
+ data.tar.gz: 25971344a9f64260d29f8c1a7878605a2e408369de05b4e4add74e828697cefde461bb83ed5564dbd6f94de3844844e6e357568e830de53a3d77253a27151e33
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:
@@ -122,7 +131,7 @@ workflows:
122
131
  - test_ruby:
123
132
  matrix:
124
133
  parameters:
125
- version: ['2.2', '2.3', '2.4', '2.5', '2.6', '2.7']
134
+ version: ['2.2', '2.3', '2.4', '2.5', '2.6', '2.7', '3.0']
126
135
  filters:
127
136
  tags:
128
137
  only: /.*/
data/CHANGELOG.md CHANGED
@@ -1,6 +1,32 @@
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.2.2..master)
4
+
5
+ ## [2.2.1](https://github.com/algolia/algoliasearch-client-ruby/compare/2.2.1...2.2.2) (2021-12-08)
6
+ ### Fixed
7
+ - Added a `status` field to the `MockRequester` ([`#467`](https://github.com/algolia/algoliasearch-client-ruby/pull/467))
8
+
9
+ ## [2.2.1](https://github.com/algolia/algoliasearch-client-ruby/compare/2.2.0...2.2.1) (2021-11-12)
10
+ ### Chore
11
+ - Deprecated `RecommendationClient` in favor of `PersonalizationClient` ([`#461`](https://github.com/algolia/algoliasearch-client-ruby/pull/461))
12
+
13
+ ## [2.2.0](https://github.com/algolia/algoliasearch-client-ruby/compare/2.1.1...2.2.0) (2021-11-08)
14
+ ### Added
15
+ - Added RecommendClient ([`#466`](https://github.com/algolia/algoliasearch-client-ruby/pull/466))
16
+ - Added `search` alias for `multiple_queries` ([`#457`](https://github.com/algolia/algoliasearch-client-ruby/pull/457))
17
+
18
+ ## [2.1.1](https://github.com/algolia/algoliasearch-client-ruby/compare/2.1.0...2.1.1) (2021-05-27)
19
+
20
+ ### Fix
21
+ - Bug with read/write nodes caching ([`#455`](https://github.com/algolia/algoliasearch-client-ruby/pull/455))
22
+
23
+ ## [2.1.0](https://github.com/algolia/algoliasearch-client-ruby/compare/2.0.4...2.1.0) (2021-03-30)
24
+
25
+ ### Feat
26
+ - Custom dictionaries methods
27
+
28
+ ### Fix
29
+ - The parameter `forwardToReplicas` should be handled independently in the `set_settings` method
4
30
 
5
31
  ## [2.0.4](https://github.com/algolia/algoliasearch-client-ruby/compare/2.0.3...2.0.4) (2021-01-05)
6
32
 
data/README.md CHANGED
@@ -41,7 +41,7 @@ Then, create objects on your index:
41
41
  client = Algolia::Search::Client.create('YourApplicationID', 'YourAPIKey')
42
42
  index = client.init_index('your_index_name')
43
43
 
44
- index.save_objects([objectID: 1, name: 'Foo'])
44
+ index.save_objects([{objectID: 1, name: 'Foo'}])
45
45
  ```
46
46
 
47
47
  Finally, you may begin searching a object using the `search` method:
@@ -0,0 +1,20 @@
1
+ module Algolia
2
+ module Personalization
3
+ class Config < BaseConfig
4
+ attr_accessor :region, :default_hosts
5
+
6
+ # Initialize a config
7
+ #
8
+ # @option options [String] :application_id
9
+ # @option options [String] :api_key
10
+ # @option options [String] :region
11
+ #
12
+ def initialize(opts = {})
13
+ super(opts)
14
+
15
+ @region = opts[:region] || 'us'
16
+ @default_hosts = [Transport::StatefulHost.new("personalization.#{region}.algolia.com")]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,6 @@
1
+ module Algolia
2
+ module Recommend
3
+ class Config < Algolia::Search::Config
4
+ end
5
+ end
6
+ end
@@ -1,20 +1,7 @@
1
1
  module Algolia
2
2
  module Recommendation
3
- class Config < BaseConfig
4
- attr_accessor :region, :default_hosts
5
-
6
- # Initialize a config
7
- #
8
- # @option options [String] :application_id
9
- # @option options [String] :api_key
10
- # @option options [String] :region
11
- #
12
- def initialize(opts = {})
13
- super(opts)
14
-
15
- @region = opts[:region] || 'us'
16
- @default_hosts = [Transport::StatefulHost.new("recommendation.#{region}.algolia.com")]
17
- end
3
+ # <b>DEPRECATED:</b> Please use <tt>Algolia::Personalization::Config</tt> instead.
4
+ class Config < Algolia::Personalization::Config
18
5
  end
19
6
  end
20
7
  end
@@ -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,60 @@
1
+ module Algolia
2
+ module Personalization
3
+ class Client
4
+ # Initializes the Personalization client
5
+ #
6
+ # @param personalization_config [Personalization::Config] a Personalization::Config object which contains your APP_ID and API_KEY
7
+ # @option adapter [Object] adapter object used for the connection
8
+ # @option logger [Object]
9
+ # @option http_requester [Object] http_requester object used for the connection
10
+ #
11
+ def initialize(personalization_config, opts = {})
12
+ @config = personalization_config
13
+ adapter = opts[:adapter] || Defaults::ADAPTER
14
+ logger = opts[:logger] || LoggerHelper.create('debug.log')
15
+ requester = opts[:http_requester] || Defaults::REQUESTER_CLASS.new(adapter, logger)
16
+ @transporter = Transport::Transport.new(@config, requester)
17
+ end
18
+
19
+ # Create a new client providing only app ID and API key
20
+ #
21
+ # @param app_id [String] Algolia application ID
22
+ # @param api_key [String] Algolia API key
23
+ #
24
+ # @return self
25
+ #
26
+ def self.create(app_id, api_key)
27
+ config = Personalization::Config.new(application_id: app_id, api_key: api_key)
28
+ create_with_config(config)
29
+ end
30
+
31
+ # Create a new client providing only an Personalization::Config object
32
+ #
33
+ # @param config [Personalization::Config]
34
+ #
35
+ # @return self
36
+ #
37
+ def self.create_with_config(config)
38
+ new(config)
39
+ end
40
+
41
+ # Set the personalization strategy.
42
+ #
43
+ # @param personalization_strategy [Hash] A strategy object.
44
+ #
45
+ # @return [Hash]
46
+ #
47
+ def set_personalization_strategy(personalization_strategy, opts = {})
48
+ @transporter.write(:POST, '1/strategies/personalization', personalization_strategy, opts)
49
+ end
50
+
51
+ # Get the personalization strategy.
52
+ #
53
+ # @return [Hash]
54
+ #
55
+ def get_personalization_strategy(opts = {})
56
+ @transporter.read(:GET, '1/strategies/personalization', {}, opts)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,134 @@
1
+ module Algolia
2
+ module Recommend
3
+ class Model
4
+ BOUGHT_TOGETHER = 'bought-together'
5
+ RELATED_PRODUCTS = 'related-products'
6
+ end
7
+
8
+ class Client
9
+ include Helpers
10
+
11
+ # Initializes the Recommend client
12
+ #
13
+ # @param recommend_config [Recommend::Config] a Recommend::Config object which contains your APP_ID and API_KEY
14
+ # @option adapter [Object] adapter object used for the connection
15
+ # @option logger [Object]
16
+ # @option http_requester [Object] http_requester object used for the connection
17
+ #
18
+ def initialize(recommend_config, opts = {})
19
+ @config = recommend_config
20
+ adapter = opts[:adapter] || Defaults::ADAPTER
21
+ logger = opts[:logger] || LoggerHelper.create('debug.log')
22
+ requester = opts[:http_requester] || Defaults::REQUESTER_CLASS.new(adapter, logger)
23
+ @transporter = Transport::Transport.new(@config, requester)
24
+ end
25
+
26
+ # Create a new client providing only app ID and API key
27
+ #
28
+ # @param app_id [String] Algolia application ID
29
+ # @param api_key [String] Algolia API key
30
+ #
31
+ # @return self
32
+ #
33
+ def self.create(app_id, api_key)
34
+ config = Recommend::Config.new(application_id: app_id, api_key: api_key)
35
+ create_with_config(config)
36
+ end
37
+
38
+ # Create a new client providing only an Recommend::Config object
39
+ #
40
+ # @param config [Recommend::Config]
41
+ #
42
+ # @return self
43
+ #
44
+ def self.create_with_config(config)
45
+ new(config)
46
+ end
47
+
48
+ # Get recommendation for the given queries
49
+ #
50
+ # @param requests [Array<Hash>] the queries to retrieve recommendations for
51
+ # @param opts [Hash] extra parameters to send with your request
52
+ #
53
+ # @return [Hash]
54
+ #
55
+ def get_recommendations(requests, opts = {})
56
+ @transporter.write(
57
+ :POST,
58
+ '/1/indexes/*/recommendations',
59
+ { requests: format_recommendation_requests(symbolize_all(requests)) },
60
+ opts
61
+ )
62
+ end
63
+
64
+ # Get related products for the given requests
65
+ #
66
+ # @param requests [Array<Hash>] the requests to get related products for
67
+ # @param opts [Hash] extra parameters to send with your request
68
+ #
69
+ # @return [Hash]
70
+ #
71
+ def get_related_products(requests, opts = {})
72
+ get_recommendations(
73
+ set_request_models(symbolize_all(requests), Model::RELATED_PRODUCTS),
74
+ opts
75
+ )
76
+ end
77
+
78
+ # Get frequently bought together items for the given requests
79
+ #
80
+ # @param requests [Array<Hash>] the requests to get frequently bought together items for
81
+ # @param opts [Hash] extra parameters to send with your request
82
+ #
83
+ # @return [Hash]
84
+ #
85
+ def get_frequently_bought_together(requests, opts = {})
86
+ get_recommendations(
87
+ set_request_models(symbolize_all(requests), Model::BOUGHT_TOGETHER),
88
+ opts
89
+ )
90
+ end
91
+
92
+ private
93
+
94
+ # Symbolize all hashes in an array
95
+ #
96
+ # @param hash_array [Array<Hash<String|Symbol, any>>] the hashes to symbolize
97
+ #
98
+ # @return [Array<Hash<Symbol, any>>]
99
+ #
100
+ def symbolize_all(hash_array)
101
+ hash_array.map { |q| symbolize_hash(q) }
102
+ end
103
+
104
+ # Format the recommendation requests
105
+ #
106
+ # @param requests [Array<Hash>] the requests to retrieve recommendations for
107
+ #
108
+ # @return [Array<Hash>]
109
+ #
110
+ def format_recommendation_requests(requests)
111
+ requests.map do |request|
112
+ request[:threshold] = 0 unless request[:threshold].is_a? Numeric
113
+ request.delete(:fallbackParameters) if request[:model] == Model::BOUGHT_TOGETHER
114
+
115
+ request
116
+ end
117
+ end
118
+
119
+ # Force the requests to target a specific model
120
+ #
121
+ # @param requests [Array<Hash>] the requests to change
122
+ # @param model [String] the model to enforce
123
+ #
124
+ # @return [Array<Hash>]
125
+ #
126
+ def set_request_models(requests, model)
127
+ requests.map do |query|
128
+ query[:model] = model
129
+ query
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -1,60 +1,7 @@
1
1
  module Algolia
2
2
  module Recommendation
3
- class Client
4
- # Initializes the Recommendation client
5
- #
6
- # @param recommendation_config [Recommendation::Config] a Recommendation::Config object which contains your APP_ID and API_KEY
7
- # @option adapter [Object] adapter object used for the connection
8
- # @option logger [Object]
9
- # @option http_requester [Object] http_requester object used for the connection
10
- #
11
- def initialize(recommendation_config, opts = {})
12
- @config = recommendation_config
13
- adapter = opts[:adapter] || Defaults::ADAPTER
14
- logger = opts[:logger] || LoggerHelper.create('debug.log')
15
- requester = opts[:http_requester] || Defaults::REQUESTER_CLASS.new(adapter, logger)
16
- @transporter = Transport::Transport.new(@config, requester)
17
- end
18
-
19
- # Create a new client providing only app ID and API key
20
- #
21
- # @param app_id [String] Algolia application ID
22
- # @param api_key [String] Algolia API key
23
- #
24
- # @return self
25
- #
26
- def self.create(app_id, api_key)
27
- config = Recommendation::Config.new(application_id: app_id, api_key: api_key)
28
- create_with_config(config)
29
- end
30
-
31
- # Create a new client providing only an Recommendation::Config object
32
- #
33
- # @param config [Recommendation::Config]
34
- #
35
- # @return self
36
- #
37
- def self.create_with_config(config)
38
- new(config)
39
- end
40
-
41
- # Set the personalization strategy.
42
- #
43
- # @param personalization_strategy [Hash] A strategy object.
44
- #
45
- # @return [Hash]
46
- #
47
- def set_personalization_strategy(personalization_strategy, opts = {})
48
- @transporter.write(:POST, '1/strategies/personalization', personalization_strategy, opts)
49
- end
50
-
51
- # Get the personalization strategy.
52
- #
53
- # @return [Hash]
54
- #
55
- def get_personalization_strategy(opts = {})
56
- @transporter.read(:GET, '1/strategies/personalization', {}, opts)
57
- end
3
+ # <b>DEPRECATED:</b> Please use <tt>Algolia::Personalization::Client</tt> instead.
4
+ class Client < Algolia::Personalization::Client
58
5
  end
59
6
  end
60
7
  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
@@ -480,6 +480,7 @@ module Algolia
480
480
  def multiple_queries(queries, opts = {})
481
481
  @transporter.read(:POST, '/1/indexes/*/queries', { requests: queries }, opts)
482
482
  end
483
+ alias_method :search, :multiple_queries
483
484
 
484
485
  # # # # # # # # # # # # # # # # # # # # #
485
486
  # MCM METHODS
@@ -594,12 +595,185 @@ module Algolia
594
595
  @transporter.read(:GET, '/1/clusters/mapping/pending' + handle_params({ getClusters: retrieve_mappings }), {}, request_options)
595
596
  end
596
597
 
597
- #
598
598
  # Aliases the pending_mappings? method
599
599
  #
600
600
  alias_method :has_pending_mappings, :pending_mappings?
601
601
 
602
+ # # # # # # # # # # # # # # # # # # # # #
603
+ # CUSTOM DICTIONARIES METHODS
604
+ # # # # # # # # # # # # # # # # # # # # #
605
+
606
+ # Save entries for a given dictionary
607
+ #
608
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
609
+ # @param dictionary_entries [Array<Hash>] array of dictionary entries
610
+ # @param opts [Hash] contains extra parameters to send with your query
611
+ #
612
+ # @return DictionaryResponse
613
+ #
614
+ def save_dictionary_entries(dictionary, dictionary_entries, opts = {})
615
+ response = @transporter.write(
616
+ :POST,
617
+ path_encode('/1/dictionaries/%s/batch', dictionary),
618
+ { clearExistingDictionaryEntries: false, requests: chunk('addEntry', dictionary_entries) },
619
+ opts
620
+ )
621
+
622
+ DictionaryResponse.new(self, response)
623
+ end
624
+
625
+ # Save entries for a given dictionary and wait for the task to finish
626
+ #
627
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
628
+ # @param dictionary_entries [Array<Hash>] array of dictionary entries
629
+ # @param opts [Hash] contains extra parameters to send with your query
630
+ #
631
+ def save_dictionary_entries!(dictionary, dictionary_entries, opts = {})
632
+ response = save_dictionary_entries(dictionary, dictionary_entries, opts)
633
+
634
+ response.wait(opts)
635
+ end
636
+
637
+ # Replace entries for a given dictionary
638
+ #
639
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
640
+ # @param dictionary_entries [Array<Hash>] array of dictionary entries
641
+ # @param opts [Hash] contains extra parameters to send with your query
642
+ #
643
+ # @return DictionaryResponse
644
+ #
645
+ def replace_dictionary_entries(dictionary, dictionary_entries, opts = {})
646
+ response = @transporter.write(
647
+ :POST,
648
+ path_encode('/1/dictionaries/%s/batch', dictionary),
649
+ { clearExistingDictionaryEntries: true, requests: chunk('addEntry', dictionary_entries) },
650
+ opts
651
+ )
652
+
653
+ DictionaryResponse.new(self, response)
654
+ end
655
+
656
+ # Replace entries for a given dictionary and wait for the task to finish
657
+ #
658
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
659
+ # @param dictionary_entries [Array<Hash>] array of dictionary entries
660
+ # @param opts [Hash] contains extra parameters to send with your query
661
+ #
662
+ def replace_dictionary_entries!(dictionary, dictionary_entries, opts = {})
663
+ response = replace_dictionary_entries(dictionary, dictionary_entries, opts)
664
+
665
+ response.wait(opts)
666
+ end
667
+
668
+ # Delete entries for a given dictionary
669
+ #
670
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
671
+ # @param object_ids [Array<Hash>] array of object ids
672
+ # @param opts [Hash] contains extra parameters to send with your query
673
+ #
674
+ # @return DictionaryResponse
675
+ #
676
+ def delete_dictionary_entries(dictionary, object_ids, opts = {})
677
+ request = object_ids.map do |object_id|
678
+ { objectID: object_id }
679
+ end
680
+ response = @transporter.write(
681
+ :POST,
682
+ path_encode('/1/dictionaries/%s/batch', dictionary),
683
+ { clearExistingDictionaryEntries: false, requests: chunk('deleteEntry', request) },
684
+ opts
685
+ )
686
+
687
+ DictionaryResponse.new(self, response)
688
+ end
689
+
690
+ # Delete entries for a given dictionary and wait for the task to finish
691
+ #
692
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
693
+ # @param object_ids [Array<Hash>] array of object ids
694
+ # @param opts [Hash] contains extra parameters to send with your query
602
695
  #
696
+ def delete_dictionary_entries!(dictionary, object_ids, opts = {})
697
+ response = delete_dictionary_entries(dictionary, object_ids, opts)
698
+
699
+ response.wait(opts)
700
+ end
701
+
702
+ # Clear all entries for a given dictionary
703
+ #
704
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
705
+ # @param opts [Hash] contains extra parameters to send with your query
706
+ #
707
+ # @return DictionaryResponse
708
+ #
709
+ def clear_dictionary_entries(dictionary, opts = {})
710
+ replace_dictionary_entries(dictionary, [], opts)
711
+ end
712
+
713
+ # Clear all entries for a given dictionary and wait for the task to finish
714
+ #
715
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
716
+ # @param opts [Hash] contains extra parameters to send with your query
717
+ #
718
+ def clear_dictionary_entries!(dictionary, opts = {})
719
+ response = replace_dictionary_entries(dictionary, [], opts)
720
+
721
+ response.wait(opts)
722
+ end
723
+
724
+ # Search entries for a given dictionary
725
+ #
726
+ # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
727
+ # @param query [String] query to send
728
+ # @param opts [Hash] contains extra parameters to send with your query
729
+ #
730
+ def search_dictionary_entries(dictionary, query, opts = {})
731
+ @transporter.read(
732
+ :POST,
733
+ path_encode('/1/dictionaries/%s/search', dictionary),
734
+ { query: query },
735
+ opts
736
+ )
737
+ end
738
+
739
+ # Set settings for all the dictionaries
740
+ #
741
+ # @param dictionary_settings [Hash]
742
+ # @param opts [Hash] contains extra parameters to send with your query
743
+ #
744
+ # @return DictionaryResponse
745
+ #
746
+ def set_dictionary_settings(dictionary_settings, opts = {})
747
+ response = @transporter.write(:PUT, '/1/dictionaries/*/settings', dictionary_settings, opts)
748
+
749
+ DictionaryResponse.new(self, response)
750
+ end
751
+
752
+ # Set settings for all the dictionaries and wait for the task to finish
753
+ #
754
+ # @param dictionary_settings [Hash]
755
+ # @param opts [Hash] contains extra parameters to send with your query
756
+ #
757
+ # @return DictionaryResponse
758
+ #
759
+ def set_dictionary_settings!(dictionary_settings, opts = {})
760
+ response = set_dictionary_settings(dictionary_settings, opts)
761
+
762
+ response.wait(opts)
763
+ end
764
+
765
+ # Retrieve settings for all the dictionaries
766
+ #
767
+ # @param opts [Hash] contains extra parameters to send with your query
768
+ #
769
+ def get_dictionary_settings(opts = {})
770
+ @transporter.read(:GET, '/1/dictionaries/*/settings', {}, opts)
771
+ end
772
+
773
+ # # # # # # # # # # # # # # # # # # # # #
774
+ # MISC METHODS
775
+ # # # # # # # # # # # # # # # # # # # # #
776
+
603
777
  # Method available to make custom requests to the API
604
778
  #
605
779
  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.2.2'.freeze
3
3
  end
data/lib/algolia.rb CHANGED
@@ -7,6 +7,8 @@ require 'algolia/config/base_config'
7
7
  require 'algolia/config/search_config'
8
8
  require 'algolia/config/analytics_config'
9
9
  require 'algolia/config/insights_config'
10
+ require 'algolia/config/recommend_config'
11
+ require 'algolia/config/personalization_config'
10
12
  require 'algolia/config/recommendation_config'
11
13
  require 'algolia/enums/call_type'
12
14
  require 'algolia/enums/retry_outcome_type'
@@ -20,6 +22,7 @@ require 'algolia/responses/indexing_response'
20
22
  require 'algolia/responses/add_api_key_response'
21
23
  require 'algolia/responses/update_api_key_response'
22
24
  require 'algolia/responses/delete_api_key_response'
25
+ require 'algolia/responses/dictionary_response'
23
26
  require 'algolia/responses/restore_api_key_response'
24
27
  require 'algolia/responses/multiple_batch_indexing_response'
25
28
  require 'algolia/responses/multiple_response'
@@ -32,6 +35,8 @@ require 'algolia/account_client'
32
35
  require 'algolia/search_client'
33
36
  require 'algolia/analytics_client'
34
37
  require 'algolia/insights_client'
38
+ require 'algolia/recommend_client'
39
+ require 'algolia/personalization_client'
35
40
  require 'algolia/recommendation_client'
36
41
  require 'algolia/error'
37
42
  require 'algolia/search_index'
@@ -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,25 +1,27 @@
1
1
  class MockRequester
2
+ attr_accessor :requests
2
3
  def initialize
3
4
  @connection = nil
5
+ @requests = []
4
6
  end
5
7
 
6
- def send_request(host, method, path, _body, headers, _timeout, _connect_timeout)
7
- connection = get_connection(host)
8
- response = {
9
- connection: connection,
8
+ def send_request(host, method, path, body, headers, timeout, connect_timeout)
9
+ request = {
10
10
  host: host,
11
+ method: method,
11
12
  path: path,
13
+ body: body,
12
14
  headers: headers,
13
- method: method,
14
- status: 200,
15
- body: '{"hits":[],"nbHits":0,"page":0,"nbPages":1,"hitsPerPage":20,"exhaustiveNbHits":true,"query":"test","params":"query=test","processingTimeMS":1}',
16
- success: true
15
+ timeout: timeout,
16
+ connect_timeout: connect_timeout
17
17
  }
18
18
 
19
+ @requests.push(request)
20
+
19
21
  Algolia::Http::Response.new(
20
- status: response[:status],
21
- body: response[:body],
22
- headers: response[:headers]
22
+ status: 200,
23
+ body: '{"hits": [], "status": "published"}',
24
+ headers: {}
23
25
  )
24
26
  end
25
27
 
@@ -0,0 +1,30 @@
1
+ require_relative 'base_test'
2
+ require 'date'
3
+
4
+ class PersonalizationClientTest < BaseTest
5
+ describe 'Personalization client' do
6
+ def test_personalization_client
7
+ client = Algolia::Personalization::Client.create(APPLICATION_ID_1, ADMIN_KEY_1)
8
+ personalization_strategy = {
9
+ eventsScoring: [
10
+ { eventName: 'Add to cart', eventType: 'conversion', score: 50 },
11
+ { eventName: 'Purchase', eventType: 'conversion', score: 100 }
12
+ ],
13
+ facetsScoring: [
14
+ { facetName: 'brand', score: 100 },
15
+ { facetName: 'categories', score: 10 }
16
+ ],
17
+ personalizationImpact: 0
18
+ }
19
+
20
+ begin
21
+ client.set_personalization_strategy(personalization_strategy)
22
+ rescue Algolia::AlgoliaHttpError => e
23
+ raise e unless e.code == 429
24
+ end
25
+ response = client.get_personalization_strategy
26
+
27
+ assert_equal response, personalization_strategy
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,70 @@
1
+ require 'securerandom'
2
+ require_relative 'base_test'
3
+
4
+ class RecommendClientTest < BaseTest
5
+ describe 'Recommendations' do
6
+ def test_get_recommendations
7
+ requester = MockRequester.new
8
+ client = Algolia::Recommend::Client.new(@@search_config, http_requester: requester)
9
+
10
+ # It correctly formats queries using the 'bought-together' model
11
+ client.get_recommendations([{ indexName: 'products', objectID: 'B018APC4LE', model: Algolia::Recommend::Model::BOUGHT_TOGETHER }])
12
+
13
+ # It correctly formats queries using the 'related-products' model
14
+ client.get_recommendations([{ indexName: 'products', objectID: 'B018APC4LE', model: Algolia::Recommend::Model::RELATED_PRODUCTS }])
15
+
16
+ # It correctly formats multiple queries.
17
+ client.get_recommendations(
18
+ [
19
+ { indexName: 'products', objectID: 'B018APC4LE-1', model: Algolia::Recommend::Model::RELATED_PRODUCTS, threshold: 0 },
20
+ { indexName: 'products', objectID: 'B018APC4LE-2', model: Algolia::Recommend::Model::RELATED_PRODUCTS, threshold: 0 }
21
+ ]
22
+ )
23
+
24
+ # It resets the threshold to 0 if it's not numeric.
25
+ client.get_recommendations([{ indexName: 'products', objectID: 'B018APC4LE', model: Algolia::Recommend::Model::BOUGHT_TOGETHER, threshold: nil }])
26
+
27
+ # It passes the threshold correctly if it's numeric.
28
+ client.get_recommendations([{ indexName: 'products', objectID: 'B018APC4LE', model: Algolia::Recommend::Model::BOUGHT_TOGETHER, threshold: 42 }])
29
+
30
+ assert_requests(
31
+ requester,
32
+ [
33
+ { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"bought-together","threshold":0}]}' },
34
+ { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"related-products","threshold":0}]}' },
35
+ { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE-1","model":"related-products","threshold":0},{"indexName":"products","objectID":"B018APC4LE-2","model":"related-products","threshold":0}]}' },
36
+ { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"bought-together","threshold":0}]}' },
37
+ { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"bought-together","threshold":42}]}' }
38
+ ]
39
+ )
40
+ end
41
+
42
+ def test_get_related_products
43
+ requester = MockRequester.new
44
+ client = Algolia::Recommend::Client.new(@@search_config, http_requester: requester)
45
+
46
+ client.get_related_products([{ indexName: 'products', objectID: 'B018APC4LE' }])
47
+
48
+ assert_requests(
49
+ requester,
50
+ [{ method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"related-products","threshold":0}]}' }]
51
+ )
52
+ end
53
+
54
+ def test_get_frequently_bought_together
55
+ requester = MockRequester.new
56
+ client = Algolia::Recommend::Client.new(@@search_config, http_requester: requester)
57
+
58
+ client.get_frequently_bought_together([{ indexName: 'products', objectID: 'B018APC4LE' }])
59
+ client.get_frequently_bought_together([{ indexName: 'products', objectID: 'B018APC4LE', fallbackParameters: {} }])
60
+
61
+ assert_requests(
62
+ requester,
63
+ [
64
+ { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"bought-together","threshold":0}]}' },
65
+ { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"bought-together","threshold":0}]}' }
66
+ ]
67
+ )
68
+ end
69
+ end
70
+ end
@@ -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
@@ -28,6 +28,22 @@ class Minitest::Test
28
28
  @@search_client = Algolia::Search::Client.new(@@search_config)
29
29
  end
30
30
 
31
+ def assert_requests(requester, requests)
32
+ refute_empty requests
33
+ refute_nil requester
34
+
35
+ actual_requests = requester.requests
36
+ assert_equal requests.size, actual_requests.size
37
+
38
+ requests.each_with_index do |expected_request, i|
39
+ request = actual_requests[i]
40
+
41
+ assert_equal(expected_request[:body], request[:body])
42
+ assert_equal(expected_request[:method], request[:method])
43
+ assert_equal(expected_request[:path], request[:path])
44
+ end
45
+ end
46
+
31
47
  def check_environment_variables
32
48
  raise Algolia::AlgoliaError, 'ALGOLIA_APPLICATION_ID_1 must be defined' if ENV['ALGOLIA_APPLICATION_ID_1'].to_s.strip.empty?
33
49
  raise Algolia::AlgoliaError, 'ALGOLIA_ADMIN_KEY_1 must be defined' if ENV['ALGOLIA_ADMIN_KEY_1'].to_s.strip.empty?
@@ -87,3 +103,15 @@ def rule_without_metadata(rule)
87
103
  rule.delete(:_metadata)
88
104
  rule
89
105
  end
106
+
107
+ def retry_test(delay = 0.1, max_retries = 30)
108
+ (1...max_retries).each do |i|
109
+ begin
110
+ return yield
111
+ rescue Algolia::AlgoliaHttpError
112
+ sleep delay * i
113
+ end
114
+ end
115
+
116
+ raise StandardError, 'reached the maximum number of retries'
117
+ 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.2.2
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-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -218,6 +218,8 @@ files:
218
218
  - lib/algolia/config/analytics_config.rb
219
219
  - lib/algolia/config/base_config.rb
220
220
  - lib/algolia/config/insights_config.rb
221
+ - lib/algolia/config/personalization_config.rb
222
+ - lib/algolia/config/recommend_config.rb
221
223
  - lib/algolia/config/recommendation_config.rb
222
224
  - lib/algolia/config/search_config.rb
223
225
  - lib/algolia/defaults.rb
@@ -234,10 +236,13 @@ files:
234
236
  - lib/algolia/iterators/rule_iterator.rb
235
237
  - lib/algolia/iterators/synonym_iterator.rb
236
238
  - lib/algolia/logger_helper.rb
239
+ - lib/algolia/personalization_client.rb
240
+ - lib/algolia/recommend_client.rb
237
241
  - lib/algolia/recommendation_client.rb
238
242
  - lib/algolia/responses/add_api_key_response.rb
239
243
  - lib/algolia/responses/base_response.rb
240
244
  - lib/algolia/responses/delete_api_key_response.rb
245
+ - lib/algolia/responses/dictionary_response.rb
241
246
  - lib/algolia/responses/indexing_response.rb
242
247
  - lib/algolia/responses/multiple_batch_indexing_response.rb
243
248
  - lib/algolia/responses/multiple_response.rb
@@ -273,6 +278,8 @@ files:
273
278
  - test/algolia/integration/base_test.rb
274
279
  - test/algolia/integration/insights_client_test.rb
275
280
  - test/algolia/integration/mocks/mock_requester.rb
281
+ - test/algolia/integration/personalization_client_test.rb
282
+ - test/algolia/integration/recommend_client_test.rb
276
283
  - test/algolia/integration/recommendation_client_test.rb
277
284
  - test/algolia/integration/search_client_test.rb
278
285
  - test/algolia/integration/search_index_test.rb
@@ -304,7 +311,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
304
311
  - !ruby/object:Gem::Version
305
312
  version: '0'
306
313
  requirements: []
307
- rubygems_version: 3.1.4
314
+ rubygems_version: 3.0.6
308
315
  signing_key:
309
316
  specification_version: 4
310
317
  summary: A simple Ruby client for the algolia.com REST API
@@ -314,6 +321,8 @@ test_files:
314
321
  - test/algolia/integration/base_test.rb
315
322
  - test/algolia/integration/insights_client_test.rb
316
323
  - test/algolia/integration/mocks/mock_requester.rb
324
+ - test/algolia/integration/personalization_client_test.rb
325
+ - test/algolia/integration/recommend_client_test.rb
317
326
  - test/algolia/integration/recommendation_client_test.rb
318
327
  - test/algolia/integration/search_client_test.rb
319
328
  - test/algolia/integration/search_index_test.rb