algoliasearch 1.6.1 → 1.7.0
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 +4 -4
- data/ChangeLog +3 -0
- data/README.md +97 -62
- data/lib/algolia/client.rb +17 -5
- data/lib/algolia/version.rb +1 -1
- data/spec/client_spec.rb +13 -1
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 09439a03773ded1c14b3085d75beca0fcd8ad5ea
         | 
| 4 | 
            +
              data.tar.gz: 0afd459775b461e96b952540f2889a54c7b8a9c6
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: b1cb21a4b0382bf44a5319d4060a816300c53a14c43db82b5e21b89a607650b6f9bbc3e0bf02c5227c2e20488333593d630e4ac5834c0f4a520c346c5aa0c14a
         | 
| 7 | 
            +
              data.tar.gz: 65e765e1557b807f380f010c1ac2548a804e9fae494003dbb8b151bc187dd4ff9bfddff3628d8828be756ea49893b003ce5cb1b4cdee0cb91e95747f526694c3
         | 
    
        data/ChangeLog
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -3,11 +3,14 @@ | |
| 3 3 |  | 
| 4 4 |  | 
| 5 5 |  | 
| 6 | 
            +
             | 
| 6 7 | 
             
            [Algolia Search](http://www.algolia.com) is a hosted full-text, numerical, and faceted search engine capable of delivering realtime results from the first keystroke.
         | 
| 7 8 |  | 
| 8 9 | 
             
            Our Ruby client lets you easily use the [Algolia Search API](https://www.algolia.com/doc/rest_api) from your backend. It wraps the [Algolia Search REST API](http://www.algolia.com/doc/rest_api).
         | 
| 9 10 |  | 
| 10 11 |  | 
| 12 | 
            +
             | 
| 13 | 
            +
             | 
| 11 14 | 
             
            [](https://travis-ci.org/algolia/algoliasearch-client-ruby) [](http://badge.fury.io/rb/algoliasearch) [](https://codeclimate.com/github/algolia/algoliasearch-client-ruby) [](https://coveralls.io/r/algolia/algoliasearch-client-ruby)
         | 
| 12 15 |  | 
| 13 16 |  | 
| @@ -22,6 +25,7 @@ Table of Contents | |
| 22 25 | 
             
            1. [Online documentation](#documentation)
         | 
| 23 26 | 
             
            1. [Tutorials](#tutorials)
         | 
| 24 27 |  | 
| 28 | 
            +
             | 
| 25 29 | 
             
            **Commands Reference**
         | 
| 26 30 |  | 
| 27 31 | 
             
            1. [Add a new object](#add-a-new-object-to-the-index)
         | 
| @@ -51,7 +55,6 @@ To setup your project, follow these steps: | |
| 51 55 |  | 
| 52 56 |  | 
| 53 57 |  | 
| 54 | 
            -
             | 
| 55 58 | 
             
             1. Install AlgoliaSearch using <code>gem install algoliasearch</code>.
         | 
| 56 59 | 
             
             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).
         | 
| 57 60 |  | 
| @@ -173,6 +176,7 @@ Check out our [tutorials](http://www.algolia.com/doc/tutorials): | |
| 173 176 |  | 
| 174 177 |  | 
| 175 178 |  | 
| 179 | 
            +
             | 
| 176 180 | 
             
            Commands Reference
         | 
| 177 181 | 
             
            ==================
         | 
| 178 182 |  | 
| @@ -226,9 +230,9 @@ index.save_object({"firstname" => "Jimmie", | |
| 226 230 | 
             
            You have many ways to update an object's attributes:
         | 
| 227 231 |  | 
| 228 232 | 
             
             1. Set the attribute value
         | 
| 229 | 
            -
             2. Add  | 
| 233 | 
            +
             2. Add a string or number element to an array
         | 
| 230 234 | 
             
             3. Remove an element from an array
         | 
| 231 | 
            -
             4. Add  | 
| 235 | 
            +
             4. Add a string or number element to an array if it doesn't exist
         | 
| 232 236 | 
             
             5. Increment an attribute
         | 
| 233 237 | 
             
             6. Decrement an attribute
         | 
| 234 238 |  | 
| @@ -242,38 +246,44 @@ index.partial_update_object({"city" => "San Francisco", | |
| 242 246 | 
             
            Example to add a tag:
         | 
| 243 247 |  | 
| 244 248 | 
             
            ```ruby
         | 
| 245 | 
            -
            index.partial_update_object({"_tags" => {"value" => "MyTag", "_operation" | 
| 249 | 
            +
            index.partial_update_object({"_tags" => {"value" => "MyTag", "_operation" => "Add"},
         | 
| 246 250 | 
             
                                         "objectID" => "myID"})
         | 
| 247 251 | 
             
            ```
         | 
| 248 252 |  | 
| 249 253 | 
             
            Example to remove a tag:
         | 
| 250 254 |  | 
| 251 255 | 
             
            ```ruby
         | 
| 252 | 
            -
            index.partial_update_object({"_tags" => {"value" => "MyTag", "_operation" | 
| 256 | 
            +
            index.partial_update_object({"_tags" => {"value" => "MyTag", "_operation" => "Remove"},
         | 
| 253 257 | 
             
                                         "objectID" => "myID"})
         | 
| 254 258 | 
             
            ```
         | 
| 255 259 |  | 
| 256 260 | 
             
            Example to add a tag if it doesn't exist:
         | 
| 257 261 |  | 
| 258 262 | 
             
            ```ruby
         | 
| 259 | 
            -
            index.partial_update_object({"_tags" => {"value" => "MyTag", "_operation" | 
| 263 | 
            +
            index.partial_update_object({"_tags" => {"value" => "MyTag", "_operation" => "AddUnique"},
         | 
| 260 264 | 
             
                                         "objectID" => "myID"})
         | 
| 261 265 | 
             
            ```
         | 
| 262 266 |  | 
| 263 267 | 
             
            Example to increment a numeric value:
         | 
| 264 268 |  | 
| 265 269 | 
             
            ```ruby
         | 
| 266 | 
            -
            index.partial_update_object({"price" => {"value" => 42, "_operation" | 
| 270 | 
            +
            index.partial_update_object({"price" => {"value" => 42, "_operation" => "Increment"},
         | 
| 267 271 | 
             
                                         "objectID" => "myID"})
         | 
| 268 272 | 
             
            ```
         | 
| 269 273 |  | 
| 274 | 
            +
            Note: Here we are incrementing the value by `42`. To increment just by one, put
         | 
| 275 | 
            +
            `value:1`.
         | 
| 276 | 
            +
             | 
| 270 277 | 
             
            Example to decrement a numeric value:
         | 
| 271 278 |  | 
| 272 279 | 
             
            ```ruby
         | 
| 273 | 
            -
            index.partial_update_object({"price" => {"value" => 42, "_operation" | 
| 280 | 
            +
            index.partial_update_object({"price" => {"value" => 42, "_operation" => "Decrement"},
         | 
| 274 281 | 
             
                                         "objectID" => "myID"})
         | 
| 275 282 | 
             
            ```
         | 
| 276 283 |  | 
| 284 | 
            +
            Note: Here we are decrementing the value by `42`. To decrement just by one, put
         | 
| 285 | 
            +
            `value:1`.
         | 
| 286 | 
            +
             | 
| 277 287 | 
             
            Search
         | 
| 278 288 | 
             
            -------------
         | 
| 279 289 |  | 
| @@ -284,6 +294,8 @@ Search | |
| 284 294 |  | 
| 285 295 | 
             
            To perform a search, you only need to initialize the index and perform a call to the search function.
         | 
| 286 296 |  | 
| 297 | 
            +
            The search query allows only to retrieve 1000 hits, if you need to retrieve more than 1000 hits for seo, you can use [Backup / Retrieve all index content](#backup--retrieve-of-all-index-content)
         | 
| 298 | 
            +
             | 
| 287 299 | 
             
            You can use the following optional arguments:
         | 
| 288 300 |  | 
| 289 301 | 
             
            ### Query Parameters
         | 
| @@ -298,7 +310,7 @@ You can use the following optional arguments: | |
| 298 310 | 
             
             * **removeWordsIfNoResults**: This option is used to select a strategy in order to avoid having an empty result page. There are three different options:
         | 
| 299 311 | 
             
              * **lastWords**: When a query does not return any results, the last word will be added as optional. The process is repeated with n-1 word, n-2 word, ... until there are results.
         | 
| 300 312 | 
             
              * **firstWords**: When a query does not return any results, the first word will be added as optional. The process is repeated with second word, third word, ... until there are results.
         | 
| 301 | 
            -
              * **allOptional**: When a query does not return any results, a second trial will be made with all words as optional. This is equivalent to transforming the AND operand between query terms to an OR operand. | 
| 313 | 
            +
              * **allOptional**: When a query does not return any results, a second trial will be made with all words as optional. This is equivalent to transforming the AND operand between query terms to an OR operand.
         | 
| 302 314 | 
             
              * **none**: No specific processing is done when a query does not return any results (default behavior).
         | 
| 303 315 | 
             
             * **minWordSizefor1Typo**: The minimum number of characters in a query word to accept one typo in this word.<br/>Defaults to 4.
         | 
| 304 316 | 
             
             * **minWordSizefor2Typos**: The minimum number of characters in a query word to accept two typos in this word.<br/>Defaults to 8.
         | 
| @@ -310,7 +322,9 @@ You can use the following optional arguments: | |
| 310 322 | 
             
              * **strict**: Hits matching with 2 typos are not retrieved if there are some matching without typos. This option is useful if you want to avoid false positives as much as possible.
         | 
| 311 323 | 
             
             * **allowTyposOnNumericTokens**: If set to false, disables typo tolerance on numeric tokens (numbers). Defaults to true.
         | 
| 312 324 | 
             
             * **ignorePlural**: If set to true, plural won't be considered as a typo. For example, car and cars will be considered as equals. Defaults to false.
         | 
| 325 | 
            +
             * **disableTypoToleranceOnAttributes** List of attributes on which you want to disable typo tolerance (must be a subset of the `attributesToIndex` index setting). Attributes are separated with a comma such as `"name,address"`. You can also use JSON string array encoding such as `encodeURIComponent("[\"name\",\"address\"]")`. By default, this list is empty.
         | 
| 313 326 | 
             
             * **restrictSearchableAttributes** List of attributes you want to use for textual search (must be a subset of the `attributesToIndex` index setting). Attributes are separated with a comma such as `"name,address"`. You can also use JSON string array encoding such as `encodeURIComponent("[\"name\",\"address\"]")`. By default, all attributes specified in `attributesToIndex` settings are used to search.
         | 
| 327 | 
            +
             * **removeStopWords**: Remove stop words from query before executing it. Defaults to false. Contains stop words for 41 languages (Arabic, Armenian, Basque, Bengali, Brazilian, Bulgarian, Catalan, Chinese, Czech, Danish, Dutch, English, Finnish, French, Galician, German, Greek, Hindi, Hungarian, Indonesian, Irish, Italian, Japanese, Korean, Kurdish, Latvian, Lithuanian, Marathi, Norwegian, Persian, Polish, Portugese, Romanian, Russian, Slovak, Spanish, Swedish, Thai, Turkish, Ukranian, Urdu).
         | 
| 314 328 | 
             
             * **advancedSyntax**: Enables the advanced query syntax. Defaults to 0 (false).
         | 
| 315 329 | 
             
                * **Phrase query**: A phrase query defines a particular sequence of terms. A phrase query is built by Algolia's query parser for words surrounded by `"`. For example, `"search engine"` will retrieve records having `search` next to `engine` only. Typo tolerance is _disabled_ on phrase queries.
         | 
| 316 330 | 
             
                * **Prohibit operator**: The prohibit operator excludes records that contain the term after the `-` symbol. For example, `search -engine` will retrieve records containing `search` but not `engine`.
         | 
| @@ -326,12 +340,12 @@ You can use the following optional arguments: | |
| 326 340 |  | 
| 327 341 | 
             
            #### Geo-search Parameters
         | 
| 328 342 |  | 
| 329 | 
            -
             * **aroundLatLng**: Search for entries around a given latitude/longitude (specified as two floats separated by a comma).<br/>For example, `aroundLatLng=47.316669,5.016670`.<br/> | 
| 330 | 
            -
             | 
| 331 | 
            -
             * **aroundLatLngViaIP**: Search for entries around a given latitude/longitude automatically computed from user IP address.<br/>For example, `aroundLatLng=47.316669,5.016670`.<br/>You can specify the maximum distance in meters with the **aroundRadius** parameter and the precision for ranking with **aroundPrecision**. For example, if you set aroundPrecision=100, two objects that are a distance of less than 100 meters will be considered as identical for the "geo" ranking parameter.<br/>At indexing, you should specify the geo location of an object with the `_geoloc` attribute in the form `{"_geoloc":{"lat":48.853409, "lng":2.348800}}`.
         | 
| 343 | 
            +
             * **aroundLatLng**: Search for entries around a given latitude/longitude (specified as two floats separated by a comma).<br/>For example, `aroundLatLng=47.316669,5.016670`.<br/>By default the maximum distance is automatically guessed based on the density of the area but you can specify it manually in meters with the **aroundRadius** parameter. The precision for ranking can be set with **aroundPrecision** parameter. For example, if you set aroundPrecision=100, the distances will be considered by ranges of 100m, for example all distances 0 and 100m will be considered as identical for the "geo" ranking parameter.<br/>When **aroundRadius** is not set, the radius is computed automatically using the density of the area, you can retrieve the computed radius in the **automaticRadius** attribute of the answer, you can also use the **minimumAroundRadius** query parameter to specify a minimum radius in meters for the automatic computation of **aroundRadius**.<br/>At indexing, you should specify geoloc of an object with the _geoloc attribute (in the form `"_geoloc":{"lat":48.853409, "lng":2.348800}` or `"_geoloc":[{"lat":48.853409, "lng":2.348800},{"lat":48.547456, "lng":2.972075}]` if you have several geo-locations in your record).
         | 
| 332 344 |  | 
| 345 | 
            +
             * **aroundLatLngViaIP**: Search for entries around a given latitude/longitude automatically computed from user IP address.<br/>For example, `aroundLatLng=47.316669,5.016670`.<br/>You can specify the maximum distance in meters with the **aroundRadius** parameter and the precision for ranking with **aroundPrecision**. For example, if you set aroundPrecision=100, two objects that are in the range 0-99m will be considered as identic in the ranking for the "geo" ranking parameter (same for 100-199, 200-299, ... ranges).<br/>At indexing, you should specify the geo location of an object with the `_geoloc` attribute in the form `{"_geoloc":{"lat":48.853409, "lng":2.348800}}`.
         | 
| 333 346 |  | 
| 334 | 
            -
             * **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  | 
| 347 | 
            +
             * **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}` or `"_geoloc":[{"lat":48.853409, "lng":2.348800},{"lat":48.547456, "lng":2.972075}]` if you have several geo-locations in your record). You can use several bounding boxes (OR) by passing more than 4 values. For example instead of having 4 values you can pass 8 to use or OR between two bounding boxes.
         | 
| 348 | 
            +
             * **insidePolygon**: Search entries inside a given area defined by a set of points (defined by a minimum of 6 floats: p1Lat,p1Lng,p2Lat,p2Lng,p3Lat,p3Long).<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}` or `"_geoloc":[{"lat":48.853409, "lng":2.348800},{"lat":48.547456, "lng":2.972075}]` if you have several geo-locations in your record).
         | 
| 335 349 |  | 
| 336 350 | 
             
            #### Parameters to Control Results Content
         | 
| 337 351 |  | 
| @@ -342,6 +356,8 @@ You can use the following optional arguments: | |
| 342 356 | 
             
              * **none**: If none of the query terms were found.
         | 
| 343 357 | 
             
             * **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 commas (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.
         | 
| 344 358 | 
             
             * **getRankingInfo**: If set to 1, the result hits will contain ranking information in the **_rankingInfo** attribute.
         | 
| 359 | 
            +
             * **highlightPreTag**: (string) Specify the string that is inserted before the highlighted parts in the query result (defaults to "<em>").
         | 
| 360 | 
            +
             * **highlightPostTag**: (string) Specify the string that is inserted after the highlighted parts in the query result (defaults to "</em>").
         | 
| 345 361 |  | 
| 346 362 |  | 
| 347 363 | 
             
            #### Numeric Search Parameters
         | 
| @@ -358,12 +374,29 @@ You can also use a string array encoding (for example `numericFilters: ["price>1 | |
| 358 374 |  | 
| 359 375 | 
             
            #### Faceting Parameters
         | 
| 360 376 | 
             
             * **facetFilters**: Filter the query with a list of facets. Facets are separated by commas and 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"]`.
         | 
| 361 | 
            -
             * **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 JSON string array encoding. For example, `["category","author"]`. Only the 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**.
         | 
| 377 | 
            +
             * **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 JSON string array encoding. For example, `["category","author"]`. Only the 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**. If the number of results is important, the count can be approximate, the attribute `exhaustiveFacetsCount` in the response is true when the count is exact.
         | 
| 362 378 | 
             
             * **maxValuesPerFacet**: Limit the number of facet values returned for each facet. For example, `maxValuesPerFacet=10` will retrieve a maximum of 10 values per facet.
         | 
| 363 379 |  | 
| 380 | 
            +
            #### UNIFIED FILTER PARAMETER (SQL LIKE)
         | 
| 381 | 
            +
             * **filters**: Filter the query with numeric, facet or/and tag filters. The syntax is a SQL like syntax, you can use the OR and AND keywords. The syntax for the underlying numeric, facet and tag filters is the same than in the other filters:
         | 
| 382 | 
            +
              `available=1 AND (category:Book OR NOT category:Ebook) AND public`
         | 
| 383 | 
            +
              `date: 1441745506 TO 1441755506 AND inStock > 0 AND author:"John Doe"`
         | 
| 384 | 
            +
            The list of keywords is:
         | 
| 385 | 
            +
             **OR**: create a disjunctive filter between two filters.
         | 
| 386 | 
            +
             **AND**: create a conjunctive filter between two filters.
         | 
| 387 | 
            +
             **TO**: used to specify a range for a numeric filter.
         | 
| 388 | 
            +
             **NOT**: used to negate a filter. The syntax with the ‘-‘ isn’t allowed.
         | 
| 389 | 
            +
             | 
| 390 | 
            +
             *Note*: To specify a value with spaces or with a value equal to a keyword, it's possible to add quotes.
         | 
| 391 | 
            +
             | 
| 392 | 
            +
             **Warning:**
         | 
| 393 | 
            +
              * Like for the other filter for performance reason, it's not possible to have FILTER1 OR (FILTER2 AND FILTER3).
         | 
| 394 | 
            +
              * It's not possible to mix different category of filter inside a OR like num=3 OR tag1 OR facet:value
         | 
| 395 | 
            +
              * It's not possible to negate an group, it's only possible to negate a filters:  NOT(FILTER1 OR (FILTER2) is not allowed.
         | 
| 396 | 
            +
             | 
| 397 | 
            +
             | 
| 364 398 | 
             
            #### Distinct Parameter
         | 
| 365 399 | 
             
             * **distinct**: If set to 1, enables the distinct feature, disabled by default, if the `attributeForDistinct` index setting is set. This feature is similar to the SQL "distinct" keyword. When enabled in a query with the `distinct=1` parameter, all hits containing a duplicate value for the attributeForDistinct attribute are removed from results. For example, if the chosen attribute is `show_name` and several hits have the same value for `show_name`, then only the best one is kept and the others are removed.
         | 
| 366 | 
            -
            **Note**: This feature is disabled if the query string is empty and there aren't any `tagFilters`, `facetFilters`, nor `numericFilters` parameters.
         | 
| 367 400 |  | 
| 368 401 | 
             
            ```ruby
         | 
| 369 402 | 
             
            index = Algolia::Index.new("contacts")
         | 
| @@ -407,6 +440,9 @@ The server response will look like: | |
| 407 440 | 
             
            ```
         | 
| 408 441 |  | 
| 409 442 |  | 
| 443 | 
            +
             | 
| 444 | 
            +
             | 
| 445 | 
            +
             | 
| 410 446 | 
             
            Multiple queries
         | 
| 411 447 | 
             
            --------------
         | 
| 412 448 |  | 
| @@ -485,7 +521,7 @@ You can retrieve all settings using the `get_settings` function. The result will | |
| 485 521 | 
             
            You can decide to have the same priority for two attributes by passing them in the same string using a comma as a separator. For example `title` and `alternative_title` have the same priority in this example, which is different than text priority: `attributesToIndex:["title,alternative_title", "text"]`.
         | 
| 486 522 | 
             
            * **numericAttributesToIndex**: (array of strings) All numerical attributes are automatically indexed as numerical filters. If you don't need filtering on some of your numerical attributes, you can specify this list to speed up the indexing.<br/> If you only need to filter on a numeric value with the operator '=', you can speed up the indexing by specifying the attribute with `equalOnly(AttributeName)`. The other operators will be disabled.
         | 
| 487 523 | 
             
             * **attributesForFaceting**: (array of strings) The list of fields you want to use for faceting. All strings in the attribute selected for faceting are extracted and added as a facet. If set to null, no attribute is used for faceting.
         | 
| 488 | 
            -
             * **attributeForDistinct**: The attribute name used for the `Distinct` feature. This feature is similar to the SQL "distinct" keyword. When enabled in queries with the `distinct=1` parameter, all hits containing a duplicate value for this attribute are removed from results. For example, if the chosen attribute is `show_name` and several hits have the same value for `show_name`, then only the best one is kept and others are removed. | 
| 524 | 
            +
             * **attributeForDistinct**: The attribute name used for the `Distinct` feature. This feature is similar to the SQL "distinct" keyword. When enabled in queries with the `distinct=1` parameter, all hits containing a duplicate value for this attribute are removed from results. For example, if the chosen attribute is `show_name` and several hits have the same value for `show_name`, then only the best one is kept and others are removed.
         | 
| 489 525 | 
             
             * **ranking**: (array of strings) Controls the way results are sorted.<br/>We have nine available criteria:
         | 
| 490 526 | 
             
              * **typo**: Sort according to number of typos.
         | 
| 491 527 | 
             
              * **geo**: Sort according to decreasing distance when performing a geo location based search.
         | 
| @@ -513,7 +549,8 @@ You can decide to have the same priority for two attributes by passing them in t | |
| 513 549 | 
             
             * **placeholders**: (hash of array of words). This is an advanced use case to define a token substitutable by a list of words without having the original token searchable. It is defined by a hash associating placeholders to lists of substitutable words. For example, `"placeholders": { "<streetnumber>": ["1", "2", "3", ..., "9999"]}` would allow it to be able to match all street numbers. We use the `< >` tag syntax to define placeholders in an attribute. For example:
         | 
| 514 550 | 
             
              * Push a record with the placeholder: `{ "name" : "Apple Store", "address" : "<streetnumber> Opera street, Paris" }`.
         | 
| 515 551 | 
             
              * Configure the placeholder in your index settings: `"placeholders": { "<streetnumber>" : ["1", "2", "3", "4", "5", ... ], ... }`.
         | 
| 516 | 
            -
             * ** | 
| 552 | 
            +
             * **disableTypoToleranceOnWords**: (string array) Specify a list of words on which automatic typo tolerance will be disabled.
         | 
| 553 | 
            +
             * **disableTypoToleranceOnAttributes**: (string array) List of attributes on which you want to disable typo tolerance (must be a subset of the `attributesToIndex` index setting). By default the list is empty.
         | 
| 517 554 | 
             
             * **altCorrections**: (object array) Specify alternative corrections that you want to consider. Each alternative correction is described by an object containing three attributes:
         | 
| 518 555 | 
             
              * **word**: The word to correct.
         | 
| 519 556 | 
             
              * **correction**: The corrected word.
         | 
| @@ -531,6 +568,26 @@ You can decide to have the same priority for two attributes by passing them in t | |
| 531 568 | 
             
             * **highlightPreTag**: (string) Specify the string that is inserted before the highlighted parts in the query result (defaults to "<em>").
         | 
| 532 569 | 
             
             * **highlightPostTag**: (string) Specify the string that is inserted after the highlighted parts in the query result (defaults to "</em>").
         | 
| 533 570 | 
             
             * **optionalWords**: (array of strings) Specify a list of words that should be considered optional when found in the query.
         | 
| 571 | 
            +
             * **allowTyposOnNumericTokens**: (boolean) If set to false, disable typo-tolerance on numeric tokens (=numbers) in the query word. For example the query `"304"` will match with `"30450"`, but not with `"40450"` that would have been the case with typo-tolerance enabled. Can be very useful on serial numbers and zip codes searches. Default to false.
         | 
| 572 | 
            +
             * **ignorePlurals**: (boolean) If set to true, simple plural forms won’t be considered as typos (for example car/cars will be considered as equal). Default to false.
         | 
| 573 | 
            +
             * **advancedSyntax**: Enable the advanced query syntax. Defaults to 0 (false).
         | 
| 574 | 
            +
             | 
| 575 | 
            +
              * **Phrase query:** a phrase query defines a particular sequence of terms. A phrase query is build by Algolia's query parser for words surrounded by `"`. For example, `"search engine"` will retrieve records having `search` next to `engine` only. Typo-tolerance is disabled on phrase queries.
         | 
| 576 | 
            +
              
         | 
| 577 | 
            +
              * **Prohibit operator:** The prohibit operator excludes records that contain the term after the `-` symbol. For example `search -engine` will retrieve records containing `search` but not `engine`.
         | 
| 578 | 
            +
             * **replaceSynonymsInHighlight**: (boolean) If set to false, words matched via synonyms expansion will not be replaced by the matched synonym in the highlighted result. Default to true.
         | 
| 579 | 
            +
             * **maxValuesPerFacet**: (integer) Limit the number of facet values returned for each facet. For example: `maxValuesPerFacet=10` will retrieve max 10 values per facet.
         | 
| 580 | 
            +
             * **distinct**: (integer) Enable the distinct feature (disabled by default) if the `attributeForDistinct` index setting is set. This feature is similar to the SQL "distinct" keyword: when enabled in a query with the `distinct=1` parameter, all hits containing a duplicate value for the`attributeForDistinct` attribute are removed from results. For example, if the chosen attribute is `show_name` and several hits have the same value for `show_name`, then only the best one is kept and others are removed.
         | 
| 581 | 
            +
             * **typoTolerance**: (string) This setting has four different options:
         | 
| 582 | 
            +
             | 
| 583 | 
            +
              * **true:** activate the typo-tolerance (default value).
         | 
| 584 | 
            +
             | 
| 585 | 
            +
              * **false:** disable the typo-tolerance
         | 
| 586 | 
            +
             | 
| 587 | 
            +
              * **min:** keep only results with the lowest number of typo. For example if one result match without typos, then all results with typos will be hidden.
         | 
| 588 | 
            +
             | 
| 589 | 
            +
              * **strict:** if there is a match without typo, then all results with 2 typos or more will be removed. This option is useful if you want to avoid as much as possible false positive.
         | 
| 590 | 
            +
             * **removeStopWords**: (boolean) Remove stop words from query before executing it. Defaults to false. Contains stop words for 41 languages (Arabic, Armenian, Basque, Bengali, Brazilian, Bulgarian, Catalan, Chinese, Czech, Danish, Dutch, English, Finnish, French, Galician, German, Greek, Hindi, Hungarian, Indonesian, Irish, Italian, Japanese, Korean, Kurdish, Latvian, Lithuanian, Marathi, Norwegian, Persian, Polish, Portugese, Romanian, Russian, Slovak, Spanish, Swedish, Thai, Turkish, Ukranian, Urdu)
         | 
| 534 591 |  | 
| 535 592 | 
             
            You can easily retrieve settings or update them:
         | 
| 536 593 |  | 
| @@ -594,7 +651,7 @@ Batch writes | |
| 594 651 | 
             
            -------------
         | 
| 595 652 |  | 
| 596 653 | 
             
            You may want to perform multiple operations with one API call to reduce latency.
         | 
| 597 | 
            -
            We expose  | 
| 654 | 
            +
            We expose four methods to perform batch operations:
         | 
| 598 655 | 
             
             * `add_objects`: Add an array of objects using automatic `objectID` assignment.
         | 
| 599 656 | 
             
             * `save_objects`: Add or update an array of objects that contains an `objectID` attribute.
         | 
| 600 657 | 
             
             * `delete_objects`: Delete an array of objectIDs.
         | 
| @@ -688,17 +745,17 @@ puts res['key'] | |
| 688 745 |  | 
| 689 746 | 
             
            You can also create an API Key with advanced settings:
         | 
| 690 747 |  | 
| 691 | 
            -
             * Add a validity period. The key will be valid for a specific period of time (in seconds).
         | 
| 692 | 
            -
             * 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 source 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 index contents by massively querying the index.
         | 
| 748 | 
            +
             * **validity**: Add a validity period. The key will be valid for a specific period of time (in seconds).
         | 
| 749 | 
            +
             * **maxQueriesPerIPPerHour**: 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 source 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 index contents by massively querying the index.
         | 
| 693 750 |  | 
| 694 751 |  | 
| 695 752 | 
             
              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.
         | 
| 696 753 |  | 
| 697 | 
            -
             * 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 index contents by massively querying the index.
         | 
| 698 | 
            -
             * Specify the list of targeted indices. You can target all indices starting with a prefix or ending with a suffix using the ' | 
| 699 | 
            -
             * Specify the list of referers. You can target all referers starting with a prefix or ending with a suffix using the ' | 
| 700 | 
            -
             * Specify the list of query parameters. You can force the query parameters for a query using the url string format (param1=X¶m2=Y...).
         | 
| 701 | 
            -
             * Specify a description to describe where the key is used.
         | 
| 754 | 
            +
             * **maxHitsPerQuery**: 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 index contents by massively querying the index.
         | 
| 755 | 
            +
             * **indexes**: Specify the list of targeted indices. You can target all indices starting with a prefix or ending with a suffix using the '\*' character. For example, "dev\_\*" matches all indices starting with "dev\_" and "\*\_dev" matches all indices ending with "\_dev". Defaults to all indices if empty or blank.
         | 
| 756 | 
            +
             * **referers**: Specify the list of referers. You can target all referers starting with a prefix or ending with a suffix using the '\*' character. For example, "algolia.com/\*" matches all referers starting with "algolia.com/" and "\*.algolia.com" matches all referers ending with ".algolia.com". Defaults to all referers if empty or blank.
         | 
| 757 | 
            +
             * **queryParameters**: Specify the list of query parameters. You can force the query parameters for a query using the url string format (param1=X¶m2=Y...).
         | 
| 758 | 
            +
             * **description**: Specify a description to describe where the key is used.
         | 
| 702 759 |  | 
| 703 760 |  | 
| 704 761 | 
             
            ```ruby
         | 
| @@ -761,14 +818,13 @@ You may have a single index containing per user data. In that case, all records | |
| 761 818 | 
             
            ```ruby
         | 
| 762 819 | 
             
            # generate a public API key for user 42. Here, records are tagged with:
         | 
| 763 820 | 
             
            #  - 'user_XXXX' if they are visible by user XXXX
         | 
| 764 | 
            -
            public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', 'tagFilters | 
| 821 | 
            +
            public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', {'tagFilters'=> 'user_42'}
         | 
| 765 822 | 
             
            ```
         | 
| 766 823 |  | 
| 767 824 | 
             
            This public API key can then be used in your JavaScript code as follow:
         | 
| 768 825 |  | 
| 769 826 | 
             
            ```js
         | 
| 770 827 | 
             
            var client = algoliasearch('YourApplicationID', '<%= public_api_key %>');
         | 
| 771 | 
            -
            client.setExtraHeader('X-Algolia-QueryParameters', 'tagFilters=user_42'); // must be same than those used at generation-time
         | 
| 772 828 |  | 
| 773 829 | 
             
            var index = client.initIndex('indexName')
         | 
| 774 830 |  | 
| @@ -782,12 +838,12 @@ index.search('something', function(err, content) { | |
| 782 838 | 
             
            });
         | 
| 783 839 | 
             
            ```
         | 
| 784 840 |  | 
| 785 | 
            -
            You can mix rate limits and secured API keys by setting  | 
| 841 | 
            +
            You can mix rate limits and secured API keys by setting a `userToken` query parameter at API key generation time. When set, a unique user will be identified by her `IP + user_token` instead of only by her `IP`. This allows you to restrict a single user to performing a maximum of `N` API calls per hour, even if she shares her `IP` with another user.
         | 
| 786 842 |  | 
| 787 843 | 
             
            ```ruby
         | 
| 788 844 | 
             
            # generate a public API key for user 42. Here, records are tagged with:
         | 
| 789 845 | 
             
            #  - 'user_XXXX' if they are visible by user XXXX
         | 
| 790 | 
            -
            public_key = Algolia.generate_secured_api_key 'YourRateLimitedApiKey', 'tagFilters | 
| 846 | 
            +
            public_key = Algolia.generate_secured_api_key 'YourRateLimitedApiKey', {'tagFilters'=> 'user_42', 'userToken'=> 'user_42'}
         | 
| 791 847 | 
             
            ```
         | 
| 792 848 |  | 
| 793 849 | 
             
            This public API key can then be used in your JavaScript code as follow:
         | 
| @@ -795,32 +851,6 @@ This public API key can then be used in your JavaScript code as follow: | |
| 795 851 | 
             
            ```js
         | 
| 796 852 | 
             
            var client = algoliasearch('YourApplicationID', '<%= public_api_key %>');
         | 
| 797 853 |  | 
| 798 | 
            -
            // must be same than those used at generation-time
         | 
| 799 | 
            -
            client.setExtraHeader('X-Algolia-QueryParameters', 'tagFilters=user_42');
         | 
| 800 | 
            -
             | 
| 801 | 
            -
            // must be same than the one used at generation-time
         | 
| 802 | 
            -
            client.setUserToken('user_42');
         | 
| 803 | 
            -
             | 
| 804 | 
            -
            var index = client.initIndex('indexName')
         | 
| 805 | 
            -
             | 
| 806 | 
            -
            index.search('another query', function(err, content) {
         | 
| 807 | 
            -
              if (err) {
         | 
| 808 | 
            -
                console.error(err);
         | 
| 809 | 
            -
                return;
         | 
| 810 | 
            -
              }
         | 
| 811 | 
            -
             | 
| 812 | 
            -
              console.log(content);
         | 
| 813 | 
            -
            });
         | 
| 814 | 
            -
            ```
         | 
| 815 | 
            -
             | 
| 816 | 
            -
            You can also generate secured API keys to limit the usage of a key to a referer. The generation use the same function than the Per user restriction. This public API key can be used in your JavaScript code as follow:
         | 
| 817 | 
            -
             | 
| 818 | 
            -
            ```js
         | 
| 819 | 
            -
            var client = algoliasearch('YourApplicationID', '<%= public_api_key %>');
         | 
| 820 | 
            -
             | 
| 821 | 
            -
            // must be same than those used at generation-time
         | 
| 822 | 
            -
            client.setExtraHeader('X-Algolia-AllowedReferer', 'algolia.com/*');
         | 
| 823 | 
            -
             | 
| 824 854 | 
             
            var index = client.initIndex('indexName')
         | 
| 825 855 |  | 
| 826 856 | 
             
            index.search('another query', function(err, content) {
         | 
| @@ -834,7 +864,6 @@ index.search('another query', function(err, content) { | |
| 834 864 | 
             
            ```
         | 
| 835 865 |  | 
| 836 866 |  | 
| 837 | 
            -
             | 
| 838 867 | 
             
            Copy or rename an index
         | 
| 839 868 | 
             
            -------------
         | 
| 840 869 |  | 
| @@ -857,19 +886,25 @@ The move command is particularly useful if you want to update a big index atomic | |
| 857 886 | 
             
            puts Algolia.move_index("MyNewIndex", "MyIndex")
         | 
| 858 887 | 
             
            ```
         | 
| 859 888 |  | 
| 889 | 
            +
             | 
| 860 890 | 
             
            Backup / Retrieve of all index content
         | 
| 861 891 | 
             
            -------------
         | 
| 862 892 |  | 
| 863 893 | 
             
            You can retrieve all index content for backup purposes or for SEO using the browse method.
         | 
| 864 | 
            -
            This method  | 
| 894 | 
            +
            This method can retrieve up to 1,000 objects per call and supports full text search and filters but the distinct feature is not available
         | 
| 895 | 
            +
            Unlike the search method, the sort by typo, proximity, geo distance and matched words is not applied, the hits are only sorted by numeric attributes specified in the ranking and the custom ranking.
         | 
| 896 | 
            +
             | 
| 897 | 
            +
            You can browse the index:
         | 
| 865 898 |  | 
| 866 899 | 
             
            ```ruby
         | 
| 867 | 
            -
            #  | 
| 868 | 
            -
             | 
| 869 | 
            -
            #  | 
| 870 | 
            -
             | 
| 900 | 
            +
            # Iterate with a filter over the index
         | 
| 901 | 
            +
            index.browse({:query => "test", :numericFilters => 'i=42'}) do
         | 
| 902 | 
            +
            	# Do something
         | 
| 903 | 
            +
            end
         | 
| 871 904 | 
             
            ```
         | 
| 872 905 |  | 
| 906 | 
            +
             | 
| 907 | 
            +
             | 
| 873 908 | 
             
            Logs
         | 
| 874 909 | 
             
            -------------
         | 
| 875 910 |  | 
| @@ -919,7 +954,7 @@ describe 'With a mocked client' do | |
| 919 954 | 
             
              it "shouldn't perform any API calls here" do
         | 
| 920 955 | 
             
                index = Algolia::Index.new("friends")
         | 
| 921 956 | 
             
                index.add_object!({ :name => "John Doe", :email => "john@doe.org" })
         | 
| 922 | 
            -
                index.search('').should == {} # mocked
         | 
| 957 | 
            +
                index.search('').should == {"hits"=>[{"objectID"=>42}], "page"=>1, "hitsPerPage"=>1} # mocked
         | 
| 923 958 | 
             
                index.clear_index
         | 
| 924 959 | 
             
                index.delete_index
         | 
| 925 960 | 
             
              end
         | 
    
        data/lib/algolia/client.rb
    CHANGED
    
    | @@ -4,6 +4,7 @@ require 'algolia/version' | |
| 4 4 | 
             
            require 'json'
         | 
| 5 5 | 
             
            require 'zlib'
         | 
| 6 6 | 
             
            require 'openssl'
         | 
| 7 | 
            +
            require 'base64'
         | 
| 7 8 |  | 
| 8 9 | 
             
            module Algolia
         | 
| 9 10 |  | 
| @@ -98,7 +99,9 @@ module Algolia | |
| 98 99 | 
             
                def multiple_queries(queries, index_name_key = :index_name, strategy = "none")
         | 
| 99 100 | 
             
                  requests = {
         | 
| 100 101 | 
             
                    :requests => queries.map do |query|
         | 
| 102 | 
            +
                      query = query.dup
         | 
| 101 103 | 
             
                      indexName = query.delete(index_name_key) || query.delete(index_name_key.to_s)
         | 
| 104 | 
            +
                      raise ArgumentError.new("Missing '#{index_name_key}' option") if indexName.nil?
         | 
| 102 105 | 
             
                      encoded_params = Hash[query.map { |k,v| [k.to_s, v.is_a?(Array) ? v.to_json : v] }]
         | 
| 103 106 | 
             
                      { :indexName => indexName, :params => Protocol.to_query(encoded_params) }
         | 
| 104 107 | 
             
                    end
         | 
| @@ -469,12 +472,21 @@ module Algolia | |
| 469 472 | 
             
              # @param tag_filters the list of tags applied to the query (used as security)
         | 
| 470 473 | 
             
              # @param user_token an optional token identifying the current user
         | 
| 471 474 | 
             
              #
         | 
| 472 | 
            -
              def Algolia.generate_secured_api_key(private_api_key,  | 
| 473 | 
            -
                if  | 
| 474 | 
            -
                   | 
| 475 | 
            +
              def Algolia.generate_secured_api_key(private_api_key, tag_filters_or_params, user_token = nil)
         | 
| 476 | 
            +
                if tag_filters_or_params.is_a?(Hash) && user_token.nil?
         | 
| 477 | 
            +
                  encoded_params = Hash[tag_filters_or_params.map { |k,v| [k.to_s, v.is_a?(Array) ? v.to_json : v] }]
         | 
| 478 | 
            +
                  query_str = Protocol.to_query(encoded_params)
         | 
| 479 | 
            +
                  hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), private_api_key, query_str)
         | 
| 480 | 
            +
                  Base64.encode64("#{hmac}#{query_str}").gsub("\n", '')
         | 
| 481 | 
            +
                else
         | 
| 482 | 
            +
                  tag_filters = if tag_filters_or_params.is_a?(Array)
         | 
| 483 | 
            +
                    tag_filters = tag_filters_or_params.map { |t| t.is_a?(Array) ? "(#{t.join(',')})" : t }.join(',')
         | 
| 484 | 
            +
                  else
         | 
| 485 | 
            +
                    tag_filters_or_params
         | 
| 486 | 
            +
                  end
         | 
| 487 | 
            +
                  raise ArgumentError.new('Attribute "tag_filters" must be a list of tags') if !tag_filters.is_a?(String)
         | 
| 488 | 
            +
                  OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), private_api_key, "#{tag_filters}#{user_token.to_s}")
         | 
| 475 489 | 
             
                end
         | 
| 476 | 
            -
                raise ArgumentError.new('Attribute "tag_filters" must be a list of tags') if !tag_filters.is_a?(String)
         | 
| 477 | 
            -
                OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), private_api_key, "#{tag_filters}#{user_token.to_s}")
         | 
| 478 490 | 
             
              end
         | 
| 479 491 |  | 
| 480 492 | 
             
              #
         | 
    
        data/lib/algolia/version.rb
    CHANGED
    
    
    
        data/spec/client_spec.rb
    CHANGED
    
    | @@ -1,5 +1,6 @@ | |
| 1 1 | 
             
            # encoding: UTF-8
         | 
| 2 2 | 
             
            require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
         | 
| 3 | 
            +
            require 'base64'
         | 
| 3 4 |  | 
| 4 5 | 
             
            # avoid concurrent access to the same index
         | 
| 5 6 | 
             
            def safe_index_name(name)
         | 
| @@ -277,6 +278,10 @@ describe 'Client' do | |
| 277 278 | 
             
                res["results"][0]["hits"].length.should eq(1)
         | 
| 278 279 | 
             
              end
         | 
| 279 280 |  | 
| 281 | 
            +
              it "should throw if the index_name is missing in multiple_queries" do
         | 
| 282 | 
            +
                expect { Algolia.multiple_queries([{"query" => ""}]) }.to raise_error(ArgumentError)
         | 
| 283 | 
            +
              end
         | 
| 284 | 
            +
             | 
| 280 285 | 
             
              it "shoud accept custom batch" do
         | 
| 281 286 | 
             
                @index.clear_index! rescue "Not fatal"
         | 
| 282 287 | 
             
                request = { "requests" => [
         | 
| @@ -647,7 +652,7 @@ describe 'Client' do | |
| 647 652 | 
             
                logs['logs'][0]['sha1'].should be_a(String)
         | 
| 648 653 | 
             
              end
         | 
| 649 654 |  | 
| 650 | 
            -
              it 'should generate secured api keys' do
         | 
| 655 | 
            +
              it 'should generate secured api keys (old syntax)' do
         | 
| 651 656 | 
             
                key = Algolia.generate_secured_api_key('my_api_key', '(public,user1)')
         | 
| 652 657 | 
             
                key.should eq(OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), 'my_api_key', '(public,user1)'))
         | 
| 653 658 | 
             
                key = Algolia.generate_secured_api_key('my_api_key', '(public,user1)', 42)
         | 
| @@ -658,6 +663,13 @@ describe 'Client' do | |
| 658 663 | 
             
                key.should eq(OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), 'my_api_key', 'public,(premium,vip)'))
         | 
| 659 664 | 
             
              end
         | 
| 660 665 |  | 
| 666 | 
            +
              it 'should generate secured api keys (new syntax)' do
         | 
| 667 | 
            +
                key = Algolia.generate_secured_api_key('my_api_key', :tagFilters => '(public,user1)')
         | 
| 668 | 
            +
                key.should eq(Base64.encode64("#{OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), 'my_api_key', 'tagFilters=%28public%2Cuser1%29')}tagFilters=%28public%2Cuser1%29").gsub("\n", ''))
         | 
| 669 | 
            +
                key = Algolia.generate_secured_api_key('182634d8894831d5dbce3b3185c50881', :tagFilters => '(public,user1)', :userToken => 42)
         | 
| 670 | 
            +
                key.should eq('OGYwN2NlNTdlOGM2ZmM4MjA5NGM0ZmYwNTk3MDBkNzMzZjQ0MDI3MWZjNTNjM2Y3YTAzMWM4NTBkMzRiNTM5YnRhZ0ZpbHRlcnM9JTI4cHVibGljJTJDdXNlcjElMjkmdXNlclRva2VuPTQy')
         | 
| 671 | 
            +
              end
         | 
| 672 | 
            +
             | 
| 661 673 | 
             
              it 'Check attributes multipleQueries' do
         | 
| 662 674 | 
             
                res = Algolia.multiple_queries([{:index_name => safe_index_name("àlgol?a"), "query" => ""}])
         | 
| 663 675 | 
             
                res.should have_key('results')
         | 
    
        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.7.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Algolia
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2016-01-09 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: httpclient
         |