algolia 2.0.0.pre.alpha.4 → 2.0.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +3 -0
  4. data/CHANGELOG.md +12 -0
  5. data/Gemfile +1 -1
  6. data/README.md +18 -10
  7. data/SECURITY.md +3 -0
  8. data/algolia.gemspec +6 -6
  9. data/lib/algolia.rb +1 -1
  10. data/lib/algolia/analytics_client.rb +1 -1
  11. data/lib/algolia/config/analytics_config.rb +2 -2
  12. data/lib/algolia/config/base_config.rb +43 -0
  13. data/lib/algolia/config/insights_config.rb +2 -2
  14. data/lib/algolia/config/recommendation_config.rb +2 -2
  15. data/lib/algolia/config/search_config.rb +2 -2
  16. data/lib/algolia/defaults.rb +2 -2
  17. data/lib/algolia/error.rb +1 -2
  18. data/lib/algolia/helpers.rb +5 -3
  19. data/lib/algolia/insights_client.rb +1 -1
  20. data/lib/algolia/iterators/object_iterator.rb +5 -4
  21. data/lib/algolia/iterators/paginator_iterator.rb +5 -3
  22. data/lib/algolia/recommendation_client.rb +1 -1
  23. data/lib/algolia/search_client.rb +1 -1
  24. data/lib/algolia/search_index.rb +37 -37
  25. data/lib/algolia/transport/request_options.rb +1 -1
  26. data/lib/algolia/transport/transport.rb +2 -5
  27. data/lib/algolia/version.rb +1 -1
  28. data/sig/config/algolia_config.rbs +3 -3
  29. data/sig/config/analytics_config.rbs +1 -1
  30. data/sig/config/insights_config.rbs +1 -1
  31. data/sig/config/recommendation_config.rbs +1 -1
  32. data/sig/config/search_config.rbs +1 -1
  33. data/test/algolia/integration/analytics_client_test.rb +6 -6
  34. data/test/algolia/integration/insights_client_test.rb +11 -11
  35. data/test/algolia/integration/search_client_test.rb +20 -11
  36. data/test/algolia/unit/algolia_config_test.rb +16 -0
  37. data/test/algolia/unit/helpers_test.rb +20 -1
  38. data/test/algolia/unit/retry_strategy_test.rb +3 -3
  39. data/test/test_helper.rb +1 -1
  40. data/upgrade_guide.md +30 -22
  41. metadata +26 -17
  42. data/lib/algolia/config/algolia_config.rb +0 -40
@@ -34,7 +34,7 @@ module Algolia
34
34
  def add_headers(opts = {})
35
35
  unless opts[:headers].nil?
36
36
  opts[:headers].each do |opt, value|
37
- @headers[opt.to_sym] = value
37
+ @headers[opt.to_s] = value
38
38
  end
39
39
  opts.delete(:headers)
40
40
  end
@@ -127,15 +127,12 @@ module Algolia
127
127
 
128
128
  # Generates headers from config headers and optional parameters
129
129
  #
130
- # @option options [String] :headers
130
+ # @param request_options [RequestOptions]
131
131
  #
132
132
  # @return [Hash] merged headers
133
133
  #
134
134
  def generate_headers(request_options = {})
135
- headers = {}
136
- extra_headers = request_options.headers || {}
137
- @config.default_headers.each { |key, val| headers[key.to_s] = val }
138
- extra_headers.each { |key, val| headers[key.to_s] = val }
135
+ headers = @config.headers.merge(request_options.headers)
139
136
  if request_options.compression_type == Defaults::GZIP_ENCODING
140
137
  headers['Accept-Encoding'] = Defaults::GZIP_ENCODING
141
138
  end
@@ -1,3 +1,3 @@
1
1
  module Algolia
2
- VERSION = '2.0.0-alpha.4'.freeze
2
+ VERSION = '2.0.1'.freeze
3
3
  end
@@ -1,11 +1,10 @@
1
1
  module Algolia
2
- # Class AlgoliaConfig
3
- class AlgoliaConfig
2
+ class BaseConfig
4
3
  attr_accessor app_id: String
5
4
 
6
5
  attr_accessor api_key: String
7
6
 
8
- attr_accessor default_headers: Hash[String, String]
7
+ attr_accessor headers: Hash[String, String]
9
8
 
10
9
  attr_accessor batch_size: Integer
11
10
 
@@ -20,5 +19,6 @@ module Algolia
20
19
  attr_accessor symbolize_keys: bool
21
20
 
22
21
  def initialize: (?::Hash[Symbol, String|[String]] opts) -> void
22
+ def set_extra_header: (Symbol|String key, String value) -> void
23
23
  end
24
24
  end
@@ -1,6 +1,6 @@
1
1
  module Algolia
2
2
  module Analytics
3
- class Config < AlgoliaConfig
3
+ class Config < BaseConfig
4
4
  attr_accessor region: String
5
5
 
6
6
  attr_accessor default_hosts: [String]
@@ -1,6 +1,6 @@
1
1
  module Algolia
2
2
  module Insights
3
- class Config < AlgoliaConfig
3
+ class Config < BaseConfig
4
4
  attr_accessor region: String
5
5
 
6
6
  attr_accessor default_hosts: [String]
@@ -1,6 +1,6 @@
1
1
  module Algolia
2
2
  module Recommendation
3
- class Config < AlgoliaConfig
3
+ class Config < BaseConfig
4
4
  attr_accessor region: String
5
5
 
6
6
  attr_accessor default_hosts: [String]
@@ -1,6 +1,6 @@
1
1
  module Algolia
2
2
  module Search
3
- class Config < AlgoliaConfig
3
+ class Config < BaseConfig
4
4
  include CallType
5
5
 
6
6
  attr_accessor default_hosts: Array[untyped]
@@ -11,14 +11,14 @@ class AnalyticsClientTest < BaseTest
11
11
  index1.save_object!({ objectID: 'one' })
12
12
  index2.save_object!({ objectID: 'one' })
13
13
 
14
- ab_test_name = index1.index_name
14
+ ab_test_name = index1.name
15
15
  tomorrow = Time.now + 24*60*60
16
16
 
17
17
  ab_test = {
18
18
  name: ab_test_name,
19
19
  variants: [
20
- { index: index1.index_name, trafficPercentage: 60, description: 'a description' },
21
- { index: index2.index_name, trafficPercentage: 40 }
20
+ { index: index1.name, trafficPercentage: 60, description: 'a description' },
21
+ { index: index2.name, trafficPercentage: 40 }
22
22
  ],
23
23
  endAt: tomorrow.strftime('%Y-%m-%dT%H:%M:%SZ')
24
24
  }
@@ -74,14 +74,14 @@ class AnalyticsClientTest < BaseTest
74
74
 
75
75
  index.save_object!({ objectID: 'one' })
76
76
 
77
- ab_test_name = index.index_name
77
+ ab_test_name = index.name
78
78
  tomorrow = Time.now + 24*60*60
79
79
 
80
80
  ab_test = {
81
81
  name: ab_test_name,
82
82
  variants: [
83
- { index: index.index_name, trafficPercentage: 90 },
84
- { index: index.index_name, trafficPercentage: 10, customSearchParameters: { ignorePlurals: true } }
83
+ { index: index.name, trafficPercentage: 90 },
84
+ { index: index.name, trafficPercentage: 10, customSearchParameters: { ignorePlurals: true } }
85
85
  ],
86
86
  endAt: tomorrow.strftime('%Y-%m-%dT%H:%M:%SZ')
87
87
  }
@@ -17,7 +17,7 @@ class InsightsClientTest < BaseTest
17
17
  client.send_event({
18
18
  eventType: 'click',
19
19
  eventName: 'foo',
20
- index: index.index_name,
20
+ index: index.name,
21
21
  userToken: 'bar',
22
22
  objectIDs: %w(one two),
23
23
  timestamp: (today - 2).strftime('%Q').to_i
@@ -27,14 +27,14 @@ class InsightsClientTest < BaseTest
27
27
  {
28
28
  eventType: 'click',
29
29
  eventName: 'foo',
30
- index: index.index_name,
30
+ index: index.name,
31
31
  userToken: 'bar',
32
32
  objectIDs: %w(one two),
33
33
  timestamp: (today - 2).strftime('%Q').to_i
34
34
  }, {
35
35
  eventType: 'click',
36
36
  eventName: 'foo',
37
- index: index.index_name,
37
+ index: index.name,
38
38
  userToken: 'bar',
39
39
  objectIDs: %w(one two),
40
40
  timestamp: (today - 2).strftime('%Q').to_i
@@ -42,37 +42,37 @@ class InsightsClientTest < BaseTest
42
42
  ])
43
43
 
44
44
  user_client = client.user('bar')
45
- response = user_client.clicked_object_ids('foo', index.index_name, %w(one two))
45
+ response = user_client.clicked_object_ids('foo', index.name, %w(one two))
46
46
  assert_equal 200, response[:status]
47
47
  assert_equal 'OK', response[:message]
48
48
 
49
49
  query_id = index.search('', { clickAnalytics: true })[:queryID]
50
50
 
51
- response = user_client.clicked_object_ids_after_search('foo', index.index_name, %w(one two), [1, 2], query_id)
51
+ response = user_client.clicked_object_ids_after_search('foo', index.name, %w(one two), [1, 2], query_id)
52
52
  assert_equal 200, response[:status]
53
53
  assert_equal 'OK', response[:message]
54
54
 
55
- response = user_client.clicked_filters('foo', index.index_name, %w(filter:foo filter:bar))
55
+ response = user_client.clicked_filters('foo', index.name, %w(filter:foo filter:bar))
56
56
  assert_equal 200, response[:status]
57
57
  assert_equal 'OK', response[:message]
58
58
 
59
- response = user_client.converted_object_ids('foo', index.index_name, %w(one two))
59
+ response = user_client.converted_object_ids('foo', index.name, %w(one two))
60
60
  assert_equal 200, response[:status]
61
61
  assert_equal 'OK', response[:message]
62
62
 
63
- response = user_client.converted_object_ids_after_search('foo', index.index_name, %w(one two), query_id)
63
+ response = user_client.converted_object_ids_after_search('foo', index.name, %w(one two), query_id)
64
64
  assert_equal 200, response[:status]
65
65
  assert_equal 'OK', response[:message]
66
66
 
67
- response = user_client.converted_filters('foo', index.index_name, %w(filter:foo filter:bar))
67
+ response = user_client.converted_filters('foo', index.name, %w(filter:foo filter:bar))
68
68
  assert_equal 200, response[:status]
69
69
  assert_equal 'OK', response[:message]
70
70
 
71
- response = user_client.viewed_object_ids('foo', index.index_name, %w(one two))
71
+ response = user_client.viewed_object_ids('foo', index.name, %w(one two))
72
72
  assert_equal 200, response[:status]
73
73
  assert_equal 'OK', response[:message]
74
74
 
75
- response = user_client.viewed_filters('foo', index.index_name, %w(filter:foo filter:bar))
75
+ response = user_client.viewed_filters('foo', index.name, %w(filter:foo filter:bar))
76
76
  assert_equal 200, response[:status]
77
77
  assert_equal 'OK', response[:message]
78
78
  end
@@ -80,10 +80,10 @@ class SearchClientTest < BaseTest
80
80
  copy_rules_index = @@search_client.init_index(get_test_index_name('copy_index_rules'))
81
81
  copy_synonyms_index = @@search_client.init_index(get_test_index_name('copy_index_synonyms'))
82
82
  copy_full_copy_index = @@search_client.init_index(get_test_index_name('copy_index_full_copy'))
83
- @@search_client.copy_settings!(@index_name, copy_settings_index.index_name)
84
- @@search_client.copy_rules!(@index_name, copy_rules_index.index_name)
85
- @@search_client.copy_synonyms!(@index_name, copy_synonyms_index.index_name)
86
- @@search_client.copy_index!(@index_name, copy_full_copy_index.index_name)
83
+ @@search_client.copy_settings!(@index_name, copy_settings_index.name)
84
+ @@search_client.copy_rules!(@index_name, copy_rules_index.name)
85
+ @@search_client.copy_synonyms!(@index_name, copy_synonyms_index.name)
86
+ @@search_client.copy_index!(@index_name, copy_full_copy_index.name)
87
87
 
88
88
  assert_equal @index.get_settings, copy_settings_index.get_settings
89
89
  assert_equal @index.get_rule(rule[:objectID]), copy_rules_index.get_rule(rule[:objectID])
@@ -93,7 +93,7 @@ class SearchClientTest < BaseTest
93
93
  assert_equal @index.get_synonym(synonym[:objectID]), copy_full_copy_index.get_synonym(synonym[:objectID])
94
94
 
95
95
  moved_index = @@search_client.init_index(get_test_index_name('move_index'))
96
- @@search_client.move_index!(@index_name, moved_index.index_name)
96
+ @@search_client.move_index!(@index_name, moved_index.name)
97
97
 
98
98
  moved_index.get_synonym('google_placeholder')
99
99
  moved_index.get_rule('company_auto_faceting')
@@ -233,7 +233,16 @@ class SearchClientTest < BaseTest
233
233
 
234
234
  assert_equal 'Key does not exist', exception.message
235
235
 
236
- @@search_client.restore_api_key!(@api_key[:value])
236
+ loop do
237
+ begin
238
+ @@search_client.restore_api_key!(@api_key[:value])
239
+ break
240
+ rescue Algolia::AlgoliaHttpError => e
241
+ if e.code != 404
242
+ raise StandardError
243
+ end
244
+ end
245
+ end
237
246
 
238
247
  restored_key = @@search_client.get_api_key(@api_key[:value])
239
248
 
@@ -261,8 +270,8 @@ class SearchClientTest < BaseTest
261
270
  end
262
271
 
263
272
  def test_multiple_operations
264
- index_name1 = @index1.index_name
265
- index_name2 = @index2.index_name
273
+ index_name1 = @index1.name
274
+ index_name2 = @index2.name
266
275
 
267
276
  response = @@search_client.multiple_batch!([
268
277
  { indexName: index_name1, action: 'addObject', body: { firstname: 'Jimmie' } },
@@ -317,12 +326,12 @@ class SearchClientTest < BaseTest
317
326
  now = Time.now.to_i
318
327
  secured_api_key = Algolia::Search::Client.generate_secured_api_key(SEARCH_KEY_1, {
319
328
  validUntil: now + (10 * 60),
320
- restrictIndices: @index1.index_name
329
+ restrictIndices: @index1.name
321
330
  })
322
331
 
323
332
  secured_client = Algolia::Search::Client.create(APPLICATION_ID_1, secured_api_key)
324
- secured_index1 = secured_client.init_index(@index1.index_name)
325
- secured_index2 = secured_client.init_index(@index2.index_name)
333
+ secured_index1 = secured_client.init_index(@index1.name)
334
+ secured_index2 = secured_client.init_index(@index2.name)
326
335
 
327
336
  secured_index1.search('')
328
337
  exception = assert_raises Algolia::AlgoliaHttpError do
@@ -0,0 +1,16 @@
1
+ require 'algolia'
2
+ require 'test_helper'
3
+
4
+ class AlgoliaConfigTest
5
+ describe 'set an extra header' do
6
+ def before_all
7
+ @config = Algolia::BaseConfig.new(application_id: 'app_id', api_key: 'api_key')
8
+ end
9
+
10
+ def test_set_extra_header
11
+ @config.set_extra_header('foo', 'bar')
12
+ assert @config.headers['foo']
13
+ assert_equal @config.headers['foo'], 'bar'
14
+ end
15
+ end
16
+ end
@@ -18,7 +18,26 @@ class HelpersTest
18
18
  replicas: %w(index1 index2)
19
19
  }
20
20
 
21
- deserialized_settings = deserialize_settings(old_settings)
21
+ deserialized_settings = deserialize_settings(old_settings, true)
22
+ assert_equal new_settings, deserialized_settings
23
+ end
24
+
25
+ def test_deserialize_settings_with_string
26
+ old_settings = {
27
+ 'attributesToIndex' => %w(attr1 attr2),
28
+ 'numericAttributesToIndex' => %w(attr1 attr2),
29
+ 'slaves' => %w(index1 index2),
30
+ 'minWordSizefor1Typo' => 1
31
+ }
32
+
33
+ new_settings = {
34
+ 'searchableAttributes' => %w(attr1 attr2),
35
+ 'numericAttributesForFiltering' => %w(attr1 attr2),
36
+ 'replicas' => %w(index1 index2),
37
+ 'minWordSizefor1Typo' => 1
38
+ }
39
+
40
+ deserialized_settings = deserialize_settings(old_settings, false)
22
41
  assert_equal new_settings, deserialized_settings
23
42
  end
24
43
  end
@@ -13,7 +13,7 @@ class RetryStrategyTest
13
13
  stateful_hosts << "#{@app_id}-4.algolianet.com"
14
14
  stateful_hosts << "#{@app_id}-5.algolianet.com"
15
15
  stateful_hosts << "#{@app_id}-6.algolianet.com"
16
- @config = Algolia::Search::Config.new(app_id: @app_id, api_key: @api_key, custom_hosts: stateful_hosts)
16
+ @config = Algolia::Search::Config.new(application_id: @app_id, api_key: @api_key, custom_hosts: stateful_hosts)
17
17
  end
18
18
 
19
19
  def test_resets_expired_hosts_according_to_read_type
@@ -74,7 +74,7 @@ class RetryStrategyTest
74
74
  describe 'All hosts are unreachable' do
75
75
  def test_failure_when_all_hosts_are_down
76
76
  stateful_hosts = ['0.0.0.0']
77
- @config = Algolia::Search::Config.new(app_id: 'foo', api_key: 'bar', custom_hosts: stateful_hosts)
77
+ @config = Algolia::Search::Config.new(application_id: 'foo', api_key: 'bar', custom_hosts: stateful_hosts)
78
78
  client = Algolia::Search::Client.create_with_config(@config)
79
79
  index = client.init_index(get_test_index_name('failure'))
80
80
 
@@ -91,7 +91,7 @@ class RetryStrategyTest
91
91
  super
92
92
  @app_id = 'app_id'
93
93
  @api_key = 'api_key'
94
- @config = Algolia::Search::Config.new(app_id: @app_id, api_key: @api_key)
94
+ @config = Algolia::Search::Config.new(application_id: @app_id, api_key: @api_key)
95
95
  @retry_strategy = Algolia::Transport::RetryStrategy.new(@config)
96
96
  @hosts = @retry_strategy.get_tryable_hosts(READ|WRITE)
97
97
  end
@@ -24,7 +24,7 @@ class Minitest::Test
24
24
 
25
25
  include Minitest::Hooks
26
26
  include Helpers
27
- @@search_config = Algolia::Search::Config.new(app_id: APPLICATION_ID_1, api_key: ADMIN_KEY_1, user_agent: USER_AGENT)
27
+ @@search_config = Algolia::Search::Config.new(application_id: APPLICATION_ID_1, api_key: ADMIN_KEY_1, user_agent: USER_AGENT)
28
28
  @@search_client = Algolia::Search::Client.new(@@search_config)
29
29
  end
30
30
 
@@ -5,7 +5,7 @@ First, you'll have to include the new version in your Gemfile. To do so, change
5
5
 
6
6
  ```diff
7
7
  - gem 'algoliasearch'
8
- + gem 'algolia', git: 'https://github.com/algolia/algoliasearch-client-ruby.git', tag: 'v2.0.0-alpha.1'
8
+ + gem 'algolia', git: 'https://github.com/algolia/algoliasearch-client-ruby.git', tag: 'v2.0.0-beta.1'
9
9
  ```
10
10
 
11
11
  Then, you'll need to change your current `require` statements:
@@ -38,11 +38,17 @@ index = client.init_index('index_name')
38
38
  client = Algolia::Search::Client.create('APP_ID', 'API_KEY')
39
39
  index = client.init_index('index_name')
40
40
  # or
41
- search_config = Algolia::Search::Config.new(app_id: app_id, api_key: api_key)
41
+ search_config = Algolia::Search::Config.new(application_id: app_id, api_key: api_key)
42
42
  client = Algolia::Search::Client.create_with_config(search_config)
43
43
  index = client.init_index('index_name')
44
44
  ```
45
45
 
46
+ By default the keys of the response hashes are symbols. If you wish to change that for strings, use the following configuration
47
+ ```ruby
48
+ search_config = Algolia::Search::Config.new(application_id: app_id, api_key: api_key, symbolize_keys: false)
49
+ client = Algolia::Search::Client.create_with_config(search_config)
50
+ ```
51
+
46
52
  ## Search parameters and request options
47
53
  The search parameters and request options are still optional, but they are combined into a single hash instead of two.
48
54
  For example:
@@ -55,12 +61,8 @@ index.search('query', search_params, request_opts)
55
61
 
56
62
  # After
57
63
  opts = {
58
- :headers => {
59
- 'X-Algolia-UserToken': 'user123'
60
- },
61
- :params => {
62
- hitsPerPage: 50
63
- }
64
+ headers: { 'X-Algolia-UserToken': 'user123' },
65
+ hitsPerPage: 50
64
66
  }
65
67
  index.search('query', opts)
66
68
  ```
@@ -69,6 +71,20 @@ index.search('query', opts)
69
71
 
70
72
  ### `Client`
71
73
 
74
+ #### `set_extra_header`
75
+ The `set_extra_header` method has been moved from the Client to the `Algolia::BaseConfig` class. You have to define your extra headers on Client instantiation.
76
+ ```ruby
77
+ # Before
78
+ client.set_extra_header('admin', 'admin-key')
79
+
80
+ # After
81
+ # `Algolia::Search::Config` inherits from `Algolia::BaseConfig`
82
+ config = Algolia::Search::Config.new(app_id: 'APP_ID', api_key: 'API_KEY')
83
+ config.set_extra_header('admin', 'admin-key')
84
+
85
+ client = Algolia::Search::Client.create_with_config(config)
86
+ ```
87
+
72
88
  #### `multiple_queries`
73
89
  The `strategy` parameter is no longer a string, but a key in the `requestOptions`.
74
90
  ```ruby
@@ -213,7 +229,7 @@ client.search_user_ids('query', {clusterName: 'my-cluster', hitPerPage: 12, page
213
229
  #### `pending_mappings`
214
230
  New method to check the status of your clusters' migration or user creation.
215
231
  ```ruby
216
- client.pending_mapping?({ retrieveMappings: true })
232
+ client.pending_mappings?({ retrieveMappings: true })
217
233
  ```
218
234
 
219
235
  #### `get_logs`
@@ -244,12 +260,8 @@ index.search('query', search_params, request_opts)
244
260
 
245
261
  # After
246
262
  opts = {
247
- :headers => {
248
- 'X-Algolia-UserToken': 'user123'
249
- },
250
- :params => {
251
- hitsPerPage: 50
252
- }
263
+ headers: { 'X-Algolia-UserToken': 'user123' },
264
+ hitsPerPage: 50
253
265
  }
254
266
  index.search('query', opts)
255
267
  ```
@@ -265,12 +277,8 @@ index.search_for_facet_values('category', 'phone', search_params, request_opts)
265
277
 
266
278
  # After
267
279
  opts = {
268
- :headers => {
269
- 'X-Algolia-UserToken': 'user123'
270
- },
271
- :params => {
272
- hitsPerPage: 50
273
- }
280
+ headers: { 'X-Algolia-UserToken': 'user123' },
281
+ hitsPerPage: 50
274
282
  }
275
283
  index.search_for_facet_values('category', 'phone', opts)
276
284
  ```
@@ -590,6 +598,6 @@ client = Algolia::Client.new({
590
598
  })
591
599
 
592
600
  # After
593
- search_config = Algolia::Search::Config.new(app_id: 'app_id', api_key: 'api_key', read_timeout: 10, connect_timeout: 2)
601
+ search_config = Algolia::Search::Config.new(application_id: 'app_id', api_key: 'api_key', read_timeout: 10, connect_timeout: 2)
594
602
  client = Algolia::Search::Client.create_with_config(search_config)
595
603
  ```