algolia 2.0.0 → 2.1.1

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: 555e432d41a84d3031f58dc7c74acf5297df48fe693fadf977c6b15547a82d6b
4
- data.tar.gz: a3fbbc9ba6552b0b432a20e34cd5cf7a311f339c2df7f7a3c549ced84f409ba0
3
+ metadata.gz: dc743bd03ca6ebc94d2ae61eec22670ccbaa3531d2a9b66c44858280c644a938
4
+ data.tar.gz: 9e5fb85f9d474d266de360c25b7ef3efafa0fe0b78765aa1cae32b402a0865ac
5
5
  SHA512:
6
- metadata.gz: 757d57c2723f3f036bfb7faa38615fd751311e99b0a3f5e1b3c13087c53a9010af88c99a5412e31bb3e6d3cdb9201478d7100c71080b3fe948004170a870f875
7
- data.tar.gz: ede51228b6bc2498b65434102f8b25b17d7db74ae74cd2b50a1ec7184f42692e4b24d94de8c621ec91a8192c924e71ac1067bfdde038a03936407f12147b6175
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/.dockerignore ADDED
@@ -0,0 +1,38 @@
1
+ # rspec failure tracking
2
+ .rspec_status
3
+
4
+ ## MAC OS
5
+ .DS_Store
6
+ .idea/
7
+
8
+ ## TEXTMATE
9
+ *.tmproj
10
+ tmtags
11
+
12
+ ## EMACS
13
+ *~
14
+ \#*
15
+ .\#*
16
+
17
+ ## VIM
18
+ *.swp
19
+
20
+ ## PROJECT::GENERAL
21
+ coverage
22
+ rdoc
23
+ pkg
24
+ .rvmrc
25
+ /.bundle/
26
+ /.yardoc
27
+ /_yardoc/
28
+ /coverage/
29
+ /doc/
30
+ /pkg/
31
+ /spec/reports/
32
+ /tmp/
33
+
34
+ ## PROJECT::SPECIFIC
35
+ spec/integration_spec_conf.rb
36
+ data.sqlite3
37
+
38
+ debug.log
data/.gitignore CHANGED
@@ -37,3 +37,4 @@ spec/integration_spec_conf.rb
37
37
  data.sqlite3
38
38
 
39
39
  debug.log
40
+ .ruby-version
data/CHANGELOG.md CHANGED
@@ -1,6 +1,40 @@
1
1
  # ChangeLog
2
2
 
3
- ## Unreleased
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
17
+
18
+ ## [2.0.4](https://github.com/algolia/algoliasearch-client-ruby/compare/2.0.3...2.0.4) (2021-01-05)
19
+
20
+ ### Fix
21
+ - `app_api_key`: send opts with waitable method
22
+
23
+ ## [2.0.3](https://github.com/algolia/algoliasearch-client-ruby/compare/2.0.2...2.0.3) (2020-11-24)
24
+
25
+ ### Chore
26
+ - Containerize the repo
27
+
28
+ ## [2.0.2](https://github.com/algolia/algoliasearch-client-ruby/compare/2.0.1...2.0.2) (2020-11-09)
29
+
30
+ ### Fix
31
+ - Don't mutate index name on stripping
32
+
33
+ ## [2.0.1](https://github.com/algolia/algoliasearch-client-ruby/compare/2.0.0...2.0.1) (2020-11-02)
34
+
35
+ ### Fix
36
+ - Simplify merge of headers in `Transport` class
37
+ - `deserialize_settings` function to take into account `symbolize_keys` parameter
4
38
 
5
39
  ## [2.0.0](https://github.com/algolia/algoliasearch-client-ruby/releases/tag/2.0.0) (2020-10-27)
6
40
 
data/CONTRIBUTING.MD ADDED
@@ -0,0 +1,184 @@
1
+ <p align="center">
2
+ <a href="https://www.algolia.com">
3
+ <img alt="Algolia for Ruby" src="https://raw.githubusercontent.com/algolia/algoliasearch-client-common/master/banners/ruby.png" >
4
+ </a>
5
+ </p>
6
+
7
+ Hello and welcome to the contributing guide for algolia gem. Thanks for considering participating in our project 🙇
8
+
9
+ If this guide does not contain what you are looking for and thus prevents you from contributing, don't hesitate to leave a message on the [community forum](https://discourse.algolia.com/) or to [open an issue](https://github.com/algolia/algoliasearch-client-ruby/issues).
10
+
11
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN TocDown TO UPDATE -->
12
+ <!-- TocDown Begin -->
13
+ * [Reporting an issue](#reporting-an-issue)
14
+ * [The code contribution process](#the-code-contribution-process)
15
+ * [Commit conventions](#commit-conventions)
16
+ * [Branch organization](#branch-organization)
17
+ * [Requirements](#requirements)
18
+ * [Code structure](#code-structure)
19
+ * [The source algolia folder](#the-source-algolia-folder)
20
+ * [Tests](#tests)
21
+ * [Linting](#linting)
22
+ <!-- TocDown End -->
23
+
24
+ ## Reporting an issue
25
+
26
+ Opening an issue is very effective way to contribute because other users might also be impacted. We'll make sure to fix it quickly if it's technically feasible and doesn't have important side effects for other users.
27
+
28
+ Before reporting an issue, first check that there is not an already open issue for the same topic using the [issues page](https://github.com/algolia/algoliasearch-client-ruby/issues). Don't hesitate to thumb up an issue that corresponds to the problem you have.
29
+
30
+ It would be very helpful if you're able to add a test case that reproduces the issue. This could help us solve the issue faster.
31
+
32
+ ## The code contribution process
33
+
34
+ The algolia gem is developed in Ruby ≥ 2.2.
35
+
36
+ For any code contribution, you need to:
37
+
38
+ - Fork and clone the project
39
+ - Create a new branch for what you want to solve (fix/_issue-number_, feat/_name-of-the-feature_)
40
+ - Make your changes
41
+ - Open a pull request
42
+
43
+ Depending on what you're working on, you might consider different [base branches](#branch-organization).
44
+
45
+ Then:
46
+
47
+ - Peer review of the pull request (by at least one of the core contributors)
48
+ - Automatic checks ([tests](#tests), [commits](#commit-conventions), [linters](#linting))
49
+ - When everything is green, one of the core contributors will merge your contribution 🚀
50
+
51
+ ## Commit conventions
52
+
53
+ This project follows the [conventional changelog](https://conventionalcommits.org/) approach. This means that all commit messages should be formatted using the following scheme:
54
+
55
+ ```
56
+ type(scope): description
57
+ ```
58
+
59
+ In most cases, we use the following types:
60
+
61
+ - `fix`: for any resolution of an issue (identified or not)
62
+ - `feat`: for any new feature
63
+ - `refactor`: for any code change that neither adds a feature nor fixes an issue
64
+ - `docs`: for any documentation change or addition
65
+ - `chore`: for anything that is not related to the library itself (doc, tooling)
66
+
67
+ Even though the scope is optional, we try to fill it in as it helps us better understand the impact of a change. We either use the name of the widget/connector/component impacted or we use impact topic (e.g. `docs`, `tooling`, `deps`, `ci`).
68
+
69
+ Finally, if your work is based on an issue on GitHub, please fill in the dedicated line in the PR template (read "[Closing issues using keywords](https://help.github.com/en/articles/closing-issues-using-keywords)").
70
+
71
+ Some examples of valid commit messages (used as first lines):
72
+
73
+ > - feat(account-client): add method XXX
74
+ > - chore(deps): update dependency XXX to v3.0.7
75
+ > - fix(search_user_ids): rename parameter clusterName
76
+ > - chore: reword contributions guides
77
+
78
+ ## Branch organization
79
+
80
+ The project is based on the classic GitHub flow:
81
+
82
+ - `master` for the current version being worked on – Pull requests for bugs and feature related to the current major version should be created against this branch
83
+ - `vX` for each major version (`X` being a number) – Pull requests for critical bug fixes should be created against this branch
84
+
85
+ Most of the time, your pull requests should target the `master` branch.
86
+
87
+ _Note that no new features will be developed or backported for the `vX` branches._
88
+
89
+ ## Requirements
90
+
91
+ To run this project, you will need:
92
+
93
+ - Ruby ≥ 2.2
94
+ - [Bundler](https://bundler.io/)
95
+
96
+ ## Use the Dockerfile
97
+
98
+ If you want to contribute to this project without installing all its dependencies, you can use our Docker image.
99
+ Please check our [dedicated guide](DOCKER_README.MD) to learn more.
100
+
101
+ ## Code structure
102
+
103
+ Here are the main files and folders of the project
104
+
105
+ ```
106
+ ▸ lib/algolia/ << standalone clients and helpers classes
107
+ ▸ lib/test/ << gathers the unit and integration tests
108
+ .rubocop.yml << contains the rule used for the linter
109
+ algolia.gemspec << gemspec file
110
+ CHANGELOG.md << changelog file
111
+ CONTRIBUTING.md << this file
112
+ Gemfile << dependencies needed to run the project locally
113
+ Rakefile << defines the different tasks to lint/test the project
114
+ README.md << the introduction of the project
115
+ ```
116
+
117
+ ### The lib/algolia folder
118
+
119
+ ```
120
+ ▸ lib/algolia/
121
+ ▸ config/ << the configurations associated with each clients
122
+ ▸ enums/ << enumerables used accross the lib
123
+ ▸ http/ << the http layer logic
124
+ ▸ iterators/ << the iterators used for the browsing methods
125
+ ▸ responses/ << the waitable responses
126
+ ▸ transport/ << the transport layer logic
127
+ ```
128
+
129
+ ## Tests
130
+
131
+ Our unit and integration tests are written with [Minitest](https://github.com/seattlerb/minitest), in the `test` syntax.
132
+
133
+ To run all the tests at once:
134
+
135
+ ```sh
136
+ bundle exec rake test:all
137
+ ```
138
+
139
+ To run only the unit tests:
140
+
141
+ ```sh
142
+ bundle exec rake test:unit
143
+ ```
144
+
145
+ To run only the integration tests:
146
+
147
+ ```sh
148
+ bundle exec rake test:integration
149
+ ```
150
+
151
+ We ask that for each fix or feature submitted, you add at least one test demonstrating its behaviour. As you will need to use your own Algolia credentials to run them, we advise you to keep them short and use a small dataset, as well as using a mock requester anytime it's possible. If you encounter huge data overload because of testing, please reach out to [our support team](support@algolia.com).
152
+
153
+ ## Linting
154
+
155
+ Linters help us maintain a consistent code base.
156
+
157
+ If your editor support them, then you will see the errors directly there. You can also run them using your command line:
158
+
159
+ ```sh
160
+ rake rubocop
161
+ ```
162
+
163
+ However, we recommend that you use in your workflow pre-commit hooks, to avoid submitting code that might not pass the linting task setup in the CI. To use them,
164
+ first download the gem `git-precommit`
165
+
166
+ ```sh
167
+ gem install git-precommit
168
+ ```
169
+
170
+ Then copy-paste the following content in a file called `pre-commit` in `.git/hooks/`
171
+
172
+ ```sh
173
+ #!/usr/bin/env sh
174
+
175
+ function unstaged_changes {
176
+ ! git diff --quiet
177
+ }
178
+
179
+ if unstaged_changes; then
180
+ git stash save --keep-index "Performing partial commit against `git rev-parse HEAD`"
181
+ fi
182
+
183
+ exec time bundle exec rake precommit
184
+ ```
data/DOCKER_README.MD ADDED
@@ -0,0 +1,89 @@
1
+ In this page you will find our recommended way of installing Docker on your machine.
2
+ This guide is made for OSX users.
3
+
4
+ ## Install docker
5
+
6
+ First install Docker using [Homebrew](https://brew.sh/)
7
+ ```
8
+ $ brew install docker
9
+ ```
10
+
11
+ You can then install [Docker Desktop](https://docs.docker.com/get-docker/) if you wish, or use `docker-machine`. As we prefer the second option, we will only document this one.
12
+
13
+ ## Setup your docker
14
+
15
+ Install `docker-machine`
16
+ ```
17
+ $ brew install docker-machine
18
+ ```
19
+
20
+ Then install [VirtualBox](https://www.virtualbox.org/) with [Homebrew Cask](https://github.com/Homebrew/homebrew-cask) to get a driver for your Docker machine
21
+ ```
22
+ $ brew cask install virtualbox
23
+ ```
24
+
25
+ You may need to enter your password and authorize the application in your `System Settings` > `Security & Privacy`.
26
+
27
+ Create now a new machine, set it up as default and connect your shell to it (here we use zsh. The commands should anyway be displayed in each steps' output)
28
+
29
+ ```
30
+ $ docker-machine create --driver virtualbox default
31
+ $ docker-machine env default
32
+ $ eval "$(docker-machine env default)"
33
+ ```
34
+
35
+ Now you're all setup to use our provided Docker image!
36
+
37
+ ## Build the image
38
+
39
+ ```bash
40
+ docker build -t algolia-ruby .
41
+ ```
42
+
43
+ ## Run the image
44
+
45
+ You need to provide few environment variables at runtime to be able to run the [Common Test Suite](https://github.com/algolia/algoliasearch-client-specs/tree/master/common-test-suite).
46
+ You can set them up directly in the command:
47
+
48
+ ```bash
49
+ docker run -it --rm --env ALGOLIA_APP_ID=XXXXXX [...] -v $PWD:/app -w /app algolia-ruby bash
50
+ ```
51
+
52
+ However, we advise you to export them in your `.bashrc` or `.zshrc`. That way, you can use [Docker's shorten syntax](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file) to set your variables.
53
+
54
+ ```bash
55
+ ### For external contributors, only the following env variables should be enough
56
+ docker run -it --rm --env ALGOLIA_APPLICATION_ID_1 \
57
+ --env ALGOLIA_ADMIN_KEY_1 \
58
+ --env ALGOLIA_SEARCH_KEY_1 \
59
+ -v $PWD:/app -w /app algolia-ruby bash
60
+
61
+ ### This is needed only to run the full test suite
62
+ docker run -it --rm --env ALGOLIA_APPLICATION_ID_1 \
63
+ --env ALGOLIA_ADMIN_KEY_1 \
64
+ --env ALGOLIA_SEARCH_KEY_1 \
65
+ --env ALGOLIA_APPLICATION_ID_2 \
66
+ --env ALGOLIA_ADMIN_KEY_2 \
67
+ --env ALGOLIA_APPLICATION_ID_MCM \
68
+ --env ALGOLIA_ADMIN_KEY_MCM \
69
+ -v $PWD:/app -w /app algolia-ruby bash
70
+ ```
71
+
72
+ Once your container is running, any changes you make in your IDE are directly reflected in the container.
73
+
74
+ To launch the tests, you can use one of the following commands
75
+ ```shell script
76
+ # run only the unit tests
77
+ bundle exec rake test:unit
78
+
79
+ # run only the integration tests
80
+ bundle exec rake test:integration
81
+
82
+ # run the whole test suite
83
+ bundle exec rake test:all
84
+
85
+ # run a single test
86
+ bundle exec rake test TEST=/full/path/to/test.rb TESTOPTS="--name=test_name"
87
+ ```
88
+
89
+ Feel free to contact us if you have any questions.
data/Dockerfile ADDED
@@ -0,0 +1,7 @@
1
+ FROM ruby:2.6.3
2
+
3
+ RUN gem install bundler
4
+
5
+ WORKDIR /app
6
+ COPY . /app/
7
+ RUN bundle install
data/README.md CHANGED
@@ -6,8 +6,8 @@
6
6
  <h4 align="center">The perfect starting point to integrate <a href="https://algolia.com" target="_blank">Algolia</a> within your Ruby project</h4>
7
7
 
8
8
  <p align="center">
9
- <a href="https://circleci.com/gh/algolia/algoliasearch-client-ruby"><img src="https://circleci.com/gh/algolia/algoliasearch-client-ruby/tree/release%2Fv2.svg?style=shield" alt="CircleCI" /></a>
10
- <a href="https://rubygems.org/gems/algolia"><img src="https://badge.fury.io/rb/algoliasearch.svg" alt="Gem Version"></a>
9
+ <a href="https://circleci.com/gh/algolia/algoliasearch-client-ruby"><img src="https://circleci.com/gh/algolia/algoliasearch-client-ruby.svg?style=shield" alt="CircleCI" /></a>
10
+ <a href="https://rubygems.org/gems/algolia"><img src="https://badge.fury.io/rb/algolia.svg" alt="Gem Version"></a>
11
11
  <a href="https://rubygems.org/gems/algolia"><img src="https://img.shields.io/badge/licence-MIT-blue.svg" alt="License"></a>
12
12
  </p>
13
13
  </p>
data/algolia.gemspec CHANGED
@@ -35,7 +35,7 @@ Gem::Specification.new do |spec|
35
35
  spec.add_development_dependency 'rake'
36
36
  spec.add_development_dependency 'rubocop', '<= 0.82.0'
37
37
 
38
- spec.add_dependency 'faraday', '~> 0.15'
38
+ spec.add_dependency 'faraday', ['>= 0.15', '< 2.0']
39
39
  spec.add_dependency 'multi_json', '~> 1.0'
40
40
  spec.add_dependency 'net-http-persistent'
41
41
 
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'
@@ -53,7 +53,7 @@ module Helpers
53
53
  # Support to convert old settings to their new names
54
54
  #
55
55
  def deserialize_settings(data, symbolize_keys)
56
- settings = symbolize_hash(data)
56
+ settings = data
57
57
  keys = {
58
58
  attributesToIndex: 'searchableAttributes',
59
59
  numericAttributesToIndex: 'numericAttributesForFiltering',
@@ -61,6 +61,7 @@ module Helpers
61
61
  }
62
62
 
63
63
  keys.each do |deprecated_key, current_key|
64
+ deprecated_key = symbolize_keys ? deprecated_key : deprecated_key.to_s
64
65
  if settings.has_key?(deprecated_key)
65
66
  key = symbolize_keys ? current_key.to_sym : current_key.to_s
66
67
  settings[key] = settings.delete(deprecated_key)
@@ -81,4 +82,53 @@ module Helpers
81
82
  end
82
83
  res
83
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
84
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
@@ -90,11 +90,11 @@ module Algolia
90
90
  # @return [Index] new Index instance
91
91
  #
92
92
  def init_index(index_name)
93
- index_name.strip!
94
- if index_name.empty?
93
+ stripped_index_name = index_name.strip
94
+ if stripped_index_name.empty?
95
95
  raise AlgoliaError, 'Please provide a valid index name'
96
96
  end
97
- Index.new(index_name, @transporter, @config)
97
+ Index.new(stripped_index_name, @transporter, @config)
98
98
  end
99
99
 
100
100
  # List all indexes of the client
@@ -300,7 +300,7 @@ module Algolia
300
300
  # @return [AddApiKeyResponse]
301
301
  #
302
302
  def add_api_key!(acl, opts = {})
303
- response = add_api_key(acl)
303
+ response = add_api_key(acl, opts)
304
304
 
305
305
  response.wait(opts)
306
306
  end
@@ -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
@@ -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.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'.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
@@ -215,6 +216,7 @@ class SearchClientTest < BaseTest
215
216
 
216
217
  def test_api_keys
217
218
  assert_equal ['search'], @api_key[:acl]
219
+ assert_equal 'A description', @api_key[:description]
218
220
 
219
221
  api_keys = @@search_client.list_api_keys[:keys].map do |key|
220
222
  key[:value]
@@ -222,7 +224,9 @@ class SearchClientTest < BaseTest
222
224
  assert_includes api_keys, @api_key[:value]
223
225
 
224
226
  @@search_client.update_api_key!(@api_key[:value], { maxHitsPerQuery: 42 })
225
- 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
226
230
  assert_equal 42, updated_api_key[:maxHitsPerQuery]
227
231
 
228
232
  @@search_client.delete_api_key!(@api_key[:value])
@@ -233,18 +237,13 @@ class SearchClientTest < BaseTest
233
237
 
234
238
  assert_equal 'Key does not exist', exception.message
235
239
 
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
240
+ retry_test do
241
+ @@search_client.restore_api_key!(@api_key[:value])
245
242
  end
246
243
 
247
- 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
248
247
 
249
248
  refute_nil restored_key
250
249
  end
@@ -333,7 +332,12 @@ class SearchClientTest < BaseTest
333
332
  secured_index1 = secured_client.init_index(@index1.name)
334
333
  secured_index2 = secured_client.init_index(@index2.name)
335
334
 
336
- secured_index1.search('')
335
+ res = retry_test do
336
+ secured_index1.search('')
337
+ end
338
+
339
+ assert_equal 1, res[:hits].length
340
+
337
341
  exception = assert_raises Algolia::AlgoliaHttpError do
338
342
  secured_index2.search('')
339
343
  end
@@ -366,5 +370,96 @@ class SearchClientTest < BaseTest
366
370
  assert_equal 'The SecuredAPIKey doesn\'t have a validUntil parameter.', exception.message
367
371
  end
368
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
369
464
  end
370
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
 
@@ -26,13 +26,15 @@ class HelpersTest
26
26
  old_settings = {
27
27
  'attributesToIndex' => %w(attr1 attr2),
28
28
  'numericAttributesToIndex' => %w(attr1 attr2),
29
- 'slaves' => %w(index1 index2)
29
+ 'slaves' => %w(index1 index2),
30
+ 'minWordSizefor1Typo' => 1
30
31
  }
31
32
 
32
33
  new_settings = {
33
34
  'searchableAttributes' => %w(attr1 attr2),
34
35
  'numericAttributesForFiltering' => %w(attr1 attr2),
35
- 'replicas' => %w(index1 index2)
36
+ 'replicas' => %w(index1 index2),
37
+ 'minWordSizefor1Typo' => 1
36
38
  }
37
39
 
38
40
  deserialized_settings = deserialize_settings(old_settings, false)
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.0
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: 2020-10-27 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
@@ -56,16 +56,22 @@ dependencies:
56
56
  name: faraday
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0.15'
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '2.0'
62
65
  type: :runtime
63
66
  prerelease: false
64
67
  version_requirements: !ruby/object:Gem::Requirement
65
68
  requirements:
66
- - - "~>"
69
+ - - ">="
67
70
  - !ruby/object:Gem::Version
68
71
  version: '0.15'
72
+ - - "<"
73
+ - !ruby/object:Gem::Version
74
+ version: '2.0'
69
75
  - !ruby/object:Gem::Dependency
70
76
  name: multi_json
71
77
  requirement: !ruby/object:Gem::Requirement
@@ -186,6 +192,7 @@ extensions: []
186
192
  extra_rdoc_files: []
187
193
  files:
188
194
  - ".circleci/config.yml"
195
+ - ".dockerignore"
189
196
  - ".github/ISSUE_TEMPLATE.md"
190
197
  - ".github/PULL_REQUEST_TEMPLATE.md"
191
198
  - ".gitignore"
@@ -193,6 +200,9 @@ files:
193
200
  - ".rubocop_todo.yml"
194
201
  - CHANGELOG.md
195
202
  - CODE_OF_CONDUCT.md
203
+ - CONTRIBUTING.MD
204
+ - DOCKER_README.MD
205
+ - Dockerfile
196
206
  - Gemfile
197
207
  - LICENSE
198
208
  - README.md
@@ -228,6 +238,7 @@ files:
228
238
  - lib/algolia/responses/add_api_key_response.rb
229
239
  - lib/algolia/responses/base_response.rb
230
240
  - lib/algolia/responses/delete_api_key_response.rb
241
+ - lib/algolia/responses/dictionary_response.rb
231
242
  - lib/algolia/responses/indexing_response.rb
232
243
  - lib/algolia/responses/multiple_batch_indexing_response.rb
233
244
  - lib/algolia/responses/multiple_response.rb
@@ -294,7 +305,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
294
305
  - !ruby/object:Gem::Version
295
306
  version: '0'
296
307
  requirements: []
297
- rubygems_version: 3.0.3
308
+ rubygems_version: 3.0.6
298
309
  signing_key:
299
310
  specification_version: 4
300
311
  summary: A simple Ruby client for the algolia.com REST API