algolia 2.0.2 → 2.2.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/.circleci/config.yml +10 -1
 - data/.dockerignore +38 -0
 - data/.gitignore +1 -0
 - data/CHANGELOG.md +36 -6
 - data/CONTRIBUTING.MD +184 -0
 - data/DOCKER_README.MD +89 -0
 - data/Dockerfile +7 -0
 - data/README.md +1 -1
 - data/lib/algolia/config/recommend_config.rb +6 -0
 - data/lib/algolia/helpers.rb +49 -0
 - data/lib/algolia/http/http_requester.rb +4 -4
 - data/lib/algolia/recommend_client.rb +134 -0
 - data/lib/algolia/responses/dictionary_response.rb +33 -0
 - data/lib/algolia/search_client.rb +177 -3
 - data/lib/algolia/search_index.rb +9 -50
 - data/lib/algolia/version.rb +1 -1
 - data/lib/algolia.rb +3 -0
 - data/test/algolia/integration/analytics_client_test.rb +6 -2
 - data/test/algolia/integration/mocks/mock_requester.rb +13 -11
 - data/test/algolia/integration/recommend_client_test.rb +70 -0
 - data/test/algolia/integration/search_client_test.rb +107 -12
 - data/test/algolia/integration/search_index_test.rb +3 -0
 - data/test/test_helper.rb +28 -0
 - metadata +12 -3
 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Algolia
         
     | 
| 
      
 2 
     | 
    
         
            +
              class DictionaryResponse < BaseResponse
         
     | 
| 
      
 3 
     | 
    
         
            +
                include CallType
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :raw_response
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                # @param client [Search::Client] Algolia Search Client used for verification
         
     | 
| 
      
 8 
     | 
    
         
            +
                # @param response [Hash] Raw response from the client
         
     | 
| 
      
 9 
     | 
    
         
            +
                #
         
     | 
| 
      
 10 
     | 
    
         
            +
                def initialize(client, response)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @client       = client
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @raw_response = response
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @done         = false
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                # Wait for the task to complete
         
     | 
| 
      
 17 
     | 
    
         
            +
                #
         
     | 
| 
      
 18 
     | 
    
         
            +
                # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
      
 19 
     | 
    
         
            +
                #
         
     | 
| 
      
 20 
     | 
    
         
            +
                def wait(_opts = {})
         
     | 
| 
      
 21 
     | 
    
         
            +
                  until @done
         
     | 
| 
      
 22 
     | 
    
         
            +
                    res    = @client.custom_request({}, path_encode('/1/task/%s', @raw_response[:taskID]), :GET, READ)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    status = get_option(res, 'status')
         
     | 
| 
      
 24 
     | 
    
         
            +
                    if status == 'published'
         
     | 
| 
      
 25 
     | 
    
         
            +
                      @done = true
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
                    sleep(Defaults::WAIT_TASK_DEFAULT_TIME_BEFORE_RETRY / 1000)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  self
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -80,7 +80,7 @@ module Algolia 
     | 
|
| 
       80 
80 
     | 
    
         
             
                  end
         
     | 
| 
       81 
81 
     | 
    
         | 
| 
       82 
82 
     | 
    
         
             
                  # # # # # # # # # # # # # # # # # # # # #
         
     | 
| 
       83 
     | 
    
         
            -
                  #  
     | 
| 
      
 83 
     | 
    
         
            +
                  # INDEX METHODS
         
     | 
| 
       84 
84 
     | 
    
         
             
                  # # # # # # # # # # # # # # # # # # # # #
         
     | 
| 
       85 
85 
     | 
    
         | 
| 
       86 
86 
     | 
    
         
             
                  # Initialize an index with a given name
         
     | 
| 
         @@ -300,7 +300,7 @@ module Algolia 
     | 
|
| 
       300 
300 
     | 
    
         
             
                  # @return [AddApiKeyResponse]
         
     | 
| 
       301 
301 
     | 
    
         
             
                  #
         
     | 
| 
       302 
302 
     | 
    
         
             
                  def add_api_key!(acl, opts = {})
         
     | 
| 
       303 
     | 
    
         
            -
                    response = add_api_key(acl)
         
     | 
| 
      
 303 
     | 
    
         
            +
                    response = add_api_key(acl, opts)
         
     | 
| 
       304 
304 
     | 
    
         | 
| 
       305 
305 
     | 
    
         
             
                    response.wait(opts)
         
     | 
| 
       306 
306 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -480,6 +480,7 @@ module Algolia 
     | 
|
| 
       480 
480 
     | 
    
         
             
                  def multiple_queries(queries, opts = {})
         
     | 
| 
       481 
481 
     | 
    
         
             
                    @transporter.read(:POST, '/1/indexes/*/queries', { requests: queries }, opts)
         
     | 
| 
       482 
482 
     | 
    
         
             
                  end
         
     | 
| 
      
 483 
     | 
    
         
            +
                  alias_method :search, :multiple_queries
         
     | 
| 
       483 
484 
     | 
    
         | 
| 
       484 
485 
     | 
    
         
             
                  # # # # # # # # # # # # # # # # # # # # #
         
     | 
| 
       485 
486 
     | 
    
         
             
                  # MCM METHODS
         
     | 
| 
         @@ -594,12 +595,185 @@ module Algolia 
     | 
|
| 
       594 
595 
     | 
    
         
             
                    @transporter.read(:GET, '/1/clusters/mapping/pending' + handle_params({ getClusters: retrieve_mappings }), {}, request_options)
         
     | 
| 
       595 
596 
     | 
    
         
             
                  end
         
     | 
| 
       596 
597 
     | 
    
         | 
| 
       597 
     | 
    
         
            -
                  #
         
     | 
| 
       598 
598 
     | 
    
         
             
                  # Aliases the pending_mappings? method
         
     | 
| 
       599 
599 
     | 
    
         
             
                  #
         
     | 
| 
       600 
600 
     | 
    
         
             
                  alias_method :has_pending_mappings, :pending_mappings?
         
     | 
| 
       601 
601 
     | 
    
         | 
| 
      
 602 
     | 
    
         
            +
                  # # # # # # # # # # # # # # # # # # # # #
         
     | 
| 
      
 603 
     | 
    
         
            +
                  # CUSTOM DICTIONARIES METHODS
         
     | 
| 
      
 604 
     | 
    
         
            +
                  # # # # # # # # # # # # # # # # # # # # #
         
     | 
| 
      
 605 
     | 
    
         
            +
             
     | 
| 
      
 606 
     | 
    
         
            +
                  # Save entries for a given dictionary
         
     | 
| 
      
 607 
     | 
    
         
            +
                  #
         
     | 
| 
      
 608 
     | 
    
         
            +
                  # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
         
     | 
| 
      
 609 
     | 
    
         
            +
                  # @param dictionary_entries [Array<Hash>] array of dictionary entries
         
     | 
| 
      
 610 
     | 
    
         
            +
                  # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
      
 611 
     | 
    
         
            +
                  #
         
     | 
| 
      
 612 
     | 
    
         
            +
                  # @return DictionaryResponse
         
     | 
| 
      
 613 
     | 
    
         
            +
                  #
         
     | 
| 
      
 614 
     | 
    
         
            +
                  def save_dictionary_entries(dictionary, dictionary_entries, opts = {})
         
     | 
| 
      
 615 
     | 
    
         
            +
                    response = @transporter.write(
         
     | 
| 
      
 616 
     | 
    
         
            +
                      :POST,
         
     | 
| 
      
 617 
     | 
    
         
            +
                      path_encode('/1/dictionaries/%s/batch', dictionary),
         
     | 
| 
      
 618 
     | 
    
         
            +
                      { clearExistingDictionaryEntries: false, requests: chunk('addEntry', dictionary_entries) },
         
     | 
| 
      
 619 
     | 
    
         
            +
                      opts
         
     | 
| 
      
 620 
     | 
    
         
            +
                    )
         
     | 
| 
      
 621 
     | 
    
         
            +
             
     | 
| 
      
 622 
     | 
    
         
            +
                    DictionaryResponse.new(self, response)
         
     | 
| 
      
 623 
     | 
    
         
            +
                  end
         
     | 
| 
      
 624 
     | 
    
         
            +
             
     | 
| 
      
 625 
     | 
    
         
            +
                  # Save entries for a given dictionary and wait for the task to finish
         
     | 
| 
      
 626 
     | 
    
         
            +
                  #
         
     | 
| 
      
 627 
     | 
    
         
            +
                  # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
         
     | 
| 
      
 628 
     | 
    
         
            +
                  # @param dictionary_entries [Array<Hash>] array of dictionary entries
         
     | 
| 
      
 629 
     | 
    
         
            +
                  # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
      
 630 
     | 
    
         
            +
                  #
         
     | 
| 
      
 631 
     | 
    
         
            +
                  def save_dictionary_entries!(dictionary, dictionary_entries, opts = {})
         
     | 
| 
      
 632 
     | 
    
         
            +
                    response = save_dictionary_entries(dictionary, dictionary_entries, opts)
         
     | 
| 
      
 633 
     | 
    
         
            +
             
     | 
| 
      
 634 
     | 
    
         
            +
                    response.wait(opts)
         
     | 
| 
      
 635 
     | 
    
         
            +
                  end
         
     | 
| 
      
 636 
     | 
    
         
            +
             
     | 
| 
      
 637 
     | 
    
         
            +
                  # Replace entries for a given dictionary
         
     | 
| 
      
 638 
     | 
    
         
            +
                  #
         
     | 
| 
      
 639 
     | 
    
         
            +
                  # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
         
     | 
| 
      
 640 
     | 
    
         
            +
                  # @param dictionary_entries [Array<Hash>] array of dictionary entries
         
     | 
| 
      
 641 
     | 
    
         
            +
                  # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
      
 642 
     | 
    
         
            +
                  #
         
     | 
| 
      
 643 
     | 
    
         
            +
                  # @return DictionaryResponse
         
     | 
| 
      
 644 
     | 
    
         
            +
                  #
         
     | 
| 
      
 645 
     | 
    
         
            +
                  def replace_dictionary_entries(dictionary, dictionary_entries, opts = {})
         
     | 
| 
      
 646 
     | 
    
         
            +
                    response = @transporter.write(
         
     | 
| 
      
 647 
     | 
    
         
            +
                      :POST,
         
     | 
| 
      
 648 
     | 
    
         
            +
                      path_encode('/1/dictionaries/%s/batch', dictionary),
         
     | 
| 
      
 649 
     | 
    
         
            +
                      { clearExistingDictionaryEntries: true, requests: chunk('addEntry', dictionary_entries) },
         
     | 
| 
      
 650 
     | 
    
         
            +
                      opts
         
     | 
| 
      
 651 
     | 
    
         
            +
                    )
         
     | 
| 
      
 652 
     | 
    
         
            +
             
     | 
| 
      
 653 
     | 
    
         
            +
                    DictionaryResponse.new(self, response)
         
     | 
| 
      
 654 
     | 
    
         
            +
                  end
         
     | 
| 
      
 655 
     | 
    
         
            +
             
     | 
| 
      
 656 
     | 
    
         
            +
                  # Replace entries for a given dictionary and wait for the task to finish
         
     | 
| 
      
 657 
     | 
    
         
            +
                  #
         
     | 
| 
      
 658 
     | 
    
         
            +
                  # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
         
     | 
| 
      
 659 
     | 
    
         
            +
                  # @param dictionary_entries [Array<Hash>] array of dictionary entries
         
     | 
| 
      
 660 
     | 
    
         
            +
                  # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
      
 661 
     | 
    
         
            +
                  #
         
     | 
| 
      
 662 
     | 
    
         
            +
                  def replace_dictionary_entries!(dictionary, dictionary_entries, opts = {})
         
     | 
| 
      
 663 
     | 
    
         
            +
                    response = replace_dictionary_entries(dictionary, dictionary_entries, opts)
         
     | 
| 
      
 664 
     | 
    
         
            +
             
     | 
| 
      
 665 
     | 
    
         
            +
                    response.wait(opts)
         
     | 
| 
      
 666 
     | 
    
         
            +
                  end
         
     | 
| 
      
 667 
     | 
    
         
            +
             
     | 
| 
      
 668 
     | 
    
         
            +
                  # Delete entries for a given dictionary
         
     | 
| 
      
 669 
     | 
    
         
            +
                  #
         
     | 
| 
      
 670 
     | 
    
         
            +
                  # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
         
     | 
| 
      
 671 
     | 
    
         
            +
                  # @param object_ids [Array<Hash>] array of object ids
         
     | 
| 
      
 672 
     | 
    
         
            +
                  # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
      
 673 
     | 
    
         
            +
                  #
         
     | 
| 
      
 674 
     | 
    
         
            +
                  # @return DictionaryResponse
         
     | 
| 
      
 675 
     | 
    
         
            +
                  #
         
     | 
| 
      
 676 
     | 
    
         
            +
                  def delete_dictionary_entries(dictionary, object_ids, opts = {})
         
     | 
| 
      
 677 
     | 
    
         
            +
                    request  = object_ids.map do |object_id|
         
     | 
| 
      
 678 
     | 
    
         
            +
                      { objectID: object_id }
         
     | 
| 
      
 679 
     | 
    
         
            +
                    end
         
     | 
| 
      
 680 
     | 
    
         
            +
                    response = @transporter.write(
         
     | 
| 
      
 681 
     | 
    
         
            +
                      :POST,
         
     | 
| 
      
 682 
     | 
    
         
            +
                      path_encode('/1/dictionaries/%s/batch', dictionary),
         
     | 
| 
      
 683 
     | 
    
         
            +
                      { clearExistingDictionaryEntries: false, requests: chunk('deleteEntry', request) },
         
     | 
| 
      
 684 
     | 
    
         
            +
                      opts
         
     | 
| 
      
 685 
     | 
    
         
            +
                    )
         
     | 
| 
      
 686 
     | 
    
         
            +
             
     | 
| 
      
 687 
     | 
    
         
            +
                    DictionaryResponse.new(self, response)
         
     | 
| 
      
 688 
     | 
    
         
            +
                  end
         
     | 
| 
      
 689 
     | 
    
         
            +
             
     | 
| 
      
 690 
     | 
    
         
            +
                  # Delete entries for a given dictionary and wait for the task to finish
         
     | 
| 
      
 691 
     | 
    
         
            +
                  #
         
     | 
| 
      
 692 
     | 
    
         
            +
                  # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
         
     | 
| 
      
 693 
     | 
    
         
            +
                  # @param object_ids [Array<Hash>] array of object ids
         
     | 
| 
      
 694 
     | 
    
         
            +
                  # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
       602 
695 
     | 
    
         
             
                  #
         
     | 
| 
      
 696 
     | 
    
         
            +
                  def delete_dictionary_entries!(dictionary, object_ids, opts = {})
         
     | 
| 
      
 697 
     | 
    
         
            +
                    response = delete_dictionary_entries(dictionary, object_ids, opts)
         
     | 
| 
      
 698 
     | 
    
         
            +
             
     | 
| 
      
 699 
     | 
    
         
            +
                    response.wait(opts)
         
     | 
| 
      
 700 
     | 
    
         
            +
                  end
         
     | 
| 
      
 701 
     | 
    
         
            +
             
     | 
| 
      
 702 
     | 
    
         
            +
                  # Clear all entries for a given dictionary
         
     | 
| 
      
 703 
     | 
    
         
            +
                  #
         
     | 
| 
      
 704 
     | 
    
         
            +
                  # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
         
     | 
| 
      
 705 
     | 
    
         
            +
                  # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
      
 706 
     | 
    
         
            +
                  #
         
     | 
| 
      
 707 
     | 
    
         
            +
                  # @return DictionaryResponse
         
     | 
| 
      
 708 
     | 
    
         
            +
                  #
         
     | 
| 
      
 709 
     | 
    
         
            +
                  def clear_dictionary_entries(dictionary, opts = {})
         
     | 
| 
      
 710 
     | 
    
         
            +
                    replace_dictionary_entries(dictionary, [], opts)
         
     | 
| 
      
 711 
     | 
    
         
            +
                  end
         
     | 
| 
      
 712 
     | 
    
         
            +
             
     | 
| 
      
 713 
     | 
    
         
            +
                  # Clear all entries for a given dictionary and wait for the task to finish
         
     | 
| 
      
 714 
     | 
    
         
            +
                  #
         
     | 
| 
      
 715 
     | 
    
         
            +
                  # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
         
     | 
| 
      
 716 
     | 
    
         
            +
                  # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
      
 717 
     | 
    
         
            +
                  #
         
     | 
| 
      
 718 
     | 
    
         
            +
                  def clear_dictionary_entries!(dictionary, opts = {})
         
     | 
| 
      
 719 
     | 
    
         
            +
                    response = replace_dictionary_entries(dictionary, [], opts)
         
     | 
| 
      
 720 
     | 
    
         
            +
             
     | 
| 
      
 721 
     | 
    
         
            +
                    response.wait(opts)
         
     | 
| 
      
 722 
     | 
    
         
            +
                  end
         
     | 
| 
      
 723 
     | 
    
         
            +
             
     | 
| 
      
 724 
     | 
    
         
            +
                  # Search entries for a given dictionary
         
     | 
| 
      
 725 
     | 
    
         
            +
                  #
         
     | 
| 
      
 726 
     | 
    
         
            +
                  # @param dictionary [String] dictionary name. Can be either 'stopwords', 'plurals' or 'compounds'
         
     | 
| 
      
 727 
     | 
    
         
            +
                  # @param query [String] query to send
         
     | 
| 
      
 728 
     | 
    
         
            +
                  # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
      
 729 
     | 
    
         
            +
                  #
         
     | 
| 
      
 730 
     | 
    
         
            +
                  def search_dictionary_entries(dictionary, query, opts = {})
         
     | 
| 
      
 731 
     | 
    
         
            +
                    @transporter.read(
         
     | 
| 
      
 732 
     | 
    
         
            +
                      :POST,
         
     | 
| 
      
 733 
     | 
    
         
            +
                      path_encode('/1/dictionaries/%s/search', dictionary),
         
     | 
| 
      
 734 
     | 
    
         
            +
                      { query: query },
         
     | 
| 
      
 735 
     | 
    
         
            +
                      opts
         
     | 
| 
      
 736 
     | 
    
         
            +
                    )
         
     | 
| 
      
 737 
     | 
    
         
            +
                  end
         
     | 
| 
      
 738 
     | 
    
         
            +
             
     | 
| 
      
 739 
     | 
    
         
            +
                  # Set settings for all the dictionaries
         
     | 
| 
      
 740 
     | 
    
         
            +
                  #
         
     | 
| 
      
 741 
     | 
    
         
            +
                  # @param dictionary_settings [Hash]
         
     | 
| 
      
 742 
     | 
    
         
            +
                  # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
      
 743 
     | 
    
         
            +
                  #
         
     | 
| 
      
 744 
     | 
    
         
            +
                  # @return DictionaryResponse
         
     | 
| 
      
 745 
     | 
    
         
            +
                  #
         
     | 
| 
      
 746 
     | 
    
         
            +
                  def set_dictionary_settings(dictionary_settings, opts = {})
         
     | 
| 
      
 747 
     | 
    
         
            +
                    response = @transporter.write(:PUT, '/1/dictionaries/*/settings', dictionary_settings, opts)
         
     | 
| 
      
 748 
     | 
    
         
            +
             
     | 
| 
      
 749 
     | 
    
         
            +
                    DictionaryResponse.new(self, response)
         
     | 
| 
      
 750 
     | 
    
         
            +
                  end
         
     | 
| 
      
 751 
     | 
    
         
            +
             
     | 
| 
      
 752 
     | 
    
         
            +
                  # Set settings for all the dictionaries and wait for the task to finish
         
     | 
| 
      
 753 
     | 
    
         
            +
                  #
         
     | 
| 
      
 754 
     | 
    
         
            +
                  # @param dictionary_settings [Hash]
         
     | 
| 
      
 755 
     | 
    
         
            +
                  # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
      
 756 
     | 
    
         
            +
                  #
         
     | 
| 
      
 757 
     | 
    
         
            +
                  # @return DictionaryResponse
         
     | 
| 
      
 758 
     | 
    
         
            +
                  #
         
     | 
| 
      
 759 
     | 
    
         
            +
                  def set_dictionary_settings!(dictionary_settings, opts = {})
         
     | 
| 
      
 760 
     | 
    
         
            +
                    response = set_dictionary_settings(dictionary_settings, opts)
         
     | 
| 
      
 761 
     | 
    
         
            +
             
     | 
| 
      
 762 
     | 
    
         
            +
                    response.wait(opts)
         
     | 
| 
      
 763 
     | 
    
         
            +
                  end
         
     | 
| 
      
 764 
     | 
    
         
            +
             
     | 
| 
      
 765 
     | 
    
         
            +
                  # Retrieve settings for all the dictionaries
         
     | 
| 
      
 766 
     | 
    
         
            +
                  #
         
     | 
| 
      
 767 
     | 
    
         
            +
                  # @param opts [Hash] contains extra parameters to send with your query
         
     | 
| 
      
 768 
     | 
    
         
            +
                  #
         
     | 
| 
      
 769 
     | 
    
         
            +
                  def get_dictionary_settings(opts = {})
         
     | 
| 
      
 770 
     | 
    
         
            +
                    @transporter.read(:GET, '/1/dictionaries/*/settings', {}, opts)
         
     | 
| 
      
 771 
     | 
    
         
            +
                  end
         
     | 
| 
      
 772 
     | 
    
         
            +
             
     | 
| 
      
 773 
     | 
    
         
            +
                  # # # # # # # # # # # # # # # # # # # # #
         
     | 
| 
      
 774 
     | 
    
         
            +
                  # MISC METHODS
         
     | 
| 
      
 775 
     | 
    
         
            +
                  # # # # # # # # # # # # # # # # # # # # #
         
     | 
| 
      
 776 
     | 
    
         
            +
             
     | 
| 
       603 
777 
     | 
    
         
             
                  # Method available to make custom requests to the API
         
     | 
| 
       604 
778 
     | 
    
         
             
                  #
         
     | 
| 
       605 
779 
     | 
    
         
             
                  def custom_request(data, uri, method, call_type, opts = {})
         
     | 
    
        data/lib/algolia/search_index.rb
    CHANGED
    
    | 
         @@ -987,7 +987,15 @@ module Algolia 
     | 
|
| 
       987 
987 
     | 
    
         
             
                  # @return [IndexingResponse]
         
     | 
| 
       988 
988 
     | 
    
         
             
                  #
         
     | 
| 
       989 
989 
     | 
    
         
             
                  def set_settings(settings, opts = {})
         
     | 
| 
       990 
     | 
    
         
            -
                     
     | 
| 
      
 990 
     | 
    
         
            +
                    request_options      = symbolize_hash(opts)
         
     | 
| 
      
 991 
     | 
    
         
            +
                    forward_to_replicas  = request_options.delete(:forwardToReplicas) || false
         
     | 
| 
      
 992 
     | 
    
         
            +
             
     | 
| 
      
 993 
     | 
    
         
            +
                    response = @transporter.write(
         
     | 
| 
      
 994 
     | 
    
         
            +
                      :PUT,
         
     | 
| 
      
 995 
     | 
    
         
            +
                      path_encode('/1/indexes/%s/settings', @name) + handle_params({ forwardToReplicas: forward_to_replicas }),
         
     | 
| 
      
 996 
     | 
    
         
            +
                      settings,
         
     | 
| 
      
 997 
     | 
    
         
            +
                      request_options
         
     | 
| 
      
 998 
     | 
    
         
            +
                    )
         
     | 
| 
       991 
999 
     | 
    
         | 
| 
       992 
1000 
     | 
    
         
             
                    IndexingResponse.new(self, response)
         
     | 
| 
       993 
1001 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -1037,55 +1045,6 @@ module Algolia 
     | 
|
| 
       1037 
1045 
     | 
    
         | 
| 
       1038 
1046 
     | 
    
         
             
                  private
         
     | 
| 
       1039 
1047 
     | 
    
         | 
| 
       1040 
     | 
    
         
            -
                  # Check the passed object to determine if it's an array
         
     | 
| 
       1041 
     | 
    
         
            -
                  #
         
     | 
| 
       1042 
     | 
    
         
            -
                  # @param object [Object]
         
     | 
| 
       1043 
     | 
    
         
            -
                  #
         
     | 
| 
       1044 
     | 
    
         
            -
                  def check_array(object)
         
     | 
| 
       1045 
     | 
    
         
            -
                    raise AlgoliaError, 'argument must be an array of objects' unless object.is_a?(Array)
         
     | 
| 
       1046 
     | 
    
         
            -
                  end
         
     | 
| 
       1047 
     | 
    
         
            -
             
     | 
| 
       1048 
     | 
    
         
            -
                  # Check the passed object
         
     | 
| 
       1049 
     | 
    
         
            -
                  #
         
     | 
| 
       1050 
     | 
    
         
            -
                  # @param object [Object]
         
     | 
| 
       1051 
     | 
    
         
            -
                  # @param in_array [Boolean] whether the object is an array or not
         
     | 
| 
       1052 
     | 
    
         
            -
                  #
         
     | 
| 
       1053 
     | 
    
         
            -
                  def check_object(object, in_array = false)
         
     | 
| 
       1054 
     | 
    
         
            -
                    case object
         
     | 
| 
       1055 
     | 
    
         
            -
                    when Array
         
     | 
| 
       1056 
     | 
    
         
            -
                      raise AlgoliaError, in_array ? 'argument must be an array of objects' : 'argument must not be an array'
         
     | 
| 
       1057 
     | 
    
         
            -
                    when String, Integer, Float, TrueClass, FalseClass, NilClass
         
     | 
| 
       1058 
     | 
    
         
            -
                      raise AlgoliaError, "argument must be an #{'array of' if in_array} object, got: #{object.inspect}"
         
     | 
| 
       1059 
     | 
    
         
            -
                    end
         
     | 
| 
       1060 
     | 
    
         
            -
                  end
         
     | 
| 
       1061 
     | 
    
         
            -
             
     | 
| 
       1062 
     | 
    
         
            -
                  # Check if passed object has a objectID
         
     | 
| 
       1063 
     | 
    
         
            -
                  #
         
     | 
| 
       1064 
     | 
    
         
            -
                  # @param object [Object]
         
     | 
| 
       1065 
     | 
    
         
            -
                  # @param object_id [String]
         
     | 
| 
       1066 
     | 
    
         
            -
                  #
         
     | 
| 
       1067 
     | 
    
         
            -
                  def get_object_id(object, object_id = nil)
         
     | 
| 
       1068 
     | 
    
         
            -
                    check_object(object)
         
     | 
| 
       1069 
     | 
    
         
            -
                    object_id ||= object[:objectID] || object['objectID']
         
     | 
| 
       1070 
     | 
    
         
            -
                    raise AlgoliaError, "Missing 'objectID'" if object_id.nil?
         
     | 
| 
       1071 
     | 
    
         
            -
                    object_id
         
     | 
| 
       1072 
     | 
    
         
            -
                  end
         
     | 
| 
       1073 
     | 
    
         
            -
             
     | 
| 
       1074 
     | 
    
         
            -
                  # Build a batch request
         
     | 
| 
       1075 
     | 
    
         
            -
                  #
         
     | 
| 
       1076 
     | 
    
         
            -
                  # @param action [String] action to perform on the engine
         
     | 
| 
       1077 
     | 
    
         
            -
                  # @param objects [Array] objects on which build the action
         
     | 
| 
       1078 
     | 
    
         
            -
                  # @param with_object_id [Boolean] if set to true, check if each object has an objectID set
         
     | 
| 
       1079 
     | 
    
         
            -
                  #
         
     | 
| 
       1080 
     | 
    
         
            -
                  def chunk(action, objects, with_object_id = false)
         
     | 
| 
       1081 
     | 
    
         
            -
                    objects.map do |object|
         
     | 
| 
       1082 
     | 
    
         
            -
                        check_object(object, true)
         
     | 
| 
       1083 
     | 
    
         
            -
                        request            = { action: action, body: object }
         
     | 
| 
       1084 
     | 
    
         
            -
                        request[:objectID] = get_object_id(object).to_s if with_object_id
         
     | 
| 
       1085 
     | 
    
         
            -
                        request
         
     | 
| 
       1086 
     | 
    
         
            -
                    end
         
     | 
| 
       1087 
     | 
    
         
            -
                  end
         
     | 
| 
       1088 
     | 
    
         
            -
             
     | 
| 
       1089 
1048 
     | 
    
         
             
                  def raw_batch(requests, opts)
         
     | 
| 
       1090 
1049 
     | 
    
         
             
                    @transporter.write(:POST, path_encode('/1/indexes/%s/batch', @name), { requests: requests }, opts)
         
     | 
| 
       1091 
1050 
     | 
    
         
             
                  end
         
     | 
    
        data/lib/algolia/version.rb
    CHANGED
    
    
    
        data/lib/algolia.rb
    CHANGED
    
    | 
         @@ -7,6 +7,7 @@ require 'algolia/config/base_config' 
     | 
|
| 
       7 
7 
     | 
    
         
             
            require 'algolia/config/search_config'
         
     | 
| 
       8 
8 
     | 
    
         
             
            require 'algolia/config/analytics_config'
         
     | 
| 
       9 
9 
     | 
    
         
             
            require 'algolia/config/insights_config'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'algolia/config/recommend_config'
         
     | 
| 
       10 
11 
     | 
    
         
             
            require 'algolia/config/recommendation_config'
         
     | 
| 
       11 
12 
     | 
    
         
             
            require 'algolia/enums/call_type'
         
     | 
| 
       12 
13 
     | 
    
         
             
            require 'algolia/enums/retry_outcome_type'
         
     | 
| 
         @@ -20,6 +21,7 @@ require 'algolia/responses/indexing_response' 
     | 
|
| 
       20 
21 
     | 
    
         
             
            require 'algolia/responses/add_api_key_response'
         
     | 
| 
       21 
22 
     | 
    
         
             
            require 'algolia/responses/update_api_key_response'
         
     | 
| 
       22 
23 
     | 
    
         
             
            require 'algolia/responses/delete_api_key_response'
         
     | 
| 
      
 24 
     | 
    
         
            +
            require 'algolia/responses/dictionary_response'
         
     | 
| 
       23 
25 
     | 
    
         
             
            require 'algolia/responses/restore_api_key_response'
         
     | 
| 
       24 
26 
     | 
    
         
             
            require 'algolia/responses/multiple_batch_indexing_response'
         
     | 
| 
       25 
27 
     | 
    
         
             
            require 'algolia/responses/multiple_response'
         
     | 
| 
         @@ -32,6 +34,7 @@ require 'algolia/account_client' 
     | 
|
| 
       32 
34 
     | 
    
         
             
            require 'algolia/search_client'
         
     | 
| 
       33 
35 
     | 
    
         
             
            require 'algolia/analytics_client'
         
     | 
| 
       34 
36 
     | 
    
         
             
            require 'algolia/insights_client'
         
     | 
| 
      
 37 
     | 
    
         
            +
            require 'algolia/recommend_client'
         
     | 
| 
       35 
38 
     | 
    
         
             
            require 'algolia/recommendation_client'
         
     | 
| 
       36 
39 
     | 
    
         
             
            require 'algolia/error'
         
     | 
| 
       37 
40 
     | 
    
         
             
            require 'algolia/search_index'
         
     | 
| 
         @@ -23,7 +23,9 @@ class AnalyticsClientTest < BaseTest 
     | 
|
| 
       23 
23 
     | 
    
         
             
                    endAt: tomorrow.strftime('%Y-%m-%dT%H:%M:%SZ')
         
     | 
| 
       24 
24 
     | 
    
         
             
                  }
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
                  response   =  
     | 
| 
      
 26 
     | 
    
         
            +
                  response   = retry_test do
         
     | 
| 
      
 27 
     | 
    
         
            +
                    client.add_ab_test(ab_test)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
       27 
29 
     | 
    
         
             
                  ab_test_id = response[:abTestID]
         
     | 
| 
       28 
30 
     | 
    
         | 
| 
       29 
31 
     | 
    
         
             
                  index1.wait_task(response[:taskID])
         
     | 
| 
         @@ -86,7 +88,9 @@ class AnalyticsClientTest < BaseTest 
     | 
|
| 
       86 
88 
     | 
    
         
             
                    endAt: tomorrow.strftime('%Y-%m-%dT%H:%M:%SZ')
         
     | 
| 
       87 
89 
     | 
    
         
             
                  }
         
     | 
| 
       88 
90 
     | 
    
         | 
| 
       89 
     | 
    
         
            -
                  response   =  
     | 
| 
      
 91 
     | 
    
         
            +
                  response   = retry_test do
         
     | 
| 
      
 92 
     | 
    
         
            +
                    client.add_ab_test(ab_test)
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
       90 
94 
     | 
    
         
             
                  ab_test_id = response[:abTestID]
         
     | 
| 
       91 
95 
     | 
    
         | 
| 
       92 
96 
     | 
    
         
             
                  index.wait_task(response[:taskID])
         
     | 
| 
         @@ -1,25 +1,27 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class MockRequester
         
     | 
| 
      
 2 
     | 
    
         
            +
              attr_accessor :requests
         
     | 
| 
       2 
3 
     | 
    
         
             
              def initialize
         
     | 
| 
       3 
4 
     | 
    
         
             
                @connection = nil
         
     | 
| 
      
 5 
     | 
    
         
            +
                @requests   = []
         
     | 
| 
       4 
6 
     | 
    
         
             
              end
         
     | 
| 
       5 
7 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
              def send_request(host, method, path,  
     | 
| 
       7 
     | 
    
         
            -
                 
     | 
| 
       8 
     | 
    
         
            -
                response   = {
         
     | 
| 
       9 
     | 
    
         
            -
                  connection: connection,
         
     | 
| 
      
 8 
     | 
    
         
            +
              def send_request(host, method, path, body, headers, timeout, connect_timeout)
         
     | 
| 
      
 9 
     | 
    
         
            +
                request = {
         
     | 
| 
       10 
10 
     | 
    
         
             
                  host: host,
         
     | 
| 
      
 11 
     | 
    
         
            +
                  method: method,
         
     | 
| 
       11 
12 
     | 
    
         
             
                  path: path,
         
     | 
| 
      
 13 
     | 
    
         
            +
                  body: body,
         
     | 
| 
       12 
14 
     | 
    
         
             
                  headers: headers,
         
     | 
| 
       13 
     | 
    
         
            -
                   
     | 
| 
       14 
     | 
    
         
            -
                   
     | 
| 
       15 
     | 
    
         
            -
                  body: '{"hits":[],"nbHits":0,"page":0,"nbPages":1,"hitsPerPage":20,"exhaustiveNbHits":true,"query":"test","params":"query=test","processingTimeMS":1}',
         
     | 
| 
       16 
     | 
    
         
            -
                  success: true
         
     | 
| 
      
 15 
     | 
    
         
            +
                  timeout: timeout,
         
     | 
| 
      
 16 
     | 
    
         
            +
                  connect_timeout: connect_timeout
         
     | 
| 
       17 
17 
     | 
    
         
             
                }
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
      
 19 
     | 
    
         
            +
                @requests.push(request)
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
       19 
21 
     | 
    
         
             
                Algolia::Http::Response.new(
         
     | 
| 
       20 
     | 
    
         
            -
                  status:  
     | 
| 
       21 
     | 
    
         
            -
                  body:  
     | 
| 
       22 
     | 
    
         
            -
                  headers:  
     | 
| 
      
 22 
     | 
    
         
            +
                  status: 200,
         
     | 
| 
      
 23 
     | 
    
         
            +
                  body: '{"hits": []}',
         
     | 
| 
      
 24 
     | 
    
         
            +
                  headers: {}
         
     | 
| 
       23 
25 
     | 
    
         
             
                )
         
     | 
| 
       24 
26 
     | 
    
         
             
              end
         
     | 
| 
       25 
27 
     | 
    
         | 
| 
         @@ -0,0 +1,70 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'securerandom'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative 'base_test'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            class RecommendClientTest < BaseTest
         
     | 
| 
      
 5 
     | 
    
         
            +
              describe 'Recommendations' do
         
     | 
| 
      
 6 
     | 
    
         
            +
                def test_get_recommendations
         
     | 
| 
      
 7 
     | 
    
         
            +
                  requester = MockRequester.new
         
     | 
| 
      
 8 
     | 
    
         
            +
                  client    = Algolia::Recommend::Client.new(@@search_config, http_requester: requester)
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  # It correctly formats queries using the 'bought-together' model
         
     | 
| 
      
 11 
     | 
    
         
            +
                  client.get_recommendations([{ indexName: 'products', objectID: 'B018APC4LE', model: Algolia::Recommend::Model::BOUGHT_TOGETHER }])
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  # It correctly formats queries using the 'related-products' model
         
     | 
| 
      
 14 
     | 
    
         
            +
                  client.get_recommendations([{ indexName: 'products', objectID: 'B018APC4LE', model: Algolia::Recommend::Model::RELATED_PRODUCTS }])
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  # It correctly formats multiple queries.
         
     | 
| 
      
 17 
     | 
    
         
            +
                  client.get_recommendations(
         
     | 
| 
      
 18 
     | 
    
         
            +
                    [
         
     | 
| 
      
 19 
     | 
    
         
            +
                      { indexName: 'products', objectID: 'B018APC4LE-1', model: Algolia::Recommend::Model::RELATED_PRODUCTS, threshold: 0 },
         
     | 
| 
      
 20 
     | 
    
         
            +
                      { indexName: 'products', objectID: 'B018APC4LE-2', model: Algolia::Recommend::Model::RELATED_PRODUCTS, threshold: 0 }
         
     | 
| 
      
 21 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 22 
     | 
    
         
            +
                  )
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  # It resets the threshold to 0 if it's not numeric.
         
     | 
| 
      
 25 
     | 
    
         
            +
                  client.get_recommendations([{ indexName: 'products', objectID: 'B018APC4LE', model: Algolia::Recommend::Model::BOUGHT_TOGETHER, threshold: nil }])
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  # It passes the threshold correctly if it's numeric.
         
     | 
| 
      
 28 
     | 
    
         
            +
                  client.get_recommendations([{ indexName: 'products', objectID: 'B018APC4LE', model: Algolia::Recommend::Model::BOUGHT_TOGETHER, threshold: 42 }])
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  assert_requests(
         
     | 
| 
      
 31 
     | 
    
         
            +
                    requester,
         
     | 
| 
      
 32 
     | 
    
         
            +
                    [
         
     | 
| 
      
 33 
     | 
    
         
            +
                      { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"bought-together","threshold":0}]}' },
         
     | 
| 
      
 34 
     | 
    
         
            +
                      { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"related-products","threshold":0}]}' },
         
     | 
| 
      
 35 
     | 
    
         
            +
                      { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE-1","model":"related-products","threshold":0},{"indexName":"products","objectID":"B018APC4LE-2","model":"related-products","threshold":0}]}' },
         
     | 
| 
      
 36 
     | 
    
         
            +
                      { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"bought-together","threshold":0}]}' },
         
     | 
| 
      
 37 
     | 
    
         
            +
                      { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"bought-together","threshold":42}]}' }
         
     | 
| 
      
 38 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 39 
     | 
    
         
            +
                  )
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def test_get_related_products
         
     | 
| 
      
 43 
     | 
    
         
            +
                  requester = MockRequester.new
         
     | 
| 
      
 44 
     | 
    
         
            +
                  client    = Algolia::Recommend::Client.new(@@search_config, http_requester: requester)
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  client.get_related_products([{ indexName: 'products', objectID: 'B018APC4LE' }])
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  assert_requests(
         
     | 
| 
      
 49 
     | 
    
         
            +
                    requester,
         
     | 
| 
      
 50 
     | 
    
         
            +
                    [{ method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"related-products","threshold":0}]}' }]
         
     | 
| 
      
 51 
     | 
    
         
            +
                  )
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                def test_get_frequently_bought_together
         
     | 
| 
      
 55 
     | 
    
         
            +
                  requester = MockRequester.new
         
     | 
| 
      
 56 
     | 
    
         
            +
                  client    = Algolia::Recommend::Client.new(@@search_config, http_requester: requester)
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  client.get_frequently_bought_together([{ indexName: 'products', objectID: 'B018APC4LE' }])
         
     | 
| 
      
 59 
     | 
    
         
            +
                  client.get_frequently_bought_together([{ indexName: 'products', objectID: 'B018APC4LE', fallbackParameters: {} }])
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  assert_requests(
         
     | 
| 
      
 62 
     | 
    
         
            +
                    requester,
         
     | 
| 
      
 63 
     | 
    
         
            +
                    [
         
     | 
| 
      
 64 
     | 
    
         
            +
                      { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"bought-together","threshold":0}]}' },
         
     | 
| 
      
 65 
     | 
    
         
            +
                      { method: :post, path: '/1/indexes/*/recommendations', body: '{"requests":[{"indexName":"products","objectID":"B018APC4LE","model":"bought-together","threshold":0}]}' }
         
     | 
| 
      
 66 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 67 
     | 
    
         
            +
                  )
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,3 +1,4 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'securerandom'
         
     | 
| 
       1 
2 
     | 
    
         
             
            require_relative 'base_test'
         
     | 
| 
       2 
3 
     | 
    
         | 
| 
       3 
4 
     | 
    
         
             
            class SearchClientTest < BaseTest
         
     | 
| 
         @@ -215,6 +216,7 @@ class SearchClientTest < BaseTest 
     | 
|
| 
       215 
216 
     | 
    
         | 
| 
       216 
217 
     | 
    
         
             
                def test_api_keys
         
     | 
| 
       217 
218 
     | 
    
         
             
                  assert_equal ['search'], @api_key[:acl]
         
     | 
| 
      
 219 
     | 
    
         
            +
                  assert_equal 'A description', @api_key[:description]
         
     | 
| 
       218 
220 
     | 
    
         | 
| 
       219 
221 
     | 
    
         
             
                  api_keys = @@search_client.list_api_keys[:keys].map do |key|
         
     | 
| 
       220 
222 
     | 
    
         
             
                    key[:value]
         
     | 
| 
         @@ -222,7 +224,9 @@ class SearchClientTest < BaseTest 
     | 
|
| 
       222 
224 
     | 
    
         
             
                  assert_includes api_keys, @api_key[:value]
         
     | 
| 
       223 
225 
     | 
    
         | 
| 
       224 
226 
     | 
    
         
             
                  @@search_client.update_api_key!(@api_key[:value], { maxHitsPerQuery: 42 })
         
     | 
| 
       225 
     | 
    
         
            -
                  updated_api_key =  
     | 
| 
      
 227 
     | 
    
         
            +
                  updated_api_key = retry_test do
         
     | 
| 
      
 228 
     | 
    
         
            +
                    @@search_client.get_api_key(@api_key[:value], test: 'test')
         
     | 
| 
      
 229 
     | 
    
         
            +
                  end
         
     | 
| 
       226 
230 
     | 
    
         
             
                  assert_equal 42, updated_api_key[:maxHitsPerQuery]
         
     | 
| 
       227 
231 
     | 
    
         | 
| 
       228 
232 
     | 
    
         
             
                  @@search_client.delete_api_key!(@api_key[:value])
         
     | 
| 
         @@ -233,18 +237,13 @@ class SearchClientTest < BaseTest 
     | 
|
| 
       233 
237 
     | 
    
         | 
| 
       234 
238 
     | 
    
         
             
                  assert_equal 'Key does not exist', exception.message
         
     | 
| 
       235 
239 
     | 
    
         | 
| 
       236 
     | 
    
         
            -
                   
     | 
| 
       237 
     | 
    
         
            -
                     
     | 
| 
       238 
     | 
    
         
            -
                      @@search_client.restore_api_key!(@api_key[:value])
         
     | 
| 
       239 
     | 
    
         
            -
                      break
         
     | 
| 
       240 
     | 
    
         
            -
                    rescue Algolia::AlgoliaHttpError => e
         
     | 
| 
       241 
     | 
    
         
            -
                      if e.code != 404
         
     | 
| 
       242 
     | 
    
         
            -
                        raise StandardError
         
     | 
| 
       243 
     | 
    
         
            -
                      end
         
     | 
| 
       244 
     | 
    
         
            -
                    end
         
     | 
| 
      
 240 
     | 
    
         
            +
                  retry_test do
         
     | 
| 
      
 241 
     | 
    
         
            +
                    @@search_client.restore_api_key!(@api_key[:value])
         
     | 
| 
       245 
242 
     | 
    
         
             
                  end
         
     | 
| 
       246 
243 
     | 
    
         | 
| 
       247 
     | 
    
         
            -
                  restored_key =  
     | 
| 
      
 244 
     | 
    
         
            +
                  restored_key = retry_test do
         
     | 
| 
      
 245 
     | 
    
         
            +
                    @@search_client.get_api_key(@api_key[:value])
         
     | 
| 
      
 246 
     | 
    
         
            +
                  end
         
     | 
| 
       248 
247 
     | 
    
         | 
| 
       249 
248 
     | 
    
         
             
                  refute_nil restored_key
         
     | 
| 
       250 
249 
     | 
    
         
             
                end
         
     | 
| 
         @@ -333,7 +332,12 @@ class SearchClientTest < BaseTest 
     | 
|
| 
       333 
332 
     | 
    
         
             
                    secured_index1 = secured_client.init_index(@index1.name)
         
     | 
| 
       334 
333 
     | 
    
         
             
                    secured_index2 = secured_client.init_index(@index2.name)
         
     | 
| 
       335 
334 
     | 
    
         | 
| 
       336 
     | 
    
         
            -
                     
     | 
| 
      
 335 
     | 
    
         
            +
                    res = retry_test do
         
     | 
| 
      
 336 
     | 
    
         
            +
                      secured_index1.search('')
         
     | 
| 
      
 337 
     | 
    
         
            +
                    end
         
     | 
| 
      
 338 
     | 
    
         
            +
             
     | 
| 
      
 339 
     | 
    
         
            +
                    assert_equal 1, res[:hits].length
         
     | 
| 
      
 340 
     | 
    
         
            +
             
     | 
| 
       337 
341 
     | 
    
         
             
                    exception = assert_raises Algolia::AlgoliaHttpError do
         
     | 
| 
       338 
342 
     | 
    
         
             
                      secured_index2.search('')
         
     | 
| 
       339 
343 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -366,5 +370,96 @@ class SearchClientTest < BaseTest 
     | 
|
| 
       366 
370 
     | 
    
         
             
                    assert_equal 'The SecuredAPIKey doesn\'t have a validUntil parameter.', exception.message
         
     | 
| 
       367 
371 
     | 
    
         
             
                  end
         
     | 
| 
       368 
372 
     | 
    
         
             
                end
         
     | 
| 
      
 373 
     | 
    
         
            +
             
     | 
| 
      
 374 
     | 
    
         
            +
                describe 'Custom Dictionaries' do
         
     | 
| 
      
 375 
     | 
    
         
            +
                  def before_all
         
     | 
| 
      
 376 
     | 
    
         
            +
                    @client = Algolia::Search::Client.create(APPLICATION_ID_2, ADMIN_KEY_2)
         
     | 
| 
      
 377 
     | 
    
         
            +
                  end
         
     | 
| 
      
 378 
     | 
    
         
            +
             
     | 
| 
      
 379 
     | 
    
         
            +
                  def test_stopwords_dictionaries
         
     | 
| 
      
 380 
     | 
    
         
            +
                    entry_id = SecureRandom.hex
         
     | 
| 
      
 381 
     | 
    
         
            +
                    assert_equal 0, @client.search_dictionary_entries('stopwords', entry_id)[:nbHits]
         
     | 
| 
      
 382 
     | 
    
         
            +
             
     | 
| 
      
 383 
     | 
    
         
            +
                    entry = {
         
     | 
| 
      
 384 
     | 
    
         
            +
                      objectID: entry_id,
         
     | 
| 
      
 385 
     | 
    
         
            +
                      language: 'en',
         
     | 
| 
      
 386 
     | 
    
         
            +
                      word: 'down'
         
     | 
| 
      
 387 
     | 
    
         
            +
                    }
         
     | 
| 
      
 388 
     | 
    
         
            +
                    @client.save_dictionary_entries!('stopwords', [entry])
         
     | 
| 
      
 389 
     | 
    
         
            +
             
     | 
| 
      
 390 
     | 
    
         
            +
                    stopwords = @client.search_dictionary_entries('stopwords', entry_id)
         
     | 
| 
      
 391 
     | 
    
         
            +
                    assert_equal 1, stopwords[:nbHits]
         
     | 
| 
      
 392 
     | 
    
         
            +
                    assert_equal stopwords[:hits][0][:objectID], entry[:objectID]
         
     | 
| 
      
 393 
     | 
    
         
            +
                    assert_equal stopwords[:hits][0][:word], entry[:word]
         
     | 
| 
      
 394 
     | 
    
         
            +
             
     | 
| 
      
 395 
     | 
    
         
            +
                    @client.delete_dictionary_entries!('stopwords', [entry_id])
         
     | 
| 
      
 396 
     | 
    
         
            +
                    assert_equal 0, @client.search_dictionary_entries('stopwords', entry_id)[:nbHits]
         
     | 
| 
      
 397 
     | 
    
         
            +
             
     | 
| 
      
 398 
     | 
    
         
            +
                    old_dictionary_state   = @client.search_dictionary_entries('stopwords', '')
         
     | 
| 
      
 399 
     | 
    
         
            +
                    old_dictionary_entries = old_dictionary_state[:hits].map do |hit|
         
     | 
| 
      
 400 
     | 
    
         
            +
                      hit.reject { |key| key == :type }
         
     | 
| 
      
 401 
     | 
    
         
            +
                    end
         
     | 
| 
      
 402 
     | 
    
         
            +
             
     | 
| 
      
 403 
     | 
    
         
            +
                    @client.save_dictionary_entries!('stopwords', [entry])
         
     | 
| 
      
 404 
     | 
    
         
            +
                    assert_equal 1, @client.search_dictionary_entries('stopwords', entry_id)[:nbHits]
         
     | 
| 
      
 405 
     | 
    
         
            +
             
     | 
| 
      
 406 
     | 
    
         
            +
                    @client.replace_dictionary_entries!('stopwords', old_dictionary_entries)
         
     | 
| 
      
 407 
     | 
    
         
            +
                    assert_equal 0, @client.search_dictionary_entries('stopwords', entry_id)[:nbHits]
         
     | 
| 
      
 408 
     | 
    
         
            +
             
     | 
| 
      
 409 
     | 
    
         
            +
                    stopwords_settings = {
         
     | 
| 
      
 410 
     | 
    
         
            +
                      disableStandardEntries: {
         
     | 
| 
      
 411 
     | 
    
         
            +
                        stopwords: {
         
     | 
| 
      
 412 
     | 
    
         
            +
                          en: true
         
     | 
| 
      
 413 
     | 
    
         
            +
                        }
         
     | 
| 
      
 414 
     | 
    
         
            +
                      }
         
     | 
| 
      
 415 
     | 
    
         
            +
                    }
         
     | 
| 
      
 416 
     | 
    
         
            +
             
     | 
| 
      
 417 
     | 
    
         
            +
                    @client.set_dictionary_settings!(stopwords_settings)
         
     | 
| 
      
 418 
     | 
    
         
            +
             
     | 
| 
      
 419 
     | 
    
         
            +
                    assert_equal @client.get_dictionary_settings, stopwords_settings
         
     | 
| 
      
 420 
     | 
    
         
            +
                  end
         
     | 
| 
      
 421 
     | 
    
         
            +
             
     | 
| 
      
 422 
     | 
    
         
            +
                  def test_plurals_dictionaries
         
     | 
| 
      
 423 
     | 
    
         
            +
                    entry_id = SecureRandom.hex
         
     | 
| 
      
 424 
     | 
    
         
            +
                    assert_equal 0, @client.search_dictionary_entries('plurals', entry_id)[:nbHits]
         
     | 
| 
      
 425 
     | 
    
         
            +
             
     | 
| 
      
 426 
     | 
    
         
            +
                    entry = {
         
     | 
| 
      
 427 
     | 
    
         
            +
                      objectID: entry_id,
         
     | 
| 
      
 428 
     | 
    
         
            +
                      language: 'fr',
         
     | 
| 
      
 429 
     | 
    
         
            +
                      words: %w(cheval chevaux)
         
     | 
| 
      
 430 
     | 
    
         
            +
                    }
         
     | 
| 
      
 431 
     | 
    
         
            +
                    @client.save_dictionary_entries!('plurals', [entry])
         
     | 
| 
      
 432 
     | 
    
         
            +
             
     | 
| 
      
 433 
     | 
    
         
            +
                    plurals = @client.search_dictionary_entries('plurals', entry_id)
         
     | 
| 
      
 434 
     | 
    
         
            +
                    assert_equal 1, plurals[:nbHits]
         
     | 
| 
      
 435 
     | 
    
         
            +
                    assert_equal plurals[:hits][0][:objectID], entry[:objectID]
         
     | 
| 
      
 436 
     | 
    
         
            +
                    assert_equal plurals[:hits][0][:words], entry[:words]
         
     | 
| 
      
 437 
     | 
    
         
            +
             
     | 
| 
      
 438 
     | 
    
         
            +
                    @client.delete_dictionary_entries!('plurals', [entry_id])
         
     | 
| 
      
 439 
     | 
    
         
            +
                    assert_equal 0, @client.search_dictionary_entries('plurals', entry_id)[:nbHits]
         
     | 
| 
      
 440 
     | 
    
         
            +
                  end
         
     | 
| 
      
 441 
     | 
    
         
            +
             
     | 
| 
      
 442 
     | 
    
         
            +
                  def test_compounds_dictionaries
         
     | 
| 
      
 443 
     | 
    
         
            +
                    entry_id = SecureRandom.hex
         
     | 
| 
      
 444 
     | 
    
         
            +
                    assert_equal 0, @client.search_dictionary_entries('compounds', entry_id)[:nbHits]
         
     | 
| 
      
 445 
     | 
    
         
            +
             
     | 
| 
      
 446 
     | 
    
         
            +
                    entry = {
         
     | 
| 
      
 447 
     | 
    
         
            +
                      objectID: entry_id,
         
     | 
| 
      
 448 
     | 
    
         
            +
                      language: 'de',
         
     | 
| 
      
 449 
     | 
    
         
            +
                      word: 'kopfschmerztablette',
         
     | 
| 
      
 450 
     | 
    
         
            +
                      decomposition: %w(kopf schmerz tablette)
         
     | 
| 
      
 451 
     | 
    
         
            +
                    }
         
     | 
| 
      
 452 
     | 
    
         
            +
                    @client.save_dictionary_entries!('compounds', [entry])
         
     | 
| 
      
 453 
     | 
    
         
            +
             
     | 
| 
      
 454 
     | 
    
         
            +
                    compounds = @client.search_dictionary_entries('compounds', entry_id)
         
     | 
| 
      
 455 
     | 
    
         
            +
                    assert_equal 1, compounds[:nbHits]
         
     | 
| 
      
 456 
     | 
    
         
            +
                    assert_equal compounds[:hits][0][:objectID], entry[:objectID]
         
     | 
| 
      
 457 
     | 
    
         
            +
                    assert_equal compounds[:hits][0][:word], entry[:word]
         
     | 
| 
      
 458 
     | 
    
         
            +
                    assert_equal compounds[:hits][0][:decomposition], entry[:decomposition]
         
     | 
| 
      
 459 
     | 
    
         
            +
             
     | 
| 
      
 460 
     | 
    
         
            +
                    @client.delete_dictionary_entries!('compounds', [entry_id])
         
     | 
| 
      
 461 
     | 
    
         
            +
                    assert_equal 0, @client.search_dictionary_entries('compounds', entry_id)[:nbHits]
         
     | 
| 
      
 462 
     | 
    
         
            +
                  end
         
     | 
| 
      
 463 
     | 
    
         
            +
                end
         
     | 
| 
       369 
464 
     | 
    
         
             
              end
         
     | 
| 
       370 
465 
     | 
    
         
             
            end
         
     | 
| 
         @@ -274,6 +274,9 @@ class SearchIndexTest < BaseTest 
     | 
|
| 
       274 
274 
     | 
    
         
             
                  @index.set_settings!(settings)
         
     | 
| 
       275 
275 
     | 
    
         | 
| 
       276 
276 
     | 
    
         
             
                  assert_equal @index.get_settings, settings
         
     | 
| 
      
 277 
     | 
    
         
            +
             
     | 
| 
      
 278 
     | 
    
         
            +
                  # check that the forwardToReplicas parameter is passed correctly
         
     | 
| 
      
 279 
     | 
    
         
            +
                  assert @index.set_settings!(settings, { forwardToReplicas: true })
         
     | 
| 
       277 
280 
     | 
    
         
             
                end
         
     | 
| 
       278 
281 
     | 
    
         
             
              end
         
     | 
| 
       279 
282 
     | 
    
         |