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 +4 -4
- data/.circleci/config.yml +9 -0
- data/.dockerignore +38 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +35 -1
- data/CONTRIBUTING.MD +184 -0
- data/DOCKER_README.MD +89 -0
- data/Dockerfile +7 -0
- data/README.md +2 -2
- data/algolia.gemspec +1 -1
- data/lib/algolia.rb +1 -0
- data/lib/algolia/helpers.rb +51 -1
- data/lib/algolia/http/http_requester.rb +4 -4
- data/lib/algolia/responses/dictionary_response.rb +33 -0
- data/lib/algolia/search_client.rb +179 -6
- data/lib/algolia/search_index.rb +9 -50
- data/lib/algolia/transport/request_options.rb +1 -1
- data/lib/algolia/transport/transport.rb +2 -5
- data/lib/algolia/version.rb +1 -1
- data/test/algolia/integration/analytics_client_test.rb +6 -2
- data/test/algolia/integration/search_client_test.rb +107 -12
- data/test/algolia/integration/search_index_test.rb +3 -0
- data/test/algolia/unit/helpers_test.rb +4 -2
- data/test/test_helper.rb +12 -0
- metadata +16 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc743bd03ca6ebc94d2ae61eec22670ccbaa3531d2a9b66c44858280c644a938
|
4
|
+
data.tar.gz: 9e5fb85f9d474d266de360c25b7ef3efafa0fe0b78765aa1cae32b402a0865ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
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
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
|
10
|
-
<a href="https://rubygems.org/gems/algolia"><img src="https://badge.fury.io/rb/
|
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', '
|
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'
|
data/lib/algolia/helpers.rb
CHANGED
@@ -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 =
|
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
|
13
|
-
@logger
|
14
|
-
@
|
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
|
-
@
|
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
|
-
#
|
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
|
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(
|
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 = {})
|
data/lib/algolia/search_index.rb
CHANGED
@@ -987,7 +987,15 @@ module Algolia
|
|
987
987
|
# @return [IndexingResponse]
|
988
988
|
#
|
989
989
|
def set_settings(settings, opts = {})
|
990
|
-
|
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
|
@@ -127,15 +127,12 @@ module Algolia
|
|
127
127
|
|
128
128
|
# Generates headers from config headers and optional parameters
|
129
129
|
#
|
130
|
-
# @
|
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
|
data/lib/algolia/version.rb
CHANGED
@@ -23,7 +23,9 @@ class AnalyticsClientTest < BaseTest
|
|
23
23
|
endAt: tomorrow.strftime('%Y-%m-%dT%H:%M:%SZ')
|
24
24
|
}
|
25
25
|
|
26
|
-
response =
|
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 =
|
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 =
|
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
|
-
|
237
|
-
|
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 =
|
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
|
-
|
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.
|
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:
|
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.
|
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
|