algoliasearch 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c4329565282764c298bfea3ca19ae79b950a3221
4
- data.tar.gz: cec3814f851200497f6c725eb6828da43c6c42bd
3
+ metadata.gz: 6815aa98febd670b9ee776ed86899d1b1f813c4b
4
+ data.tar.gz: f5a69438b609bcbe2e70b04fb53c60c51ad007c9
5
5
  SHA512:
6
- metadata.gz: 478083554dec799684b0cc34096063ae127aad3d42ca8e08a46a7b7b356819f34c487aa3776f9ac9aa5585cd0cc2cb160baadc0a7b516da6ce00b000f1b0947f
7
- data.tar.gz: f0f4e50441de3d2047f07987fedabbf3ee9a22a2ed6db8ba62a55f2468fb37bd258d526ccd2bd8beed03645d1dde20400d33dd328554110e362da8560a5a94db
6
+ metadata.gz: 5226f954185110c75e6d6c12081139a574f9e1f6fd3579d53d92e32d48e959dde1dd2da8a4407fe0980a2b6b44852e97b0ba6eaee5ab1517ea9dbf433ed0601d
7
+ data.tar.gz: c2fa093f6517079ad36aba007bdcf59eb0f6f91209160aaa6c4ebc72a795c4ac44d30f47a45afb0fb41942623f262a0ddaeadaa4e789345daa503b609ee52f4c
data/ChangeLog CHANGED
@@ -1,9 +1,18 @@
1
1
  CHANGELOG
2
2
 
3
- 2014-11-29 1.3.0
3
+ 2014-11-29 1.3.1
4
+ * Fixed wrong deployed version (1.3.0 was based on 1.2.13 instead of 1.2.14)
4
5
 
6
+ 2014-11-29 1.3.0
5
7
  * Use algolia.net domain instead of algolia.io
6
8
 
9
+ 2014-11-10 1.2.14
10
+ * Force the underlying httpclient dependency to be >= 2.4 in the gemspec as well
11
+ * Ability to force the SSL version
12
+
13
+ 2014-10-22 1.2.13
14
+ * Fix the loop on hosts to retry when the http code is different than 200, 201, 400, 403, 404
15
+
7
16
  2014-10-08 1.2.12
8
17
 
9
18
  * Upgrade to httpclient 2.4
@@ -50,17 +50,17 @@ Gem::Specification.new do |s|
50
50
  s.specification_version = 4
51
51
 
52
52
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
53
- s.add_runtime_dependency(%q<httpclient>, ["~> 2.3"])
53
+ s.add_runtime_dependency(%q<httpclient>, ["~> 2.4"])
54
54
  s.add_runtime_dependency(%q<json>, [">= 1.5.1"])
55
55
  s.add_development_dependency "travis"
56
56
  s.add_development_dependency "rake"
57
57
  s.add_development_dependency "rdoc"
58
58
  else
59
- s.add_dependency(%q<httpclient>, ["~> 2.3"])
59
+ s.add_dependency(%q<httpclient>, ["~> 2.4"])
60
60
  s.add_dependency(%q<json>, [">= 1.5.1"])
61
61
  end
62
62
  else
63
- s.add_dependency(%q<httpclient>, ["~> 2.3"])
63
+ s.add_dependency(%q<httpclient>, ["~> 2.4"])
64
64
  s.add_dependency(%q<json>, [">= 1.5.1"])
65
65
  end
66
66
  end
@@ -10,11 +10,12 @@ module Algolia
10
10
  # A class which encapsulates the HTTPS communication with the Algolia
11
11
  # API server. Uses the HTTPClient library for low-level HTTP communication.
12
12
  class Client
13
- attr_reader :ssl, :hosts, :application_id, :api_key, :headers, :connect_timeout, :send_timeout, :receive_timeout, :search_timeout
13
+ attr_reader :ssl, :ssl_version, :hosts, :application_id, :api_key, :headers, :connect_timeout, :send_timeout, :receive_timeout, :search_timeout
14
14
 
15
15
 
16
16
  def initialize(data = {})
17
17
  @ssl = data[:ssl].nil? ? true : data[:ssl]
18
+ @ssl_version = data[:ssl_version].nil? ? nil : data[:ssl_version]
18
19
  @application_id = data[:application_id]
19
20
  @api_key = data[:api_key]
20
21
  @hosts = (data[:hosts] || 1.upto(3).map { |i| "#{@application_id}-#{i}.algolia.net" }).shuffle
@@ -40,7 +41,7 @@ module Algolia
40
41
  begin
41
42
  return perform_request(host[:session], host[:base_url] + uri, method, data)
42
43
  rescue AlgoliaProtocolError => e
43
- raise if e.code != Protocol::ERROR_TIMEOUT and e.code != Protocol::ERROR_UNAVAILABLE
44
+ raise if e.code == Protocol::ERROR_BAD_REQUEST or e.code == Protocol::ERROR_FORBIDDEN or e.code == Protocol::ERROR_NOT_FOUND
44
45
  exceptions << e
45
46
  rescue => e
46
47
  exceptions << e
@@ -76,9 +77,11 @@ module Algolia
76
77
  def thread_local_hosts(forced_timeout)
77
78
  Thread.current[:algolia_hosts] ||= {}
78
79
  Thread.current[:algolia_hosts][forced_timeout.to_s] ||= hosts.map do |host|
80
+ client = HTTPClient.new
81
+ client.ssl_config.ssl_version = @ssl_version if @ssl && @ssl_version
79
82
  hinfo = {
80
83
  :base_url => "http#{@ssl ? 's' : ''}://#{host}",
81
- :session => HTTPClient.new
84
+ :session => client
82
85
  }
83
86
  hinfo[:session].transparent_gzip_decompression = true
84
87
  hinfo[:session].connect_timeout = @connect_timeout if @connect_timeout
data/lib/algolia/index.rb CHANGED
@@ -232,27 +232,34 @@ module Algolia
232
232
  #
233
233
  # @param obj the object attributes to override
234
234
  # @param objectID the associated objectID, if nil 'obj' must contain an 'objectID' key
235
+ # @param create_if_not_exits a boolean, if true creates the object if this one doesn't exist
235
236
  #
236
- def partial_update_object(obj, objectID = nil)
237
- Algolia.client.post(Protocol.partial_object_uri(name, get_objectID(obj, objectID)), obj.to_json)
237
+ def partial_update_object(obj, objectID = nil, create_if_not_exits = true)
238
+ Algolia.client.post(Protocol.partial_object_uri(name, get_objectID(obj, objectID), create_if_not_exits), obj.to_json)
238
239
  end
239
240
 
240
241
  #
241
242
  # Partially Override the content of several objects
242
243
  #
243
244
  # @param objs an array of objects to update (each object must contains a objectID attribute)
245
+ # @param create_if_not_exits a boolean, if true create the objects if they don't exist
244
246
  #
245
- def partial_update_objects(objs)
246
- batch build_batch('partialUpdateObject', objs, true)
247
+ def partial_update_objects(objs, create_if_not_exits = true)
248
+ if create_if_not_exits
249
+ batch build_batch('partialUpdateObject', objs, true)
250
+ else
251
+ batch build_batch('partialUpdateObjectNoCreate', objs, true)
252
+ end
247
253
  end
248
254
 
249
255
  #
250
256
  # Partially Override the content of several objects and wait end of indexing
251
257
  #
252
258
  # @param objs an array of objects to update (each object must contains a objectID attribute)
259
+ # @param create_if_not_exits a boolean, if true create the objects if they don't exist
253
260
  #
254
- def partial_update_objects!(objs)
255
- res = partial_update_objects(objs)
261
+ def partial_update_objects!(objs, create_if_not_exits = true)
262
+ res = partial_update_objects(objs, create_if_not_exits)
256
263
  wait_task(res["taskID"])
257
264
  return res
258
265
  end
@@ -262,9 +269,10 @@ module Algolia
262
269
  #
263
270
  # @param obj the attributes to override
264
271
  # @param objectID the associated objectID, if nil 'obj' must contain an 'objectID' key
272
+ # @param create_if_not_exits a boolean, if true creates the object if this one doesn't exist
265
273
  #
266
- def partial_update_object!(obj, objectID = nil)
267
- res = partial_update_object(obj, objectID)
274
+ def partial_update_object!(obj, objectID = nil, create_if_not_exits = true)
275
+ res = partial_update_object(obj, objectID, create_if_not_exits)
268
276
  wait_task(res["taskID"])
269
277
  return res
270
278
  end
@@ -27,8 +27,9 @@ module Algolia
27
27
  # HTTP ERROR CODES
28
28
  # ----------------------------------------
29
29
 
30
- ERROR_TIMEOUT = 124
31
- ERROR_UNAVAILABLE = 503
30
+ ERROR_BAD_REQUEST = 400
31
+ ERROR_FORBIDDEN = 403
32
+ ERROR_NOT_FOUND = 404
32
33
 
33
34
  # URI Helpers
34
35
  # ----------------------------------------
@@ -78,8 +79,9 @@ module Algolia
78
79
  "#{index_uri(index)}/browse#{params}"
79
80
  end
80
81
 
81
- def Protocol.partial_object_uri(index, object_id)
82
- "#{index_uri(index)}/#{CGI.escape(object_id)}/partial"
82
+ def Protocol.partial_object_uri(index, object_id, create_if_not_exits = true)
83
+ params = create_if_not_exits ? "" : "?createIfNotExists=false"
84
+ "#{index_uri(index)}/#{CGI.escape(object_id)}/partial#{params}"
83
85
  end
84
86
 
85
87
  def Protocol.settings_uri(index)
@@ -1,3 +1,3 @@
1
1
  module Algolia
2
- VERSION = "1.3.0"
2
+ VERSION = "1.3.1"
3
3
  end
@@ -9,40 +9,40 @@ end
9
9
  WebMock.disable!
10
10
 
11
11
  # list indexes
12
- WebMock.stub_request(:get, /.*\.algolia\.io\/1\/indexes/).to_return(:body => '{ "items": [] }')
12
+ WebMock.stub_request(:get, /.*\.algolia\.(io|net)\/1\/indexes/).to_return(:body => '{ "items": [] }')
13
13
  # query index
14
- WebMock.stub_request(:get, /.*\.algolia\.io\/1\/indexes\/[^\/]+/).to_return(:body => '{}')
15
- WebMock.stub_request(:post, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/query/).to_return(:body => '{}')
14
+ WebMock.stub_request(:get, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+/).to_return(:body => '{}')
15
+ WebMock.stub_request(:post, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/query/).to_return(:body => '{}')
16
16
  # delete index
17
- WebMock.stub_request(:delete, /.*\.algolia\.io\/1\/indexes\/[^\/]+/).to_return(:body => '{ "taskID": 42 }')
17
+ WebMock.stub_request(:delete, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+/).to_return(:body => '{ "taskID": 42 }')
18
18
  # clear index
19
- WebMock.stub_request(:post, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/clear/).to_return(:body => '{ "taskID": 42 }')
19
+ WebMock.stub_request(:post, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/clear/).to_return(:body => '{ "taskID": 42 }')
20
20
  # add object
21
- WebMock.stub_request(:post, /.*\.algolia\.io\/1\/indexes\/[^\/]+/).to_return(:body => '{ "taskID": 42 }')
21
+ WebMock.stub_request(:post, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+/).to_return(:body => '{ "taskID": 42 }')
22
22
  # save object
23
- WebMock.stub_request(:put, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/[^\/]+/).to_return(:body => '{ "taskID": 42 }')
23
+ WebMock.stub_request(:put, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/[^\/]+/).to_return(:body => '{ "taskID": 42 }')
24
24
  # partial update
25
- WebMock.stub_request(:put, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/[^\/]+\/partial/).to_return(:body => '{ "taskID": 42 }')
25
+ WebMock.stub_request(:put, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/[^\/]+\/partial/).to_return(:body => '{ "taskID": 42 }')
26
26
  # get object
27
- WebMock.stub_request(:get, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/[^\/]+/).to_return(:body => '{}')
27
+ WebMock.stub_request(:get, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/[^\/]+/).to_return(:body => '{}')
28
28
  # delete object
29
- WebMock.stub_request(:delete, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/[^\/]+/).to_return(:body => '{ "taskID": 42 }')
29
+ WebMock.stub_request(:delete, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/[^\/]+/).to_return(:body => '{ "taskID": 42 }')
30
30
  # batch
31
- WebMock.stub_request(:post, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/batch/).to_return(:body => '{ "taskID": 42 }')
31
+ WebMock.stub_request(:post, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/batch/).to_return(:body => '{ "taskID": 42 }')
32
32
  # settings
33
- WebMock.stub_request(:get, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/settings/).to_return(:body => '{}')
34
- WebMock.stub_request(:put, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/settings/).to_return(:body => '{ "taskID": 42 }')
33
+ WebMock.stub_request(:get, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/settings/).to_return(:body => '{}')
34
+ WebMock.stub_request(:put, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/settings/).to_return(:body => '{ "taskID": 42 }')
35
35
  # browse
36
- WebMock.stub_request(:get, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/browse/).to_return(:body => '{}')
36
+ WebMock.stub_request(:get, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/browse/).to_return(:body => '{}')
37
37
  # operations
38
- WebMock.stub_request(:post, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/operation/).to_return(:body => '{ "taskID": 42 }')
38
+ WebMock.stub_request(:post, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/operation/).to_return(:body => '{ "taskID": 42 }')
39
39
  # tasks
40
- WebMock.stub_request(:get, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/task\/[^\/]+/).to_return(:body => '{ "status": "published" }')
40
+ WebMock.stub_request(:get, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/task\/[^\/]+/).to_return(:body => '{ "status": "published" }')
41
41
  # index keys
42
- WebMock.stub_request(:post, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/keys/).to_return(:body => '{ }')
43
- WebMock.stub_request(:get, /.*\.algolia\.io\/1\/indexes\/[^\/]+\/keys/).to_return(:body => '{ "keys": [] }')
42
+ WebMock.stub_request(:post, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/keys/).to_return(:body => '{ }')
43
+ WebMock.stub_request(:get, /.*\.algolia\.(io|net)\/1\/indexes\/[^\/]+\/keys/).to_return(:body => '{ "keys": [] }')
44
44
  # global keys
45
- WebMock.stub_request(:post, /.*\.algolia\.io\/1\/keys/).to_return(:body => '{ }')
46
- WebMock.stub_request(:get, /.*\.algolia\.io\/1\/keys/).to_return(:body => '{ "keys": [] }')
47
- WebMock.stub_request(:get, /.*\.algolia\.io\/1\/keys\/[^\/]+/).to_return(:body => '{ }')
48
- WebMock.stub_request(:delete, /.*\.algolia\.io\/1\/keys\/[^\/]+/).to_return(:body => '{ }')
45
+ WebMock.stub_request(:post, /.*\.algolia\.(io|net)\/1\/keys/).to_return(:body => '{ }')
46
+ WebMock.stub_request(:get, /.*\.algolia\.(io|net)\/1\/keys/).to_return(:body => '{ "keys": [] }')
47
+ WebMock.stub_request(:get, /.*\.algolia\.(io|net)\/1\/keys\/[^\/]+/).to_return(:body => '{ }')
48
+ WebMock.stub_request(:delete, /.*\.algolia\.(io|net)\/1\/keys\/[^\/]+/).to_return(:body => '{ }')
data/spec/client_spec.rb CHANGED
@@ -42,6 +42,41 @@ describe 'Client' do
42
42
  res["hits"].length.should eq(1)
43
43
  end
44
44
 
45
+ it "should partial update a simple object, or add it if it doesn't exist" do
46
+ res = @index.search("tonny@parker.org")
47
+ res["hits"].length.should eq(0)
48
+ @index.partial_update_object!({ :email => "tonny@parker.org" }, "1")
49
+ res = @index.search("tonny@parker.org")
50
+ res["hits"].length.should eq(1)
51
+ end
52
+
53
+ it "should partial update a simple object, but don't add it if it doesn't exist" do
54
+ @index.partial_update_object!({ :email => "alex@boom.org" }, "51", false)
55
+ res = @index.search("alex@boom.org")
56
+ res["hits"].length.should eq(0)
57
+ end
58
+
59
+ it "should partial update a batch of objects, and add them if they don't exist" do
60
+ batch = [
61
+ { :objectID => "1", :email => "john@wanna.org" },
62
+ { :objectID => "2", :email => "robert@wanna.org" }
63
+ ]
64
+ @index.partial_update_objects!(batch)
65
+ res = @index.search("@wanna.org")
66
+ res["hits"].length.should eq(2)
67
+ end
68
+
69
+ it "should partial update a batch of objects, but don't add them if they don't exist" do
70
+ create_if_not_exits = false
71
+ batch = [
72
+ { :objectID => "11", :email => "john@be.org" },
73
+ { :objectID => "22", :email => "robert@be.org" }
74
+ ]
75
+ @index.partial_update_objects!(batch, create_if_not_exits)
76
+ res = @index.search("@be.org")
77
+ res["hits"].length.should eq(0)
78
+ end
79
+
45
80
  it "should add a set of objects" do
46
81
  @index.add_objects!([
47
82
  { :name => "Another", :email => "another1@example.org" },
@@ -685,3 +720,4 @@ describe 'Client' do
685
720
  answer['disjunctiveFacets']['stars']['****'].should eq(1)
686
721
  end
687
722
  end
723
+
data/spec/stub_spec.rb CHANGED
@@ -10,7 +10,7 @@ describe 'With a rate limited client' do
10
10
  end
11
11
 
12
12
  it "should pass the right headers" do
13
- WebMock.stub_request(:get, %r{https://.*\.algolia\.io/1/indexes/friends\?query=.*}).
13
+ WebMock.stub_request(:get, %r{https://.*\.algolia\.(io|net)/1/indexes/friends\?query=.*}).
14
14
  with(:headers => {'Content-Type'=>'application/json; charset=utf-8', 'User-Agent'=>"Algolia for Ruby #{Algolia::VERSION}", 'X-Algolia-Api-Key'=>ENV['ALGOLIA_API_KEY'], 'X-Algolia-Application-Id'=>ENV['ALGOLIA_APPLICATION_ID'], 'X-Forwarded-Api-Key'=>'ratelimitapikey', 'X-Forwarded-For'=>'1.2.3.4'}).
15
15
  to_return(:status => 200, :body => "{ \"hits\": [], \"fakeAttribute\": 1 }", :headers => {})
16
16
  Algolia.enable_rate_limit_forward ENV['ALGOLIA_API_KEY'], "1.2.3.4", "ratelimitapikey"
@@ -20,7 +20,7 @@ describe 'With a rate limited client' do
20
20
  end
21
21
 
22
22
  it "should use original headers" do
23
- WebMock.stub_request(:get, %r{https://.*\.algolia\.io/1/indexes/friends\?query=.*}).
23
+ WebMock.stub_request(:get, %r{https://.*\.algolia\.(io|net)/1/indexes/friends\?query=.*}).
24
24
  with(:headers => {'Content-Type'=>'application/json; charset=utf-8', 'User-Agent'=>"Algolia for Ruby #{Algolia::VERSION}", 'X-Algolia-Api-Key'=>ENV['ALGOLIA_API_KEY'], 'X-Algolia-Application-Id'=>ENV['ALGOLIA_APPLICATION_ID'] }).
25
25
  to_return(:status => 200, :body => "{ \"hits\": [], \"fakeAttribute\": 2 }", :headers => {})
26
26
  Algolia.disable_rate_limit_forward
@@ -29,7 +29,7 @@ describe 'With a rate limited client' do
29
29
  end
30
30
 
31
31
  it "should pass the right headers in the scope" do
32
- WebMock.stub_request(:get, %r{https://.*\.algolia\.io/1/indexes/friends\?query=.*}).
32
+ WebMock.stub_request(:get, %r{https://.*\.algolia\.(io|net)/1/indexes/friends\?query=.*}).
33
33
  with(:headers => {'Content-Type'=>'application/json; charset=utf-8', 'User-Agent'=>"Algolia for Ruby #{Algolia::VERSION}", 'X-Algolia-Api-Key'=>ENV['ALGOLIA_API_KEY'], 'X-Algolia-Application-Id'=>ENV['ALGOLIA_APPLICATION_ID'], 'X-Forwarded-Api-Key'=>'ratelimitapikey', 'X-Forwarded-For'=>'1.2.3.4'}).
34
34
  to_return(:status => 200, :body => "{ \"hits\": [], \"fakeAttribute\": 1 }", :headers => {})
35
35
  Algolia.with_rate_limits "1.2.3.4", "ratelimitapikey" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: algoliasearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Algolia
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.3'
19
+ version: '2.4'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.3'
26
+ version: '2.4'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: json
29
29
  requirement: !ruby/object:Gem::Requirement