algoliasearch 1.2.2 → 1.2.3

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
- ---
2
- SHA1:
3
- metadata.gz: fc4ad0e747cb1f514fd118b8b1f09e787d5310cd
4
- data.tar.gz: 29066a59d3003a129c446a4e14da14a8390cde6e
5
- SHA512:
6
- metadata.gz: 7c24ead447698bfd22333db709d541c1fa3a432c13f37c3f5cc789afc63db5edc18ec1796579cdc47012c94cd586605d05ef08e9c2e2660e9eb4f0dc0832adc6
7
- data.tar.gz: f7bde31ef08f0ef03e61a46df6436c07c30b8daaf6e16719de15fb8cdf664e10c5241ba7d8ac74518ce6b1e1269e82560468e84beffb71f4d7d87c1e6d4e00cf
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c168df1007c65f3a05fdac4a6d85abb0c032307b
4
+ data.tar.gz: 428cd9b8e97c21fdece377ef64e5a8b78118470c
5
+ SHA512:
6
+ metadata.gz: a9443ef278cfc1767212702a70f7d335f18b710f77538014c6e327e0bb165ab676f1044594a323a83718efec5e4bce00efb2dd2efc209f48d2143984260a06c5
7
+ data.tar.gz: 9ded465bc3d8f4486c96693ea14cfecb6f0ba2a4249931f8c15fae518f3ba2bf82cd6827b0da0b9462c305a799b2fc86e7a0b6a677269dd43ba8d3adff5445da
data/ChangeLog CHANGED
@@ -1,5 +1,9 @@
1
1
  CHANGELOG
2
2
 
3
+ 2014-02-10 1.2.3
4
+
5
+ * add_object: POST request if objectID is nil OR empty
6
+
3
7
  2014-01-11 1.2.2
4
8
 
5
9
  * Expose batch requests
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ gem 'json', '>= 1.5.1'
5
5
  gem 'rubysl', '~> 2.0', platform: :rbx
6
6
 
7
7
  group :development do
8
+ gem 'coveralls'
8
9
  gem 'travis'
9
10
  gem 'rake'
10
11
  gem 'rdoc'
@@ -17,4 +18,5 @@ group :test do
17
18
  gem 'redgreen'
18
19
  gem 'autotest-growl'
19
20
  gem 'webmock'
21
+ gem 'simplecov'
20
22
  end
data/Gemfile.lock CHANGED
@@ -10,9 +10,16 @@ GEM
10
10
  autotest-growl (0.2.16)
11
11
  backports (3.4.0)
12
12
  coderay (1.1.0)
13
+ coveralls (0.7.0)
14
+ multi_json (~> 1.3)
15
+ rest-client
16
+ simplecov (>= 0.7)
17
+ term-ansicolor
18
+ thor
13
19
  crack (0.4.1)
14
20
  safe_yaml (~> 0.9.0)
15
21
  diff-lcs (1.2.5)
22
+ docile (1.1.2)
16
23
  ethon (0.6.2)
17
24
  ffi (>= 1.3.0)
18
25
  mime-types (~> 1.18)
@@ -36,6 +43,9 @@ GEM
36
43
  json (1.8.1-java)
37
44
  launchy (2.4.2)
38
45
  addressable (~> 2.3)
46
+ launchy (2.4.2-java)
47
+ addressable (~> 2.3)
48
+ spoon (~> 0.0.1)
39
49
  method_source (0.8.2)
40
50
  mime-types (1.25.1)
41
51
  multi_json (1.8.2)
@@ -57,6 +67,8 @@ GEM
57
67
  rdoc (4.1.0)
58
68
  json (~> 1.4)
59
69
  redgreen (1.2.2)
70
+ rest-client (1.6.7)
71
+ mime-types (>= 1.16)
60
72
  rspec (2.14.1)
61
73
  rspec-core (~> 2.14.0)
62
74
  rspec-expectations (~> 2.14.0)
@@ -268,11 +280,20 @@ GEM
268
280
  rubysl-yaml (2.0.4)
269
281
  rubysl-zlib (2.0.1)
270
282
  safe_yaml (0.9.7)
283
+ simplecov (0.8.2)
284
+ docile (~> 1.1.0)
285
+ multi_json
286
+ simplecov-html (~> 0.8.0)
287
+ simplecov-html (0.8.0)
271
288
  slop (3.4.7)
272
289
  spoon (0.0.4)
273
290
  ffi
274
291
  sys-uname (0.9.2)
275
292
  ffi (>= 1.0.0)
293
+ term-ansicolor (1.2.2)
294
+ tins (~> 0.8)
295
+ thor (0.18.1)
296
+ tins (0.13.1)
276
297
  travis (1.6.6)
277
298
  addressable (~> 2.3)
278
299
  backports
@@ -299,6 +320,7 @@ DEPENDENCIES
299
320
  autotest
300
321
  autotest-fsevent
301
322
  autotest-growl
323
+ coveralls
302
324
  httpclient (~> 2.3)
303
325
  json (>= 1.5.1)
304
326
  rake
@@ -306,5 +328,6 @@ DEPENDENCIES
306
328
  redgreen
307
329
  rspec (>= 2.5.0)
308
330
  rubysl (~> 2.0)
331
+ simplecov
309
332
  travis
310
333
  webmock
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  Algolia Search API Client for Ruby
2
2
  ==================
3
3
 
4
+
5
+
6
+
7
+
4
8
  [Algolia Search](http://www.algolia.com) is a search API that provides hosted full-text, numerical and faceted search.
5
9
  Algolia’s Search API makes it easy to deliver a great search experience in your apps & websites providing:
6
10
 
@@ -15,20 +19,23 @@ Algolia’s Search API makes it easy to deliver a great search experience in you
15
19
 
16
20
  This Ruby client let you easily use the Algolia Search API from your backend. It wraps [Algolia's REST API](http://www.algolia.com/doc/rest_api).
17
21
 
18
- [![Build Status](https://travis-ci.org/algolia/algoliasearch-client-ruby.png?branch=master)](https://travis-ci.org/algolia/algoliasearch-client-ruby) [![Gem Version](https://badge.fury.io/rb/algoliasearch.png)](http://badge.fury.io/rb/algoliasearch) [![Code Climate](https://codeclimate.com/github/algolia/algoliasearch-client-ruby.png)](https://codeclimate.com/github/algolia/algoliasearch-client-ruby)
22
+ [![Build Status](https://travis-ci.org/algolia/algoliasearch-client-ruby.png?branch=master)](https://travis-ci.org/algolia/algoliasearch-client-ruby) [![Gem Version](https://badge.fury.io/rb/algoliasearch.png)](http://badge.fury.io/rb/algoliasearch) [![Code Climate](https://codeclimate.com/github/algolia/algoliasearch-client-ruby.png)](https://codeclimate.com/github/algolia/algoliasearch-client-ruby) [![Coverage Status](https://coveralls.io/repos/algolia/algoliasearch-client-ruby/badge.png)](https://coveralls.io/r/algolia/algoliasearch-client-ruby)
23
+
24
+
19
25
 
20
26
  Table of Content
21
27
  -------------
22
28
  **Get started**
23
29
 
24
- 1. [Setup](#setup)
30
+ 1. [Setup](#setup)
25
31
  1. [Quick Start](#quick-start)
32
+ 1. [Online documentation](#online-documentation)
26
33
 
27
34
  **Commands reference**
28
35
 
29
- 1. [Search](#search)
30
36
  1. [Add a new object](#add-a-new-object-in-the-index)
31
37
  1. [Update an object](#update-an-existing-object-in-the-index)
38
+ 1. [Search](#search)
32
39
  1. [Get an object](#get-an-object)
33
40
  1. [Delete an object](#delete-an-object)
34
41
  1. [Index settings](#index-settings)
@@ -43,10 +50,16 @@ Table of Content
43
50
  1. [Logs](#logs)
44
51
  1. [Mock](#mock)
45
52
 
53
+
54
+
55
+
46
56
  Setup
47
57
  -------------
48
58
  To setup your project, follow these steps:
49
59
 
60
+
61
+
62
+
50
63
  1. Install AlgoliaSearch using <code>gem install algoliasearch</code>.
51
64
  2. Initialize the client with your ApplicationID and API-Key. You can find all of them on [your Algolia account](http://www.algolia.com/users/edit).
52
65
 
@@ -58,8 +71,11 @@ Algolia.init :application_id => "YourApplicationID",
58
71
  :api_key => "YourAPIKey"
59
72
  ```
60
73
 
74
+
75
+
61
76
  Quick Start
62
77
  -------------
78
+
63
79
  This quick start is a 30 seconds tutorial where you can discover how to index and search objects.
64
80
 
65
81
  Without any prior-configuration, you can index [500 contacts](https://github.com/algolia/algoliasearch-client-ruby/blob/master/contacts.json) in the ```contacts``` index with the following code:
@@ -85,6 +101,7 @@ Settings can be customized to tune the search behavior. For example you can add
85
101
  ```ruby
86
102
  index.set_settings({"customRanking" => ["desc(followers)"]})
87
103
  ```
104
+
88
105
  You can also configure the list of attributes you want to index by order of importance (first = most important):
89
106
  ```ruby
90
107
  index.set_settings({"attributesToIndex" => ["lastname", "firstname", "company",
@@ -97,13 +114,91 @@ puts index.search('or').to_json
97
114
  puts index.search('jim').to_json
98
115
  ```
99
116
 
117
+
118
+
119
+
120
+ Online Documentation
121
+ ----------------
122
+
123
+ Check our [online documentation](http://www.algolia.com/doc):
124
+ * [Initial Import](http://www.algolia.com/doc#InitialImport)
125
+ * [Ranking &amp; Relevance](http://www.algolia.com/doc#RankingRelevance)
126
+ * [Settings](http://www.algolia.com/doc#Settings)
127
+ * [Search](http://www.algolia.com/doc#Search)
128
+ * [Incremental Updates](http://www.algolia.com/doc#IncrementalUpdates)
129
+ * [Reindexing](http://www.algolia.com/doc#Reindexing)
130
+ * [Numeric-Search](http://www.algolia.com/doc#Numeric-Search)
131
+ * [Category-Search](http://www.algolia.com/doc#Category-Search)
132
+ * [Faceting](http://www.algolia.com/doc#Faceting)
133
+ * [Geo-Search](http://www.algolia.com/doc#Geo-Search)
134
+ * [Security](http://www.algolia.com/doc#Security)
135
+ * [Indexing Several Types](http://www.algolia.com/doc#IndexingSeveralTypes)
136
+ * [REST API](http://www.algolia.com/doc/rest)
137
+
138
+
139
+
140
+
141
+
142
+
143
+
144
+ Add a new object in the Index
145
+ -------------
146
+
147
+ Each entry in an index has a unique identifier called `objectID`. You have two ways to add en entry in the index:
148
+
149
+ 1. Using automatic `objectID` assignement, you will be able to retrieve it in the answer.
150
+ 2. Passing your own `objectID`
151
+
152
+ You don't need to explicitely create an index, it will be automatically created the first time you add an object.
153
+ Objects are schema less, you don't need any configuration to start indexing. The settings section provide details about advanced settings.
154
+
155
+ Example with automatic `objectID` assignement:
156
+
157
+ ```ruby
158
+ res = index.add_object({"firstname" => "Jimmie",
159
+ "lastname" => "Barninger"})
160
+ puts "ObjectID=" + res["objectID"]
161
+ ```
162
+
163
+ Example with manual `objectID` assignement:
164
+
165
+ ```ruby
166
+ res = index.add_object({"firstname" => "Jimmie",
167
+ "lastname" => "Barninger"}, "myID")
168
+ puts "ObjectID=" + res["objectID"]
169
+ ```
170
+
171
+ Update an existing object in the Index
172
+ -------------
173
+
174
+ You have two options to update an existing object:
175
+
176
+ 1. Replace all its attributes.
177
+ 2. Replace only some attributes.
178
+
179
+ Example to replace all the content of an existing object:
180
+
181
+ ```ruby
182
+ index.save_object({"firstname" => "Jimmie",
183
+ "lastname" => "Barninger",
184
+ "city" => "New York",
185
+ "objectID" => "myID"})
186
+ ```
187
+
188
+ Example to update only the city attribute of an existing object:
189
+
190
+ ```ruby
191
+ index.partial_update_object({"city" => "San Francisco",
192
+ "objectID" => "myID"})
193
+ ```
194
+
100
195
  Search
101
196
  -------------
102
- > **Opening note:** If you are building a web application, you may be more interested in using our [javascript client](https://github.com/algolia/algoliasearch-client-js) to send queries. It brings two benefits: (i) your users get a better response time by avoiding to go through your servers, and (ii) it will offload your servers of unnecessary tasks.
197
+ **Opening note:** If you are building a web application, you may be more interested in using our [javascript client](https://github.com/algolia/algoliasearch-client-js) to send queries. It brings two benefits: (i) your users get a better response time by avoiding to go through your servers, and (ii) it will offload your servers of unnecessary tasks.
103
198
 
104
- To perform a search, you just need to initialize the index and perform a call to the search function.<br/>
105
- You can use the following optional arguments:
199
+ To perform a search, you just need to initialize the index and perform a call to the search function.
106
200
 
201
+ You can use the following optional arguments:
107
202
 
108
203
  ### Query parameters
109
204
 
@@ -129,6 +224,7 @@ You can use the following optional arguments:
129
224
  * **insideBoundingBox**: search entries inside a given area defined by the two extreme points of a rectangle (defined by 4 floats: p1Lat,p1Lng,p2Lat,p2Lng).<br/>For example `insideBoundingBox=47.3165,4.9665,47.3424,5.0201`).<br/>At indexing, you should specify geoloc of an object with the _geoloc attribute (in the form `{"_geoloc":{"lat":48.853409, "lng":2.348800}}`)
130
225
 
131
226
  #### Parameters to control results content
227
+
132
228
  * **attributesToRetrieve**: a string that contains the list of object attributes you want to retrieve (let you minimize the answer size).<br/> Attributes are separated with a comma (for example `"name,address"`), you can also use a string array encoding (for example `["name","address"]` ). By default, all attributes are retrieved. You can also use `*` to retrieve all values when an **attributesToRetrieve** setting is specified for your index.
133
229
  * **attributesToHighlight**: a string that contains the list of attributes you want to highlight according to the query. Attributes are separated by a comma. You can also use a string array encoding (for example `["name","address"]`). If an attribute has no match for the query, the raw value is returned. By default all indexed text attributes are highlighted. You can use `*` if you want to highlight all textual attributes. Numerical attributes are not highlighted. A matchLevel is returned for each highlighted attribute and can contain:
134
230
  * **full**: if all the query terms were found in the attribute,
@@ -136,6 +232,7 @@ You can use the following optional arguments:
136
232
  * **none**: if none of the query terms were found.
137
233
  * **attributesToSnippet**: a string that contains the list of attributes to snippet alongside the number of words to return (syntax is `attributeName:nbWords`). Attributes are separated by a comma (Example: `attributesToSnippet=name:10,content:10`). <br/>You can also use a string array encoding (Example: `attributesToSnippet: ["name:10","content:10"]`). By default no snippet is computed.
138
234
  * **getRankingInfo**: if set to 1, the result hits will contain ranking information in **_rankingInfo** attribute.
235
+
139
236
 
140
237
  #### Numeric search parameters
141
238
  * **numericFilters**: a string that contains the list of numeric filters you want to apply separated by a comma. The syntax of one filter is `attributeName` followed by `operand` followed by `value`. Supported operands are `<`, `<=`, `=`, `>` and `>=`.
@@ -145,7 +242,7 @@ You can use the following optional arguments:
145
242
  * **tagFilters**: filter the query by a set of tags. You can AND tags by separating them by commas. To OR tags, you must add parentheses. For example, `tags=tag1,(tag2,tag3)` means *tag1 AND (tag2 OR tag3)*. You can also use a string array encoding, for example `tagFilters: ["tag1",["tag2","tag3"]]` means *tag1 AND (tag2 OR tag3)*.<br/>At indexing, tags should be added in the **_tags** attribute of objects (for example `{"_tags":["tag1","tag2"]}`).
146
243
 
147
244
  #### Faceting parameters
148
- * **facetFilters**: filter the query by a list of facets. Facets are separated by commas and each facet is encoded as `attributeName:value`. For example: `facetFilters=category:Book,author:John%20Doe`. You can also use a string array encoding (for example `["category:Book","author:John%20Doe"]`).
245
+ * **facetFilters**: filter the query by a list of facets. Facets are separated by commas and each facet is encoded as `attributeName:value`. To OR facets, you must add parentheses. For example: `facetFilters=(category:Book,category:Movie),author:John%20Doe`. You can also use a string array encoding (for example `[["category:Book","category:Movie"],"author:John%20Doe"]`).
149
246
  * **facets**: List of object attributes that you want to use for faceting. <br/>Attributes are separated with a comma (for example `"category,author"` ). You can also use a JSON string array encoding (for example `["category","author"]` ). Only attributes that have been added in **attributesForFaceting** index setting can be used in this parameter. You can also use `*` to perform faceting on all attributes specified in **attributesForFaceting**.
150
247
 
151
248
  #### Distinct parameter
@@ -192,57 +289,6 @@ The server response will look like:
192
289
  }
193
290
  ```
194
291
 
195
- Add a new object in the Index
196
- -------------
197
-
198
- Each entry in an index has a unique identifier called `objectID`. You have two ways to add en entry in the index:
199
-
200
- 1. Using automatic `objectID` assignement, you will be able to retrieve it in the answer.
201
- 2. Passing your own `objectID`
202
-
203
- You don't need to explicitely create an index, it will be automatically created the first time you add an object.
204
- Objects are schema less, you don't need any configuration to start indexing. The settings section provide details about advanced settings.
205
-
206
- Example with automatic `objectID` assignement:
207
-
208
- ```ruby
209
- res = index.add_object({"firstname" => "Jimmie",
210
- "lastname" => "Barninger"})
211
- puts "ObjectID=" + res["objectID"]
212
- ```
213
-
214
- Example with manual `objectID` assignement:
215
-
216
- ```ruby
217
- res = index.add_object({"firstname" => "Jimmie",
218
- "lastname" => "Barninger"}, "myID")
219
- puts "ObjectID=" + res["objectID"]
220
- ```
221
-
222
- Update an existing object in the Index
223
- -------------
224
-
225
- You have two options to update an existing object:
226
-
227
- 1. Replace all its attributes.
228
- 2. Replace only some attributes.
229
-
230
- Example to replace all the content of an existing object:
231
-
232
- ```ruby
233
- index.save_object({"firstname" => "Jimmie",
234
- "lastname" => "Barninger",
235
- "city" => "New York",
236
- "objectID" => "myID"})
237
- ```
238
-
239
- Example to update only the city attribute of an existing object:
240
-
241
- ```ruby
242
- index.partial_update_object({"city" => "San Francisco",
243
- "objectID" => "myID"})
244
- ```
245
-
246
292
  Get an object
247
293
  -------------
248
294
 
@@ -269,7 +315,8 @@ index.delete_object("myID")
269
315
  Index Settings
270
316
  -------------
271
317
 
272
- You can retrieve all settings using the `getSettings` function. The result will contains the following attributes:
318
+ You can retrieve all settings using the `get_settings` function. The result will contains the following attributes:
319
+
273
320
 
274
321
  #### Indexing parameters
275
322
  * **attributesToIndex**: (array of strings) the list of fields you want to index.<br/>If set to null, all textual and numerical attributes of your objects are indexed, but you should update it to get optimal results.<br/>This parameter has two important uses:
@@ -292,6 +339,7 @@ For example `"customRanking" => ["desc(population)", "asc(name)"]`
292
339
  * **prefixAll**: all query words are interpreted as prefixes,
293
340
  * **prefixLast**: only the last word is interpreted as a prefix (default behavior),
294
341
  * **prefixNone**: no query word is interpreted as a prefix. This option is not recommended.
342
+ * **slaves**: The list of indexes on which you want to replicate all write operations. In order to get response times in milliseconds, we pre-compute part of the ranking during indexing. If you want to use different ranking configurations depending of the use-case, you need to create one index per ranking configuration. This option enables you to perform write operations only on this index, and to automatically update slave indexes with the same operations.
295
343
 
296
344
  #### Default query parameters (can be overwrite by query)
297
345
  * **minWordSizefor1Typo**: (integer) the minimum number of characters to accept one typo (default = 3).
@@ -329,22 +377,21 @@ You can delete an index using its name:
329
377
 
330
378
  ```ruby
331
379
  index = Algolia::Index.new("contacts")
332
- index.delete
380
+ index.delete_index
333
381
  ```
334
382
 
335
383
  Clear an index
336
384
  -------------
337
-
338
385
  You can delete the index content without removing settings and index specific API keys with the clearIndex command:
339
386
 
340
387
  ```ruby
341
- index.clear
388
+ index.clear_index
342
389
  ```
343
390
 
344
391
  Wait indexing
345
392
  -------------
346
393
 
347
- All write operations return a `taskID` when the job is securely stored on our infrastructure but not when the job is published in your index. Even if it's extremely fast, you can easily ensure indexing is complete using the same method with a `!`.
394
+ All write operations return a `taskID` when the job is securely stored on our infrastructure but not when the job is published in your index. Even if it's extremely fast, you can easily ensure indexing is complete using the same method with a `!`.
348
395
 
349
396
  For example, to wait for indexing of a new object:
350
397
  ```ruby
@@ -352,13 +399,14 @@ res = index.add_object!({"firstname" => "Jimmie",
352
399
  "lastname" => "Barninger"})
353
400
  ```
354
401
 
402
+
355
403
  If you want to ensure multiple objects have been indexed, you can only check the biggest taskID with `wait_task`.
356
404
 
357
405
  Batch writes
358
406
  -------------
359
407
 
360
408
  You may want to perform multiple operations with one API call to reduce latency.
361
- We expose two methods to perform batch:
409
+ We expose three methods to perform batch:
362
410
  * `add_objects`: add an array of object using automatic `objectID` assignement
363
411
  * `save_objects`: add or update an array of object that contains an `objectID` attribute
364
412
  * `partial_update_objects`: partially update an array of objects that contain an `objectID` attribute (only specified attributes will be updated, other will remain unchanged)
@@ -389,6 +437,8 @@ res = index.partial_update_objects([{"firstname" => "Jimmie",
389
437
  "objectID" => "myID2"}])
390
438
  ```
391
439
 
440
+
441
+
392
442
  Security / User API Keys
393
443
  -------------
394
444
 
@@ -422,11 +472,13 @@ puts res['key']
422
472
  res = index.add_user_key(["search"])
423
473
  puts res['key']
424
474
  ```
475
+
425
476
  You can also create an API Key with advanced restrictions:
426
477
 
427
478
  * Add a validity period: the key will be valid only for a specific period of time (in seconds),
428
479
  * Specify the maximum number of API calls allowed from an IP address per hour. Each time an API call is performed with this key, a check is performed. If the IP at the origin of the call did more than this number of calls in the last hour, a 403 code is returned. Defaults to 0 (no rate limit). This parameter can be used to protect you from attempts at retrieving your entire content by massively querying the index.
429
480
 
481
+
430
482
  Note: If you are sending the query through your servers, you must use the `Algolia.with_rate_limits("EndUserIP", "APIKeyWithRateLimit") do ... end` block to enable rate-limit.
431
483
 
432
484
  * Specify the maximum number of hits this API key can retrieve in one call. Defaults to 0 (unlimited). This parameter can be used to protect you from attempts at retrieving your entire content by massively querying the index.
@@ -534,8 +586,8 @@ describe 'With a mocked client' do
534
586
  index = Algolia::Index.new("friends")
535
587
  index.add_object!({ :name => "John Doe", :email => "john@doe.org" })
536
588
  index.search('').should == {} # mocked
537
- index.clear
538
- index.delete
589
+ index.clear_index
590
+ index.delete_index
539
591
  end
540
592
 
541
593
  after(:each) do
@@ -544,3 +596,6 @@ describe 'With a mocked client' do
544
596
 
545
597
  end
546
598
  ```
599
+
600
+
601
+
@@ -6,7 +6,7 @@
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "algoliasearch"
9
- s.version = "1.2.2"
9
+ s.version = "1.2.3"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
@@ -93,18 +93,6 @@ module Algolia
93
93
  return JSON.parse(response.content)
94
94
  end
95
95
 
96
- def init_session
97
- s = Curl::Easy.new
98
- s.headers[Protocol::HEADER_API_KEY] = api_key
99
- s.headers[Protocol::HEADER_APP_ID] = application_id
100
- s.headers["Content-Type"] = "application/json; charset=utf-8"
101
- s.headers["User-Agent"] = "Algolia for Ruby #{::Algolia::VERSION}"
102
- s.verbose = true if @debug
103
- s.cacert = File.join File.dirname(__FILE__), '..', '..', 'resources', 'ca-bundle.crt'
104
- s.encoding = ''
105
- s
106
- end
107
-
108
96
  end
109
97
 
110
98
  # Module methods
data/lib/algolia/index.rb CHANGED
@@ -16,6 +16,7 @@ module Algolia
16
16
  def delete
17
17
  Algolia.client.delete(Protocol.index_uri(name))
18
18
  end
19
+ alias_method :delete_index, :delete
19
20
 
20
21
  # Add an object in this index
21
22
  #
@@ -25,7 +26,7 @@ module Algolia
25
26
  # (if the attribute already exist the old object will be overridden)
26
27
  def add_object(obj, objectID = nil)
27
28
  check_object obj
28
- if objectID.nil?
29
+ if objectID.nil? || objectID.to_s.empty?
29
30
  Algolia.client.post(Protocol.index_uri(name), obj.to_json)
30
31
  else
31
32
  Algolia.client.put(Protocol.object_uri(name, objectID), obj.to_json)
@@ -232,7 +233,7 @@ module Algolia
232
233
  # @param objs an array of objects to update (each object must contains a objectID attribute)
233
234
  #
234
235
  def partial_update_objects!(objs)
235
- res = partial_update_objects(obj)
236
+ res = partial_update_objects(objs)
236
237
  wait_task(res["taskID"])
237
238
  return res
238
239
  end
@@ -276,6 +277,7 @@ module Algolia
276
277
  def clear
277
278
  Algolia.client.post(Protocol.clear_uri(name))
278
279
  end
280
+ alias_method :clear_index, :clear
279
281
 
280
282
  #
281
283
  # Delete the index content and wait end of indexing
@@ -285,6 +287,7 @@ module Algolia
285
287
  wait_task(res["taskID"])
286
288
  return res
287
289
  end
290
+ alias_method :clear_index!, :clear!
288
291
 
289
292
  #
290
293
  # Set settings for this index
@@ -40,15 +40,15 @@ module Algolia
40
40
 
41
41
  # Construct a uri referencing a given Algolia index
42
42
  def Protocol.index_uri(index)
43
- "/#{VERSION}/indexes/#{index}"
43
+ "/#{VERSION}/indexes/#{CGI.escape(index)}"
44
44
  end
45
45
 
46
46
  def Protocol.batch_uri(index)
47
- "/#{VERSION}/indexes/#{index}/batch"
47
+ "#{index_uri(index)}/batch"
48
48
  end
49
49
 
50
50
  def Protocol.index_operation_uri(index)
51
- "/#{VERSION}/indexes/#{index}/operation"
51
+ "#{index_uri(index)}/operation"
52
52
  end
53
53
 
54
54
  def Protocol.task_uri(index, task_id)
@@ -57,7 +57,7 @@ module Algolia
57
57
 
58
58
  def Protocol.object_uri(index, object_id, params = {})
59
59
  params = params.nil? || params.size == 0 ? "" : "?#{to_query(params)}"
60
- "#{index_uri(index)}/#{object_id}#{params}"
60
+ "#{index_uri(index)}/#{CGI.escape(object_id.to_s)}#{params}"
61
61
  end
62
62
 
63
63
  def Protocol.search_uri(index, query, params = {})
@@ -71,7 +71,7 @@ module Algolia
71
71
  end
72
72
 
73
73
  def Protocol.partial_object_uri(index, object_id)
74
- "#{index_uri(index)}/#{object_id}/partial"
74
+ "#{index_uri(index)}/#{CGI.escape(object_id)}/partial"
75
75
  end
76
76
 
77
77
  def Protocol.settings_uri(index)
@@ -1,3 +1,3 @@
1
1
  module Algolia
2
- VERSION = "1.2.2"
2
+ VERSION = "1.2.3"
3
3
  end
data/spec/client_spec.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
3
 
3
4
  # avoid concurrent access to the same index
@@ -7,18 +8,40 @@ def safe_index_name(name)
7
8
  "#{name}_travis-#{id}"
8
9
  end
9
10
 
11
+ def is_present(array, attr, value)
12
+ array.each do |elt|
13
+ if elt[attr] == value
14
+ return true
15
+ end
16
+ end
17
+ return false
18
+ end
19
+
10
20
  describe 'Client' do
11
21
  before(:all) do
12
- @index = Algolia::Index.new(safe_index_name("friends"))
13
- @index.delete rescue "not fatal"
22
+ @index = Algolia::Index.new(safe_index_name("àlgol?a"))
23
+ @index.delete_index rescue "not fatal"
24
+ end
25
+
26
+ after(:all) do
27
+ @index.delete_index rescue "not fatal"
14
28
  end
15
29
 
16
30
  it "should add a simple object" do
17
- @index.add_object!({ :name => "John Doe", :email => "john@doe.org" })
31
+ @index.add_object!({ :name => "John Doe", :email => "john@doe.org" }, "1")
18
32
  res = @index.search("john")
19
33
  res["hits"].length.should eq(1)
20
34
  end
21
35
 
36
+ it "should partial update a simple object" do
37
+ @index.add_object!({ :name => "John Doe", :email => "john@doe.org" }, "1")
38
+ res = @index.search("john")
39
+ res["hits"].length.should eq(1)
40
+ @index.partial_update_object!({ :name => "Robert Doe"}, "1")
41
+ res = @index.search("robert")
42
+ res["hits"].length.should eq(1)
43
+ end
44
+
22
45
  it "should add a set of objects" do
23
46
  @index.add_objects!([
24
47
  { :name => "Another", :email => "another1@example.org" },
@@ -28,6 +51,22 @@ describe 'Client' do
28
51
  res["hits"].length.should eq(2)
29
52
  end
30
53
 
54
+ it "should partial update a simple object" do
55
+ @index.add_object!({ :name => "John Doe", :email => "john@doe.org" }, "1")
56
+ @index.add_object!({ :name => "John Doe", :email => "john@doe.org" }, "2")
57
+ res = @index.search("john")
58
+ res["hits"].length.should eq(2)
59
+ @index.partial_update_objects!([{ :name => "Robert Doe", :objectID => "1"}, { :name => "Robert Doe", :objectID => "2"}])
60
+ res = @index.search("robert")
61
+ res["hits"].length.should eq(2)
62
+ end
63
+
64
+ it "should save a set of objects with their ids" do
65
+ @index.save_object!({ :name => "objectid", :email => "objectid1@example.org", :objectID => 101 })
66
+ res = @index.search("objectid")
67
+ res["hits"].length.should eq(1)
68
+ end
69
+
31
70
  it "should save a set of objects with their ids" do
32
71
  @index.save_objects!([
33
72
  { :name => "objectid", :email => "objectid1@example.org", :objectID => 101 },
@@ -55,7 +94,7 @@ describe 'Client' do
55
94
  t = Thread.new do
56
95
  10.times do
57
96
  res = @index.search("john")
58
- res["hits"].length.should eq(1)
97
+ res["hits"].length.should eq(2)
59
98
  end
60
99
  end
61
100
  threads << t
@@ -69,7 +108,7 @@ describe 'Client' do
69
108
  Process.fork do
70
109
  10.times do
71
110
  res = @index.search("john")
72
- res["hits"].length.should eq(1)
111
+ res["hits"].length.should eq(2)
73
112
  end
74
113
  end
75
114
  end
@@ -82,6 +121,124 @@ describe 'Client' do
82
121
  @index.search("")["hits"].length.should eq(0)
83
122
  end
84
123
 
124
+ it "should have another index after" do
125
+ index = Algolia::Index.new(safe_index_name("àlgol?a"))
126
+ begin
127
+ index.delete_index
128
+ sleep 4 # Dirty but temporary
129
+ rescue
130
+ # friends_2 does not exist
131
+ end
132
+ res = Algolia.list_indexes
133
+ is_present(res['items'], 'name', safe_index_name('àlgol?a')).should eq(false)
134
+ index.add_object!({ :name => "Robert" })
135
+ resAfter = Algolia.list_indexes;
136
+ is_present(resAfter['items'], 'name', safe_index_name('àlgol?a')).should eq(true)
137
+ end
138
+
139
+ it "should get a object" do
140
+ @index.clear_index
141
+ @index.add_object!({:firstname => "Robert"})
142
+ res = @index.search('')
143
+ @index.search("")["nbHits"].should eq(1)
144
+ object = @index.get_object(res['hits'][0]['objectID'])
145
+ object['firstname'].should eq('Robert')
146
+ object = @index.get_object(res['hits'][0]['objectID'], 'firstname')
147
+ object['firstname'].should eq('Robert')
148
+ end
149
+
150
+ it "should delete the object" do
151
+ @index.clear
152
+ @index.add_object!({:firstname => "Robert"})
153
+ res = @index.search('')
154
+ @index.search('')['nbHits'].should eq(1)
155
+ object = @index.delete_object!(res['hits'][0]['objectID'])
156
+ @index.search('')['nbHits'].should eq(0)
157
+ end
158
+
159
+ it "should copy the index" do
160
+ index = Algolia::Index.new(safe_index_name("àlgol?à"))
161
+ begin
162
+ @index.clear_index
163
+ index.delete_index
164
+ rescue
165
+ # friends_2 does not exist
166
+ end
167
+
168
+ @index.add_object!({:firstname => "Robert"})
169
+ @index.search('')['nbHits'].should eq(1)
170
+
171
+ Algolia.copy_index(safe_index_name("àlgol?a"), safe_index_name("àlgol?à"))
172
+ @index.delete_index
173
+
174
+ index.search('')['nbHits'].should eq(1)
175
+ index.delete_index
176
+ end
177
+
178
+ it "should move the index" do
179
+ @index.clear_index rescue "friends does not exist"
180
+ index = Algolia::Index.new(safe_index_name("àlgol?à"))
181
+ begin
182
+ index.delete_index
183
+ rescue
184
+ # friends_2 does not exist
185
+ end
186
+
187
+ @index.add_object!({:firstname => "Robert"})
188
+ @index.search('')['nbHits'].should eq(1)
189
+
190
+ Algolia.move_index(safe_index_name("àlgol?a"), safe_index_name("àlgol?à"))
191
+
192
+ index.search('')['nbHits'].should eq(1)
193
+ index.delete_index
194
+ end
195
+
196
+ it "should retrieve the object" do
197
+ @index.clear_index rescue "friends does not exist"
198
+ @index.add_object!({:firstname => "Robert"})
199
+
200
+ res = @index.browse
201
+
202
+ res['hits'].size.should eq(1)
203
+ res['hits'][0]['firstname'].should eq("Robert")
204
+ end
205
+
206
+ it "should get logs" do
207
+ res = Algolia.get_logs
208
+
209
+ res['logs'].size.should > 0
210
+ end
211
+
212
+ it "shoud accept custom batch" do
213
+ @index.clear_index! rescue "Not fatal"
214
+ request = { "requests" => [
215
+ {
216
+ "action" => "addObject",
217
+ "body" => {"firstname" => "Jimmie",
218
+ "lastname" => "Barninger"}
219
+ },
220
+ {
221
+ "action" => "addObject",
222
+ "body" => {"firstname" => "Warren",
223
+ "lastname" => "Speach"}
224
+ },
225
+ {
226
+ "action" => "updateObject",
227
+ "body" => {"firstname" => "Jimmie",
228
+ "lastname" => "Barninger",
229
+ "objectID" => "43"}
230
+ },
231
+ {
232
+ "action" => "updateObject",
233
+ "body" => {"firstname" => "Warren",
234
+ "lastname" => "Speach"},
235
+ "objectID" => "42"
236
+ }
237
+ ]}
238
+ res = @index.batch(request)
239
+ @index.search('')['nbHits'].should eq(4)
240
+ end
241
+
85
242
  it "should allow an array of tags" do
86
243
  @index.add_object!({ :name => "P1", :_tags => "t1" })
87
244
  @index.add_object!({ :name => "P2", :_tags => "t1" })
@@ -119,4 +276,279 @@ describe 'Client' do
119
276
  res['facets']['f']['f3'].should be_nil
120
277
  end
121
278
 
279
+ it "should test keys" do
280
+ resIndex = @index.list_user_keys
281
+ newIndexKey = @index.add_user_key(['search'])
282
+ newIndexKey['key'].should_not eq("")
283
+ resIndexAfter = @index.list_user_keys
284
+ resIndex['keys'].size.should eq(resIndexAfter['keys'].size - 1)
285
+ indexKey = @index.get_user_key(newIndexKey['key'])
286
+ indexKey['acl'][0].should eq('search')
287
+ @index.delete_user_key(newIndexKey['key'])
288
+ sleep 1 # Dirty but temporary
289
+ resIndexEnd = @index.list_user_keys
290
+ resIndex['keys'].size.should eq(resIndexEnd['keys'].size)
291
+
292
+
293
+ res = Algolia.list_user_keys
294
+ newKey = Algolia.add_user_key(['search'])
295
+ newKey['key'].should_not eq("")
296
+ resAfter = Algolia.list_user_keys
297
+ res['keys'].size.should eq(resAfter['keys'].size - 1)
298
+ key = Algolia.get_user_key(newKey['key'])
299
+ key['acl'][0].should eq('search')
300
+ Algolia.delete_user_key(newKey['key'])
301
+ sleep 1 # Dirty but temporary
302
+ resEnd = Algolia.list_user_keys
303
+ res['keys'].size.should eq(resEnd['keys'].size)
304
+
305
+
306
+ end
307
+
308
+ it "should check functions" do
309
+ @index.get_settings
310
+ @index.list_user_keys
311
+ Algolia.list_user_keys
312
+
313
+ end
314
+
315
+ it "should handle slash in objectId" do
316
+ @index.clear_index!()
317
+ @index.add_object!({:firstname => "Robert", :objectID => "A/go/?a"})
318
+ res = @index.search('')
319
+ @index.search("")["nbHits"].should eq(1)
320
+ object = @index.get_object(res['hits'][0]['objectID'])
321
+ object['firstname'].should eq('Robert')
322
+ object = @index.get_object(res['hits'][0]['objectID'], 'firstname')
323
+ object['firstname'].should eq('Robert')
324
+
325
+ @index.save_object!({:firstname => "George", :objectID => "A/go/?a"})
326
+ res = @index.search('')
327
+ @index.search("")["nbHits"].should eq(1)
328
+ object = @index.get_object(res['hits'][0]['objectID'])
329
+ object['firstname'].should eq('George')
330
+
331
+ @index.partial_update_object!({:firstname => "Sylvain", :objectID => "A/go/?a"})
332
+ res = @index.search('')
333
+ @index.search("")["nbHits"].should eq(1)
334
+ object = @index.get_object(res['hits'][0]['objectID'])
335
+ object['firstname'].should eq('Sylvain')
336
+
337
+ end
338
+
339
+ it "Check attributes list_indexes:" do
340
+ res = Algolia.list_indexes
341
+ res.should have_key('items')
342
+ res['items'][0].should have_key('name')
343
+ res['items'][0]['name'].should be_a(String)
344
+ res['items'][0].should have_key('createdAt')
345
+ res['items'][0]['createdAt'].should be_a(String)
346
+ res['items'][0].should have_key('updatedAt')
347
+ res['items'][0]['updatedAt'].should be_a(String)
348
+ res['items'][0].should have_key('entries')
349
+ res['items'][0]['entries'].should be_a(Integer)
350
+ res['items'][0].should have_key('pendingTask')
351
+ [true, false].should include(res['items'][0]['pendingTask'])
352
+ end
353
+
354
+ it 'Check attributes search : ' do
355
+ res = @index.search('')
356
+ res.should have_key('hits')
357
+ res['hits'].should be_a(Array)
358
+ res.should have_key('page')
359
+ res['page'].should be_a(Integer)
360
+ res.should have_key('nbHits')
361
+ res['nbHits'].should be_a(Integer)
362
+ res.should have_key('nbPages')
363
+ res['nbPages'].should be_a(Integer)
364
+ res.should have_key('hitsPerPage')
365
+ res['hitsPerPage'].should be_a(Integer)
366
+ res.should have_key('processingTimeMS')
367
+ res['processingTimeMS'].should be_a(Integer)
368
+ res.should have_key('query')
369
+ res['query'].should be_a(String)
370
+ res.should have_key('params')
371
+ res['params'].should be_a(String)
372
+ end
373
+
374
+ it 'Check attributes delete_index : ' do
375
+ index = Algolia::Index.new(safe_index_name("àlgol?à2"))
376
+ index.add_object!({ :name => "John Doe", :email => "john@doe.org" }, "1")
377
+ task = index.delete_index()
378
+ task.should have_key('deletedAt')
379
+ task['deletedAt'].should be_a(String)
380
+ task.should have_key('taskID')
381
+ task['taskID'].should be_a(Integer)
382
+ end
383
+
384
+ it 'Check attributes clear_index : ' do
385
+ task = @index.clear_index
386
+ task.should have_key('updatedAt')
387
+ task['updatedAt'].should be_a(String)
388
+ task.should have_key('taskID')
389
+ task['taskID'].should be_a(Integer)
390
+ end
391
+
392
+ it 'Check attributes add object : ' do
393
+ task = @index.add_object({ :name => "John Doe", :email => "john@doe.org" })
394
+ task.should have_key('createdAt')
395
+ task['createdAt'].should be_a(String)
396
+ task.should have_key('taskID')
397
+ task['taskID'].should be_a(Integer)
398
+ task.should have_key('objectID')
399
+ task['objectID'].should be_a(String)
400
+ end
401
+
402
+ it 'Check attributes add object id: ' do
403
+ task = @index.add_object({ :name => "John Doe", :email => "john@doe.org" }, "1")
404
+ task.should have_key('updatedAt')
405
+ task['updatedAt'].should be_a(String)
406
+ task.should have_key('taskID')
407
+ task['taskID'].should be_a(Integer)
408
+ #task.to_s.should eq("")
409
+ task.should have_key('objectID')
410
+ task['objectID'].should be_a(String)
411
+ task['objectID'].should eq("1")
412
+ end
413
+
414
+ it 'Check attributes partial update: ' do
415
+ task = @index.partial_update_object({ :name => "John Doe", :email => "john@doe.org" }, "1")
416
+ task.should have_key('updatedAt')
417
+ task['updatedAt'].should be_a(String)
418
+ task.should have_key('taskID')
419
+ task['taskID'].should be_a(Integer)
420
+ task.should have_key('objectID')
421
+ task['objectID'].should be_a(String)
422
+ task['objectID'].should eq("1")
423
+ end
424
+
425
+ it 'Check attributes delete object: ' do
426
+ @index.add_object({ :name => "John Doe", :email => "john@doe.org" }, "1")
427
+ task = @index.delete_object("1")
428
+ task.should have_key('deletedAt')
429
+ task['deletedAt'].should be_a(String)
430
+ task.should have_key('taskID')
431
+ task['taskID'].should be_a(Integer)
432
+ end
433
+
434
+ it 'Check attributes add objects: ' do
435
+ task = @index.add_objects([{ :name => "John Doe", :email => "john@doe.org", :objectID => "1" }])
436
+ task.should have_key('taskID')
437
+ task['taskID'].should be_a(Integer)
438
+ task.should have_key('objectIDs')
439
+ task['objectIDs'].should be_a(Array)
440
+ end
441
+
442
+ it 'Check attributes browse: ' do
443
+ res = @index.browse()
444
+ res.should have_key('hits')
445
+ res['hits'].should be_a(Array)
446
+ res.should have_key('page')
447
+ res['page'].should be_a(Integer)
448
+ res.should have_key('nbHits')
449
+ res['nbHits'].should be_a(Integer)
450
+ res.should have_key('nbPages')
451
+ res['nbPages'].should be_a(Integer)
452
+ res.should have_key('hitsPerPage')
453
+ res['hitsPerPage'].should be_a(Integer)
454
+ res.should have_key('processingTimeMS')
455
+ res['processingTimeMS'].should be_a(Integer)
456
+ res.should have_key('query')
457
+ res['query'].should be_a(String)
458
+ res.should have_key('params')
459
+ res['params'].should be_a(String)
460
+ end
461
+
462
+ it 'Check attributes get settings: ' do
463
+ task = @index.set_settings({})
464
+ task.should have_key('taskID')
465
+ task['taskID'].should be_a(Integer)
466
+ task.should have_key('updatedAt')
467
+ task['updatedAt'].should be_a(String)
468
+ end
469
+
470
+ it 'Check attributes move_index : ' do
471
+ index = Algolia::Index.new(safe_index_name("àlgol?à"))
472
+ index2 = Algolia::Index.new(safe_index_name("àlgol?à2"))
473
+ index2.add_object!({ :name => "John Doe", :email => "john@doe.org" }, "1")
474
+ task = Algolia.move_index(safe_index_name("àlgol?à2"), safe_index_name("àlgol?à"))
475
+ task.should have_key('updatedAt')
476
+ task['updatedAt'].should be_a(String)
477
+ task.should have_key('taskID')
478
+ task['taskID'].should be_a(Integer)
479
+ index.delete_index
480
+ end
481
+
482
+ it 'Check attributes copy_index : ' do
483
+ index = Algolia::Index.new(safe_index_name("àlgol?à"))
484
+ index2 = Algolia::Index.new(safe_index_name("àlgol?à2"))
485
+ index2.add_object!({ :name => "John Doe", :email => "john@doe.org" }, "1")
486
+ task = Algolia.copy_index(safe_index_name("àlgol?à2"), safe_index_name("àlgol?à"))
487
+ task.should have_key('updatedAt')
488
+ task['updatedAt'].should be_a(String)
489
+ task.should have_key('taskID')
490
+ task['taskID'].should be_a(Integer)
491
+ index.delete_index
492
+ index2.delete_index
493
+ end
494
+
495
+ it 'Check attributes wait_task : ' do
496
+ task = @index.add_object!({ :name => "John Doe", :email => "john@doe.org" }, "1")
497
+ task = Algolia.client.get(Algolia::Protocol.task_uri(safe_index_name("àlgol?a"), task['objectID']))
498
+ task.should have_key('status')
499
+ task['status'].should be_a(String)
500
+ task.should have_key('pendingTask')
501
+ [true, false].should include(task['pendingTask'])
502
+ end
503
+
504
+ it "Check add keys" do
505
+ newIndexKey = @index.add_user_key(['search'])
506
+ newIndexKey.should have_key('key')
507
+ newIndexKey['key'].should be_a(String)
508
+ newIndexKey.should have_key('createdAt')
509
+ newIndexKey['createdAt'].should be_a(String)
510
+ resIndex = @index.list_user_keys
511
+ resIndex.should have_key('keys')
512
+ resIndex['keys'].should be_a(Array)
513
+ resIndex['keys'][0].should have_key('value')
514
+ resIndex['keys'][0]['value'].should be_a(String)
515
+ resIndex['keys'][0].should have_key('acl')
516
+ resIndex['keys'][0]['acl'].should be_a(Array)
517
+ resIndex['keys'][0].should have_key('validity')
518
+ resIndex['keys'][0]['validity'].should be_a(Integer)
519
+ indexKey = @index.get_user_key(newIndexKey['key'])
520
+ indexKey.should have_key('value')
521
+ indexKey['value'].should be_a(String)
522
+ indexKey.should have_key('acl')
523
+ indexKey['acl'].should be_a(Array)
524
+ indexKey.should have_key('validity')
525
+ indexKey['validity'].should be_a(Integer)
526
+ task = @index.delete_user_key(newIndexKey['key'])
527
+ task.should have_key('deletedAt')
528
+ task['deletedAt'].should be_a(String)
529
+ end
530
+
531
+ it 'Check attributes log : ' do
532
+ logs = Algolia.get_logs()
533
+ logs.should have_key('logs')
534
+ logs['logs'].should be_a(Array)
535
+ logs['logs'][0].should have_key('timestamp')
536
+ logs['logs'][0]['timestamp'].should be_a(String)
537
+ logs['logs'][0].should have_key('method')
538
+ logs['logs'][0]['method'].should be_a(String)
539
+ logs['logs'][0].should have_key('answer_code')
540
+ logs['logs'][0]['answer_code'].should be_a(String)
541
+ logs['logs'][0].should have_key('query_body')
542
+ logs['logs'][0]['query_body'].should be_a(String)
543
+ logs['logs'][0].should have_key('answer')
544
+ logs['logs'][0]['answer'].should be_a(String)
545
+ logs['logs'][0].should have_key('url')
546
+ logs['logs'][0]['url'].should be_a(String)
547
+ logs['logs'][0].should have_key('ip')
548
+ logs['logs'][0]['ip'].should be_a(String)
549
+ logs['logs'][0].should have_key('query_headers')
550
+ logs['logs'][0]['query_headers'].should be_a(String)
551
+ logs['logs'][0].should have_key('sha1')
552
+ logs['logs'][0]['sha1'].should be_a(String)
553
+ end
122
554
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,14 @@
1
+
2
+ if ENV['COVERAGE']
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+ end
6
+
7
+ if ENV['TRAVIS'] && RUBY_ENGINE == "ruby"
8
+ require 'coveralls'
9
+ Coveralls.wear!
10
+ end
11
+
1
12
  require 'rubygems'
2
13
  Bundler.setup :test
3
14
 
metadata CHANGED
@@ -1,74 +1,94 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: algoliasearch
3
- version: !ruby/object:Gem::Version
4
- version: 1.2.2
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.3
5
5
  platform: ruby
6
- authors:
6
+ authors:
7
7
  - Algolia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
-
12
- date: 2014-01-11 00:00:00 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
11
+ date: 2014-01-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
15
14
  name: httpclient
16
- prerelease: false
17
- requirement: &id001 !ruby/object:Gem::Requirement
18
- requirements:
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
19
17
  - - ~>
20
- - !ruby/object:Gem::Version
21
- version: "2.3"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.3'
22
20
  type: :runtime
23
- version_requirements: *id001
24
- - !ruby/object:Gem::Dependency
25
- name: json
26
21
  prerelease: false
27
- requirement: &id002 !ruby/object:Gem::Requirement
28
- requirements:
29
- - - ">="
30
- - !ruby/object:Gem::Version
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '2.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
31
33
  version: 1.5.1
32
34
  type: :runtime
33
- version_requirements: *id002
34
- - !ruby/object:Gem::Dependency
35
- name: travis
36
35
  prerelease: false
37
- requirement: &id003 !ruby/object:Gem::Requirement
38
- requirements:
39
- - &id004
40
- - ">="
41
- - !ruby/object:Gem::Version
42
- version: "0"
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.5.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: travis
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
43
48
  type: :development
44
- version_requirements: *id003
45
- - !ruby/object:Gem::Dependency
46
- name: rake
47
49
  prerelease: false
48
- requirement: &id005 !ruby/object:Gem::Requirement
49
- requirements:
50
- - *id004
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
51
62
  type: :development
52
- version_requirements: *id005
53
- - !ruby/object:Gem::Dependency
54
- name: rdoc
55
63
  prerelease: false
56
- requirement: &id006 !ruby/object:Gem::Requirement
57
- requirements:
58
- - *id004
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rdoc
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
59
76
  type: :development
60
- version_requirements: *id006
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
61
83
  description: A simple Ruby client for the algolia.com REST API
62
84
  email: contact@algolia.com
63
85
  executables: []
64
-
65
86
  extensions: []
66
-
67
- extra_rdoc_files:
87
+ extra_rdoc_files:
68
88
  - ChangeLog
69
89
  - LICENSE.txt
70
90
  - README.md
71
- files:
91
+ files:
72
92
  - .rspec
73
93
  - .travis.yml
74
94
  - ChangeLog
@@ -92,27 +112,27 @@ files:
92
112
  - spec/spec_helper.rb
93
113
  - spec/stub_spec.rb
94
114
  homepage: http://github.com/algolia/algoliasearch-client-ruby
95
- licenses:
115
+ licenses:
96
116
  - MIT
97
117
  metadata: {}
98
-
99
118
  post_install_message:
100
119
  rdoc_options: []
101
-
102
- require_paths:
120
+ require_paths:
103
121
  - lib
104
- required_ruby_version: !ruby/object:Gem::Requirement
105
- requirements:
106
- - *id004
107
- required_rubygems_version: !ruby/object:Gem::Requirement
108
- requirements:
109
- - *id004
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
110
132
  requirements: []
111
-
112
133
  rubyforge_project:
113
- rubygems_version: 2.2.1
134
+ rubygems_version: 2.1.11
114
135
  signing_key:
115
136
  specification_version: 4
116
137
  summary: A simple Ruby client for the algolia.com REST API
117
138
  test_files: []
118
-