algoliasearch 1.26.1 → 1.27.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -1
- data/CHANGELOG.md +21 -0
- data/Gemfile.lock +4 -20
- data/lib/algolia/client.rb +22 -0
- data/lib/algolia/error.rb +9 -1
- data/lib/algolia/index.rb +87 -0
- data/lib/algolia/version.rb +1 -1
- data/spec/client_spec.rb +91 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9036ce666897c7cfb05a637b80ffcebc26a08560ac655bca29f0bbaa631aa2e6
|
4
|
+
data.tar.gz: 39a1e847147a3d9f08fa529045abaec8725d95c7cb4f8a496646c0b2dd25f9d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db1d480cc1aa22bf2c2ea547740ab905440928dab50680afb21998bffa9b6ffd29aef6dda35a0263bf5c4a61c398a7d6e260c045efe636fc1a0dbc781dd15b44
|
7
|
+
data.tar.gz: 22e70e7d376ca9ef5fca68e13b381eedd854afef4d315a2d2e18c6c2b64562e2d1952d8a17dad309171bc33dc489728004cbf9bc668fd39fc6d4e81a18bc2aa8
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# ChangeLog
|
2
2
|
|
3
|
+
## [1.27.0](https://github.com/algolia/algoliasearch-client-ruby/releases/tag/1.27.0) (2019-09-16)
|
4
|
+
|
5
|
+
**Added**
|
6
|
+
|
7
|
+
* Introduce `Algolia::Index.exists` method. [358](https://github.com/algolia/algoliasearch-client-ruby/issues/358)
|
8
|
+
|
9
|
+
Check whether an index exists or not.
|
10
|
+
|
11
|
+
* Introduce `Algolia::Index.find_object` method. [359](https://github.com/algolia/algoliasearch-client-ruby/issues/359)
|
12
|
+
|
13
|
+
Find object by the given condition.
|
14
|
+
|
15
|
+
* Introduce `Algolia::Index.get_object_position` method. [359](https://github.com/algolia/algoliasearch-client-ruby/issues/359)
|
16
|
+
|
17
|
+
Retrieve the given object position in a set of results.
|
18
|
+
|
19
|
+
* Introduce `Algolia.get_secured_api_key_remaining_validity` method. [361](https://github.com/algolia/algoliasearch-client-ruby/issues/361)
|
20
|
+
|
21
|
+
Returns the remaining validity time for the given API key in seconds.
|
22
|
+
|
23
|
+
|
3
24
|
## [1.26.1](https://github.com/algolia/algoliasearch-client-ruby/compare/1.26.0...1.26.1) (2019-07-31)
|
4
25
|
|
5
26
|
### Chore
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
algoliasearch (1.26.
|
4
|
+
algoliasearch (1.26.1)
|
5
5
|
httpclient (~> 2.8, >= 2.8.3)
|
6
6
|
json (>= 1.5.1)
|
7
7
|
|
@@ -10,12 +10,6 @@ GEM
|
|
10
10
|
specs:
|
11
11
|
addressable (2.4.0)
|
12
12
|
backports (3.15.0)
|
13
|
-
coveralls (0.7.2)
|
14
|
-
multi_json (~> 1.3)
|
15
|
-
rest-client (= 1.6.7)
|
16
|
-
simplecov (>= 0.7)
|
17
|
-
term-ansicolor (= 1.2.2)
|
18
|
-
thor (= 0.18.1)
|
19
13
|
crack (0.4.3)
|
20
14
|
safe_yaml (~> 1.0.0)
|
21
15
|
diff-lcs (1.3)
|
@@ -41,9 +35,6 @@ GEM
|
|
41
35
|
json (2.2.0)
|
42
36
|
launchy (2.4.3)
|
43
37
|
addressable (~> 2.3)
|
44
|
-
mime-types (3.2.2)
|
45
|
-
mime-types-data (~> 3.2015)
|
46
|
-
mime-types-data (3.2019.0331)
|
47
38
|
multi_json (1.13.1)
|
48
39
|
multipart-post (2.1.1)
|
49
40
|
net-http-persistent (2.9.4)
|
@@ -51,10 +42,8 @@ GEM
|
|
51
42
|
pusher-client (0.6.2)
|
52
43
|
json
|
53
44
|
websocket (~> 1.0)
|
54
|
-
rake (12.3.
|
55
|
-
rdoc (6.
|
56
|
-
rest-client (1.6.7)
|
57
|
-
mime-types (>= 1.16)
|
45
|
+
rake (12.3.3)
|
46
|
+
rdoc (6.2.0)
|
58
47
|
rspec (3.8.0)
|
59
48
|
rspec-core (~> 3.8.0)
|
60
49
|
rspec-expectations (~> 3.8.0)
|
@@ -276,10 +265,6 @@ GEM
|
|
276
265
|
json (>= 1.8, < 3)
|
277
266
|
simplecov-html (~> 0.10.0)
|
278
267
|
simplecov-html (0.10.2)
|
279
|
-
term-ansicolor (1.2.2)
|
280
|
-
tins (~> 0.8)
|
281
|
-
thor (0.18.1)
|
282
|
-
tins (0.13.2)
|
283
268
|
travis (1.8.10)
|
284
269
|
backports
|
285
270
|
faraday (~> 0.9)
|
@@ -291,7 +276,7 @@ GEM
|
|
291
276
|
typhoeus (~> 0.6, >= 0.6.8)
|
292
277
|
typhoeus (0.8.0)
|
293
278
|
ethon (>= 0.8.0)
|
294
|
-
webmock (3.
|
279
|
+
webmock (3.7.2)
|
295
280
|
addressable (>= 2.3.6)
|
296
281
|
crack (>= 0.3.2)
|
297
282
|
hashdiff (>= 0.4.0, < 2.0.0)
|
@@ -302,7 +287,6 @@ PLATFORMS
|
|
302
287
|
|
303
288
|
DEPENDENCIES
|
304
289
|
algoliasearch!
|
305
|
-
coveralls
|
306
290
|
rake
|
307
291
|
rdoc
|
308
292
|
rspec (>= 2.5.0)
|
data/lib/algolia/client.rb
CHANGED
@@ -774,6 +774,28 @@ module Algolia
|
|
774
774
|
end
|
775
775
|
end
|
776
776
|
|
777
|
+
#
|
778
|
+
# Returns the remaining validity time for the given API key in seconds
|
779
|
+
#
|
780
|
+
# @param [String] secured_api_key the secured API key to check
|
781
|
+
#
|
782
|
+
# @return [Integer] remaining validity in seconds
|
783
|
+
#
|
784
|
+
def Algolia.get_secured_api_key_remaining_validity(secured_api_key)
|
785
|
+
now = Time.now.to_i
|
786
|
+
decoded_key = Base64.decode64(secured_api_key)
|
787
|
+
regex = 'validUntil=(\d+)'
|
788
|
+
matches = decoded_key.match(regex)
|
789
|
+
|
790
|
+
if matches === nil
|
791
|
+
raise ValidUntilNotFoundError.new('The SecuredAPIKey doesn\'t have a validUntil parameter.')
|
792
|
+
end
|
793
|
+
|
794
|
+
valid_until = matches[1].to_i
|
795
|
+
|
796
|
+
valid_until - now
|
797
|
+
end
|
798
|
+
|
777
799
|
#
|
778
800
|
# This method allows to query multiple indexes with one API call
|
779
801
|
#
|
data/lib/algolia/error.rb
CHANGED
@@ -20,4 +20,12 @@ module Algolia
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
# An exception class raised when the given object was not found.
|
24
|
+
class AlgoliaObjectNotFoundError < AlgoliaError
|
25
|
+
end
|
26
|
+
|
27
|
+
# An exception class raised when the validUntil parameter is not found
|
28
|
+
class ValidUntilNotFoundError < AlgoliaError
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
data/lib/algolia/index.rb
CHANGED
@@ -264,6 +264,75 @@ module Algolia
|
|
264
264
|
client.post(Protocol.objects_uri, { :requests => requests }.to_json, :read, request_options)['results']
|
265
265
|
end
|
266
266
|
|
267
|
+
#
|
268
|
+
# Find object by the given condition.
|
269
|
+
#
|
270
|
+
# Options can be passed in request_options body:
|
271
|
+
# - query (string): pass a query
|
272
|
+
# - paginate (bool): choose if you want to iterate through all the
|
273
|
+
# documents (true) or only the first page (false). Default is true.
|
274
|
+
# The function takes a block to filter the results from search query
|
275
|
+
# Usage example:
|
276
|
+
# index.find_object({'query' => '', 'paginate' => true}) {|obj| obj.key?('company') and obj['company'] == 'Apple'}
|
277
|
+
#
|
278
|
+
# @param request_options contains extra parameters to send with your query
|
279
|
+
#
|
280
|
+
# @return [Hash] the matching object and its position in the result set
|
281
|
+
#
|
282
|
+
def find_object(request_options = {})
|
283
|
+
paginate = true
|
284
|
+
page = 0
|
285
|
+
|
286
|
+
query = request_options[:query] || request_options['query'] || ''
|
287
|
+
request_options.delete(:query)
|
288
|
+
request_options.delete('query')
|
289
|
+
|
290
|
+
if request_options.has_key? :paginate
|
291
|
+
paginate = request_options[:paginate]
|
292
|
+
end
|
293
|
+
|
294
|
+
if request_options.has_key? 'paginate'
|
295
|
+
paginate = request_options['paginate']
|
296
|
+
end
|
297
|
+
|
298
|
+
request_options.delete(:paginate)
|
299
|
+
request_options.delete('paginate')
|
300
|
+
|
301
|
+
while true
|
302
|
+
request_options['page'] = page
|
303
|
+
res = search(query, request_options)
|
304
|
+
|
305
|
+
res['hits'].each_with_index do |hit, i|
|
306
|
+
if yield(hit)
|
307
|
+
return {
|
308
|
+
'object' => hit,
|
309
|
+
'position' => i,
|
310
|
+
'page' => page,
|
311
|
+
}
|
312
|
+
end
|
313
|
+
end if block_given?
|
314
|
+
|
315
|
+
has_next_page = page + 1 < res['nbPages']
|
316
|
+
if !paginate || !has_next_page
|
317
|
+
raise AlgoliaObjectNotFoundError.new('Object not found')
|
318
|
+
end
|
319
|
+
|
320
|
+
page += 1
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
#
|
325
|
+
# Retrieve the given object position in a set of results.
|
326
|
+
#
|
327
|
+
# @param [Array] objects the result set to browse
|
328
|
+
# @param [String] object_id the object to look for
|
329
|
+
#
|
330
|
+
# @return [Integer] position of the object, or -1 if it's not in the array
|
331
|
+
#
|
332
|
+
def self.get_object_position(objects, object_id)
|
333
|
+
objects['hits'].find_index { |hit| hit['objectID'] == object_id } || -1
|
334
|
+
end
|
335
|
+
|
267
336
|
#
|
268
337
|
# Check the status of a task on the server.
|
269
338
|
# All server task are asynchronous and you can check the status of a task with this method.
|
@@ -1208,6 +1277,24 @@ module Algolia
|
|
1208
1277
|
res
|
1209
1278
|
end
|
1210
1279
|
|
1280
|
+
#
|
1281
|
+
# Check whether an index exists or not
|
1282
|
+
#
|
1283
|
+
# @return [Boolean]
|
1284
|
+
#
|
1285
|
+
def exists
|
1286
|
+
begin
|
1287
|
+
get_settings
|
1288
|
+
rescue AlgoliaProtocolError => e
|
1289
|
+
if e.code === 404
|
1290
|
+
return false
|
1291
|
+
end
|
1292
|
+
|
1293
|
+
raise e
|
1294
|
+
end
|
1295
|
+
return true
|
1296
|
+
end
|
1297
|
+
|
1211
1298
|
# Deprecated
|
1212
1299
|
alias_method :get_user_key, :get_api_key
|
1213
1300
|
alias_method :list_user_keys, :list_api_keys
|
data/lib/algolia/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
@@ -175,6 +175,16 @@ describe 'Client' do
|
|
175
175
|
@index.delete_index rescue "not fatal"
|
176
176
|
end
|
177
177
|
|
178
|
+
it "should tell if index exists" do
|
179
|
+
@index.add_object!({ :name => "John Doe", :email => "john@doe.org" }, "1")
|
180
|
+
expect(@index.exists).to be true
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should tell if index does not exist" do
|
184
|
+
index = Algolia::Index.new('nonexistent_index')
|
185
|
+
expect(index.exists).to be false
|
186
|
+
end
|
187
|
+
|
178
188
|
it "should add a simple object" do
|
179
189
|
@index.add_object!({ :name => "John Doe", :email => "john@doe.org" }, "1")
|
180
190
|
res = @index.search("john")
|
@@ -436,6 +446,73 @@ describe 'Client' do
|
|
436
446
|
end
|
437
447
|
end
|
438
448
|
|
449
|
+
it 'should find objects when needed' do
|
450
|
+
index = Algolia::Index.new(safe_index_name("àlgol?à"))
|
451
|
+
|
452
|
+
index.save_objects!([
|
453
|
+
{:company => 'Algolia', :name => 'Julien Lemoine', :objectID => 'julien-lemoine'},
|
454
|
+
{:company => 'Algolia', :name => 'Nicolas Dessaigne', :objectID => 'nicolas-dessaigne'},
|
455
|
+
{:company => 'Amazon', :name =>' "Jeff Bezos', :objectID => '162590850'},
|
456
|
+
{:company => 'Apple', :name => 'Steve Jobs', :objectID => '162590860'},
|
457
|
+
{:company => 'Apple', :name => 'Steve Wozniak', :objectID => '162590870'},
|
458
|
+
{:company => 'Arista Networks', :name => 'Jayshree Ullal', :objectID => '162590880'},
|
459
|
+
{:company => 'Google', :name => 'Larry Page', :objectID => '162590890'},
|
460
|
+
{:company => 'Google', :name => 'Rob Pike', :objectID => '162590900'},
|
461
|
+
{:company => 'Google', :name => 'Sergueï Brin', :objectID => '162590910'},
|
462
|
+
{:company => 'Microsoft', :name => 'Bill Gates', :objectID => '162590920'},
|
463
|
+
{:company => 'SpaceX', :name => 'Elon Musk', :objectID => '162590930'},
|
464
|
+
{:company => 'Tesla', :name => 'Elon Musk', :objectID => '162590940'},
|
465
|
+
{:company => 'Yahoo', :name => 'Marissa Mayer', :objectID => '162590950'},
|
466
|
+
])
|
467
|
+
|
468
|
+
res = index.search('algolia')
|
469
|
+
Algolia::Index.get_object_position(res, 'nicolas-dessaigne').should eq(0)
|
470
|
+
Algolia::Index.get_object_position(res, 'julien-lemoine').should eq(1)
|
471
|
+
Algolia::Index.get_object_position(res, '').should eq(-1)
|
472
|
+
|
473
|
+
expect {
|
474
|
+
index.find_object({'query' => '', 'paginate' => true})
|
475
|
+
}.to raise_exception(
|
476
|
+
Algolia::AlgoliaObjectNotFoundError,
|
477
|
+
'Object not found'
|
478
|
+
)
|
479
|
+
|
480
|
+
expect {
|
481
|
+
index.find_object({'query' => '', 'paginate' => true}) { false }
|
482
|
+
}.to raise_exception(
|
483
|
+
Algolia::AlgoliaObjectNotFoundError,
|
484
|
+
'Object not found'
|
485
|
+
)
|
486
|
+
|
487
|
+
obj = index.find_object({'query' => '', 'paginate' => true}) { true }
|
488
|
+
obj['position'].should eq(0)
|
489
|
+
obj['page'].should eq(0)
|
490
|
+
|
491
|
+
# we use a lambda and convert it to a block with `&`
|
492
|
+
# so as not to repeat the condition
|
493
|
+
condition = lambda do |obj|
|
494
|
+
obj.key?('company') and obj['company'] == 'Apple'
|
495
|
+
end
|
496
|
+
|
497
|
+
expect {
|
498
|
+
index.find_object({'query' => 'algolia', 'paginate' => true}, &condition)
|
499
|
+
}.to raise_exception(
|
500
|
+
Algolia::AlgoliaObjectNotFoundError,
|
501
|
+
'Object not found'
|
502
|
+
)
|
503
|
+
|
504
|
+
expect {
|
505
|
+
index.find_object({'query' => '', 'paginate' => false, 'hitsPerPage' => 5}, &condition)
|
506
|
+
}.to raise_exception(
|
507
|
+
Algolia::AlgoliaObjectNotFoundError,
|
508
|
+
'Object not found'
|
509
|
+
)
|
510
|
+
|
511
|
+
obj = index.find_object({'query' => '', 'paginate' => true, 'hitsPerPage' => 5}, &condition)
|
512
|
+
obj['position'].should eq(0)
|
513
|
+
obj['page'].should eq(2)
|
514
|
+
end
|
515
|
+
|
439
516
|
it "should copy the index" do
|
440
517
|
index = Algolia::Index.new(safe_index_name("àlgol?à"))
|
441
518
|
begin
|
@@ -615,7 +692,7 @@ describe 'Client' do
|
|
615
692
|
expect { Algolia.multiple_queries([{"query" => ""}]) }.to raise_error(ArgumentError)
|
616
693
|
end
|
617
694
|
|
618
|
-
it "
|
695
|
+
it "should accept custom batch" do
|
619
696
|
@index.clear_index! rescue "Not fatal"
|
620
697
|
request = { "requests" => [
|
621
698
|
{
|
@@ -1277,6 +1354,19 @@ describe 'Client' do
|
|
1277
1354
|
expect{Algolia.list_indexes('headers' => { 'X-Algolia-API-Key' => 'NotExistentAPIKey' })}.to raise_error(Algolia::AlgoliaProtocolError)
|
1278
1355
|
end
|
1279
1356
|
|
1357
|
+
it 'should retrieve the remaining validity time in seconds' do
|
1358
|
+
now = Time.now.to_i
|
1359
|
+
|
1360
|
+
key = Algolia.generate_secured_api_key('foo', :validUntil => now - (10 * 60))
|
1361
|
+
expect(Algolia.get_secured_api_key_remaining_validity(key)).to be < 0
|
1362
|
+
|
1363
|
+
key = Algolia.generate_secured_api_key('foo', :validUntil => now + (10 * 60))
|
1364
|
+
expect(Algolia.get_secured_api_key_remaining_validity(key)).to be > 0
|
1365
|
+
|
1366
|
+
key = Algolia.generate_secured_api_key('foo', [])
|
1367
|
+
expect { Algolia.get_secured_api_key_remaining_validity(key) }.to raise_error(Algolia::ValidUntilNotFoundError)
|
1368
|
+
end
|
1369
|
+
|
1280
1370
|
context 'DNS timeout' do
|
1281
1371
|
before(:each) do
|
1282
1372
|
@client = Algolia::Client.new :application_id => ENV['ALGOLIA_APPLICATION_ID'], :api_key => ENV['ALGOLIA_API_KEY'],
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: algoliasearch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.27.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Algolia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpclient
|
@@ -145,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
145
|
- !ruby/object:Gem::Version
|
146
146
|
version: '0'
|
147
147
|
requirements: []
|
148
|
-
rubygems_version: 3.0.
|
148
|
+
rubygems_version: 3.0.4
|
149
149
|
signing_key:
|
150
150
|
specification_version: 4
|
151
151
|
summary: A simple Ruby client for the algolia.com REST API
|