From 2578da02eec96741dc5fa4276d5bc52aceea0129 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 7 Oct 2024 15:34:21 +0200 Subject: [PATCH 01/40] chore: update algolia version --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 3352617..6d8c274 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source "http://rubygems.org" gem 'json', '>= 1.5.1' -gem 'algolia', '< 3.0.0' +gem 'algolia', '>= 3.0.0' if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' gem 'rubysl', '~> 2.0', :platform => :rbx From 9b1c417dc9e358c01ce54ebbf61c84d9e8c6068e Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Wed, 9 Oct 2024 10:49:50 +0200 Subject: [PATCH 02/40] WIP: fix tests until FowardToReplicas --- Gemfile | 2 +- lib/algoliasearch-rails.rb | 224 +++++++++++++++++++++-------- lib/algoliasearch/configuration.rb | 3 +- spec/integration_spec.rb | 151 +++++++++---------- spec/spec_helper.rb | 10 +- 5 files changed, 246 insertions(+), 144 deletions(-) diff --git a/Gemfile b/Gemfile index 6d8c274..7226ff4 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source "http://rubygems.org" gem 'json', '>= 1.5.1' -gem 'algolia', '>= 3.0.0' +gem 'algolia', '>= 3.4.0' if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' gem 'rubysl', '~> 2.0', :platform => :rbx diff --git a/lib/algoliasearch-rails.rb b/lib/algoliasearch-rails.rb index 82754dc..a225c2c 100644 --- a/lib/algoliasearch-rails.rb +++ b/lib/algoliasearch-rails.rb @@ -95,7 +95,6 @@ def initialize(options, &block) def use_serializer(serializer) @serializer = serializer - # instance_variable_set("@serializer", serializer) end def attribute(*names, &block) @@ -240,11 +239,16 @@ def get_setting(name) instance_variable_get("@#{name}") end + # TODO def to_settings + Algolia::Search::IndexSettings.new(to_hash) + end + + def to_hash settings = {} OPTIONS.each do |k| v = get_setting(k) - settings[k] = v if !v.nil? + settings[setting_name(k)] = v if !v.nil? end if !@options[:replica] @@ -256,9 +260,18 @@ def to_settings end settings.delete(:replicas) if settings[:replicas].empty? end + settings end + def setting_name(name) + name.to_s.gsub(/::/, '/'). + gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). + gsub(/([a-z\d])([A-Z])/,'\1_\2'). + tr("-", "_"). + downcase + end + def add_index(index_name, options = {}, &block) raise ArgumentError.new('Cannot specify additional index on a replica index') if @options[:replica] raise ArgumentError.new('No block given') if !block_given? @@ -289,19 +302,20 @@ def additional_indexes # this class wraps an Algolia::Index object ensuring all raised exceptions # are correctly logged or thrown depending on the `raise_on_failure` option + # TODO class SafeIndex def initialize(name, raise_on_failure) @index = AlgoliaSearch.client.init_index(name) @raise_on_failure = raise_on_failure.nil? || raise_on_failure end - ::Algolia::Search::Index.instance_methods(false).each do |m| - define_method(m) do |*args, &block| - SafeIndex.log_or_throw(m, @raise_on_failure) do - @index.send(m, *args, &block) - end - end - end + # ::Algolia::Search::Index.instance_methods(false).each do |m| + # define_method(m) do |*args, &block| + # SafeIndex.log_or_throw(m, @raise_on_failure) do + # @index.send(m, *args, &block) + # end + # end + # end # special handling of wait_task to handle null task_id def wait_task(task_id) @@ -493,11 +507,13 @@ def algolia_without_auto_index_scope Thread.current["algolia_without_auto_index_scope_for_#{self.model_name}"] end + # TODO def algolia_reindex!(batch_size = AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZE, synchronous = false) return if algolia_without_auto_index_scope algolia_configurations.each do |options, settings| next if algolia_indexing_disabled?(options) - index = algolia_ensure_init(options, settings) + ensure_init_new(options, settings) + index_name = algolia_index_name(options) next if options[:replica] last_task = nil @@ -505,7 +521,7 @@ def algolia_reindex!(batch_size = AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SI if algolia_conditional_index?(options) # delete non-indexable objects ids = group.select { |o| !algolia_indexable?(o, options) }.map { |o| algolia_object_id_of(o, options) } - index.delete_objects(ids.select { |id| !id.blank? }) + AlgoliaSearch.client.delete_objects(index_name, ids.select { |id| !id.blank? }) # select only indexable objects group = group.select { |o| algolia_indexable?(o, options) } end @@ -516,13 +532,14 @@ def algolia_reindex!(batch_size = AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SI end attributes.merge 'objectID' => algolia_object_id_of(o, options) end - last_task = index.save_objects(objects) + last_task = AlgoliaSearch.client.save_objects(index_name, objects).last.task_id end - index.wait_task(last_task.raw_response["taskID"]) if last_task and (synchronous || options[:synchronous]) + AlgoliaSearch.client.wait_for_task(index_name, last_task) if last_task and (synchronous || options[:synchronous]) end nil end + # TODO # reindex whole database using a extra temporary index + move operation def algolia_reindex(batch_size = AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZE, synchronous = false) return if algolia_without_auto_index_scope @@ -530,28 +547,31 @@ def algolia_reindex(batch_size = AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZ next if algolia_indexing_disabled?(options) next if options[:replica] + ensure_init_new(options, settings) + index_name = algolia_index_name(options) + # fetch the master settings - master_index = algolia_ensure_init(options, settings) - master_settings = master_index.get_settings rescue {} # if master doesn't exist yet + + master_settings = AlgoliaSearch.client.get_settings(index_name).to_hash rescue {} # if master doesn't exist yet master_exists = master_settings != {} - master_settings.merge!(JSON.parse(settings.to_settings.to_json)) # convert symbols to strings + master_settings.merge!(settings.to_hash) # remove the replicas of the temporary index master_settings.delete :replicas master_settings.delete 'replicas' # init temporary index - src_index_name = algolia_index_name(options) - tmp_index_name = "#{src_index_name}.tmp" + tmp_index_name = "#{index_name}.tmp" tmp_options = options.merge({ :index_name => tmp_index_name }) tmp_options.delete(:per_environment) # already included in the temporary index_name tmp_settings = settings.dup if options[:check_settings] == false && master_exists - AlgoliaSearch.client.copy_index!(src_index_name, tmp_index_name, { scope: %w[settings synonyms rules] }) - tmp_index = SafeIndex.new(tmp_index_name, !!options[:raise_on_failure]) - else - tmp_index = algolia_ensure_init(tmp_options, tmp_settings, master_settings) + task_id = AlgoliaSearch.client.operation_index( + index_name, + Algolia::Search::OperationIndexParams.new(operation: "copy", destination: tmp_index_name, scope: %w[settings synonyms rules]) + ).task_id + AlgoliaSearch.client.wait_for_task(index_name, task_id) end algolia_find_in_batches(batch_size) do |group| @@ -560,15 +580,20 @@ def algolia_reindex(batch_size = AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZ group = group.select { |o| algolia_indexable?(o, tmp_options) } end objects = group.map { |o| tmp_settings.get_attributes(o).merge 'objectID' => algolia_object_id_of(o, tmp_options) } - tmp_index.save_objects(objects) + + AlgoliaSearch.client.save_objects(tmp_index_name, objects) end - move_task = SafeIndex.move_index(tmp_index.name, src_index_name) - master_index.wait_task(move_task.raw_response["taskID"]) if synchronous || options[:synchronous] + task_id = AlgoliaSearch.client.operation_index( + tmp_index_name, + Algolia::Search::OperationIndexParams.new(operation: "move", destination: index_name) + ).task_id + AlgoliaSearch.client.wait_for_task(index_name, task_id) if synchronous || options[:synchronous] end nil end + # TODO def algolia_set_settings(synchronous = false) algolia_configurations.each do |options, settings| if options[:primary_settings] && options[:inherit] @@ -586,77 +611,94 @@ def algolia_set_settings(synchronous = false) end end + # TODO def algolia_index_objects(objects, synchronous = false) algolia_configurations.each do |options, settings| next if algolia_indexing_disabled?(options) - index = algolia_ensure_init(options, settings) + ensure_init_new(options, settings) + index_name = algolia_index_name(options) + next if options[:replica] - task = index.save_objects(objects.map { |o| settings.get_attributes(o).merge 'objectID' => algolia_object_id_of(o, options) }) - index.wait_task(task.raw_response["taskID"]) if synchronous || options[:synchronous] + tasks = AlgoliaSearch.client.save_objects(index_name, objects.map { |o| settings.get_attributes(o).merge 'objectID' => algolia_object_id_of(o, options) }) + tasks.each do |task| + AlgoliaSearch.client.wait_for_task(index_name, task.task_id) if synchronous || options[:synchronous] + end end end + # TODO def algolia_index!(object, synchronous = false) return if algolia_without_auto_index_scope algolia_configurations.each do |options, settings| next if algolia_indexing_disabled?(options) + object_id = algolia_object_id_of(object, options) - index = algolia_ensure_init(options, settings) + index_name = algolia_index_name(options) + ensure_init_new(options, settings) next if options[:replica] + if algolia_indexable?(object, options) raise ArgumentError.new("Cannot index a record with a blank objectID") if object_id.blank? + resp = AlgoliaSearch.client.save_object(index_name, settings.get_attributes(object).merge({ 'objectID' => algolia_object_id_of(object, options) })) if synchronous || options[:synchronous] - index.save_object!(settings.get_attributes(object).merge 'objectID' => algolia_object_id_of(object, options)) - else - index.save_object(settings.get_attributes(object).merge 'objectID' => algolia_object_id_of(object, options)) + AlgoliaSearch.client.wait_for_task(index_name, resp.task_id) end elsif algolia_conditional_index?(options) && !object_id.blank? # remove non-indexable objects + resp = AlgoliaSearch.client.delete_object(index_name, object_id) if synchronous || options[:synchronous] - index.delete_object!(object_id) - else - index.delete_object(object_id) + AlgoliaSearch.client.wait_for_task(index_name, resp.task_id) end end end nil end + # TODO def algolia_remove_from_index!(object, synchronous = false) return if algolia_without_auto_index_scope object_id = algolia_object_id_of(object) raise ArgumentError.new("Cannot index a record with a blank objectID") if object_id.blank? algolia_configurations.each do |options, settings| next if algolia_indexing_disabled?(options) - index = algolia_ensure_init(options, settings) + ensure_init_new(options, settings) + index_name = algolia_index_name(options) + next if options[:replica] + + resp = AlgoliaSearch.client.delete_object(index_name, object_id) if synchronous || options[:synchronous] - index.delete_object!(object_id) - else - index.delete_object(object_id) + AlgoliaSearch.client.wait_for_task(index_name, resp.task_id) end end nil end + # TODO def algolia_clear_index!(synchronous = false) algolia_configurations.each do |options, settings| - next if algolia_indexing_disabled?(options) - index = algolia_ensure_init(options, settings) - next if options[:replica] - synchronous || options[:synchronous] ? index.clear_objects! : index.clear_objects - @algolia_indexes[settings] = nil + next if algolia_indexing_disabled?(options) || options[:replica] + + ensure_init_new(options, settings) + index_name = algolia_index_name(options) + res = AlgoliaSearch.client.clear_objects(index_name) + + if synchronous || options[:synchronous] + AlgoliaSearch.client.wait_for_task(index_name, res.task_id) + end end nil end + # TODO + def algolia_raw_search(q, params = {}) - index_name = params.delete(:index) || + index_name_base = params.delete(:index) || params.delete('index') || params.delete(:replica) || params.delete('replica') - index = algolia_index(index_name) - index.search(q, Hash[params.map { |k,v| [k.to_s, v.to_s] }]) + index_name = algolia_index_name(algoliasearch_options, index_name_base) + AlgoliaSearch.client.search_single_index(index_name,Hash[params.to_h.map { |k,v| [k.to_s, v.to_s] }].merge({query: q})).to_hash end module AdditionalMethods @@ -672,7 +714,7 @@ def algolia_raw_answer end def algolia_facets - @algolia_json['facets'] + @algolia_json[:facets] end private @@ -681,6 +723,7 @@ def algolia_init_raw_answer(json) end end + # TODO def algolia_search(q, params = {}) if AlgoliaSearch.configuration[:pagination_backend] # kaminari, will_paginate, and pagy start pagination at 1, Algolia starts at 0 @@ -688,7 +731,7 @@ def algolia_search(q, params = {}) params[:page] -= 1 if params[:page].to_i > 0 end json = algolia_raw_search(q, params) - hit_ids = json['hits'].map { |hit| hit['objectID'] } + hit_ids = json[:hits].map { |hit| hit[:objectID] } if defined?(::Mongoid::Document) && self.include?(::Mongoid::Document) condition_key = algolia_object_id_method.in else @@ -697,36 +740,39 @@ def algolia_search(q, params = {}) results_by_id = algoliasearch_options[:type].where(condition_key => hit_ids).index_by do |hit| algolia_object_id_of(hit) end - results = json['hits'].map do |hit| - o = results_by_id[hit['objectID'].to_s] + results = json[:hits].map do |hit| + o = results_by_id[hit[:objectID].to_s] if o - o.highlight_result = hit['_highlightResult'] - o.snippet_result = hit['_snippetResult'] + o.highlight_result = hit[:_highlightResult] + o.snippet_result = hit[:_snippetResult] o end end.compact # Algolia has a default limit of 1000 retrievable hits - total_hits = json['nbHits'].to_i < json['nbPages'].to_i * json['hitsPerPage'].to_i ? - json['nbHits'].to_i: json['nbPages'].to_i * json['hitsPerPage'].to_i - res = AlgoliaSearch::Pagination.create(results, total_hits, algoliasearch_options.merge({ :page => json['page'].to_i + 1, :per_page => json['hitsPerPage'] })) + total_hits = json[:nbHits].to_i < json[:nbPages].to_i * json[:hitsPerPage].to_i ? + json[:nbHits].to_i: json[:nbPages].to_i * json[:hitsPerPage].to_i + res = AlgoliaSearch::Pagination.create(results, total_hits, algoliasearch_options.merge({ :page => json[:page].to_i + 1, :per_page => json[:hitsPerPage] })) res.extend(AdditionalMethods) res.send(:algolia_init_raw_answer, json) res end + # TODO def algolia_search_for_facet_values(facet, text, params = {}) index_name = params.delete(:index) || params.delete('index') || params.delete(:replica) || params.delete('replicas') - index = algolia_index(index_name) - query = Hash[params.map { |k, v| [k.to_s, v.to_s] }] - index.search_for_facet_values(facet, text, query)['facetHits'] + index_name ||= algolia_index_name(algoliasearch_options) + req = Algolia::Search::SearchForFacetValuesRequest.new({facet_query: text, params: params.to_query}) + + AlgoliaSearch.client.search_for_facet_values(index_name, facet, req).facet_hits end # deprecated (renaming) alias :algolia_search_facet :algolia_search_for_facet_values + # TODO def algolia_index(name = nil) if name algolia_configurations.each do |o, s| @@ -737,9 +783,19 @@ def algolia_index(name = nil) algolia_ensure_init end - def algolia_index_name(options = nil) + def ensure_algolia_index(name = nil) + if name + algolia_configurations.each do |o, s| + return ensure_init_new(o, s) if o[:index_name].to_s == name.to_s + end + raise ArgumentError.new("Invalid index/replica name: #{name}") + end + ensure_init_new + end + + def algolia_index_name(options = nil, index_name = nil) options ||= algoliasearch_options - name = options[:index_name] || model_name.to_s.gsub('::', '_') + name = index_name || options[:index_name] || model_name.to_s.gsub('::', '_') name = "#{name}_#{Rails.env.to_s}" if options[:per_environment] name end @@ -774,6 +830,7 @@ def algolia_must_reindex?(object) protected + # TODO - deprecate def algolia_ensure_init(options = nil, settings = nil, index_settings = nil) raise ArgumentError.new('No `algoliasearch` block found in your model.') if algoliasearch_settings.nil? @@ -806,8 +863,51 @@ def algolia_ensure_init(options = nil, settings = nil, index_settings = nil) @algolia_indexes[settings] end + def ensure_init_new(options = nil, settings = nil, index_settings_hash = nil) + raise ArgumentError.new('No `algoliasearch` block found in your model.') if algoliasearch_settings.nil? + + @algolia_indexes_init ||= {} + + options ||= algoliasearch_options + settings ||= algoliasearch_settings + + return if @algolia_indexes_init[settings] + + index_name = algolia_index_name(options) + + + index_settings_hash ||= settings.to_settings.to_hash + index_settings_hash = options[:primary_settings].to_settings.to_hash.merge(index_settings_hash) if options[:inherit] + replicas = index_settings_hash.delete(:replicas) || index_settings_hash.delete('replicas') + index_settings_hash[:replicas] = replicas unless replicas.nil? || options[:inherit] + + options[:check_settings] = true if options[:check_settings].nil? + + current_settings = if options[:check_settings] && !algolia_indexing_disabled?(options) + AlgoliaSearch.client.get_settings(index_name, {:getVersion => 1}).to_hash rescue nil # if the index doesn't exist + end + + if !algolia_indexing_disabled?(options) && options[:check_settings] && algoliasearch_settings_changed?(current_settings, index_settings_hash) + s = index_settings_hash.map do |k, v| + [settings.setting_name(k), v] + end.to_h + + synonyms = s.delete("synonyms") || s.delete(:synonyms) + unless synonyms.nil? || synonyms.empty? + resp = AlgoliaSearch.client.save_synonyms(index_name,synonyms.map {|s| Algolia::Search::SynonymHit.new({object_id: s.join("-"), synonyms: s, type: "synonym"}) } ) + AlgoliaSearch.client.wait_for_task(index_name, resp.task_id) if options[:synchronous] + end + + resp = AlgoliaSearch.client.set_settings(index_name, Algolia::Search::IndexSettings.new(s)) + AlgoliaSearch.client.wait_for_task(index_name, resp.task_id) if options[:synchronous] + end + + return + end + private + # TODO def algolia_configurations raise ArgumentError.new('No `algoliasearch` block found in your model.') if algoliasearch_settings.nil? if @configurations.nil? @@ -843,7 +943,7 @@ def algolia_object_id_changed?(o, options = nil) def algoliasearch_settings_changed?(prev, current) return true if prev.nil? current.each do |k, v| - prev_v = prev[k.to_s] + prev_v = prev[k.to_sym] if v.is_a?(Array) and prev_v.is_a?(Array) # compare array of strings, avoiding symbols VS strings comparison return true if v.map { |x| x.to_s } != prev_v.map { |x| x.to_s } diff --git a/lib/algoliasearch/configuration.rb b/lib/algoliasearch/configuration.rb index cd48b49..3b6bda3 100644 --- a/lib/algoliasearch/configuration.rb +++ b/lib/algoliasearch/configuration.rb @@ -37,8 +37,9 @@ def client @client end + # TODO def setup_client - @client = Algolia::Search::Client.new(Algolia::Search::Config.new(@@configuration), client_opts) + @client = Algolia::SearchClient.create(@@configuration[:application_id], @@configuration[:api_key]) end def default_configuration diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 18a71a4..7beadf2 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -294,8 +294,9 @@ def nb_children end # create this index before the class actually loads, to ensure the customRanking is updated -index = AlgoliaSearch.client.init_index(safe_index_name('City_replica2')) -index.set_settings!({'customRanking' => ['desc(d)']}) +index_name = safe_index_name('City_replica2') +res = AlgoliaSearch.client.set_settings(index_name, Algolia::Search::IndexSettings.new(custom_ranking: ['desc(d)'])) +AlgoliaSearch.client.wait_for_task(index_name, res.task_id) class City < ActiveRecord::Base include AlgoliaSearch @@ -313,12 +314,12 @@ def geoloc_array add_attribute :a_null_lat, :a_lng customRanking ['desc(b)'] - add_replica safe_index_name('City_replica1'), :per_environment => true do + add_replica safe_index_name('City_replica1'), :per_environment => true, :synchronous => true do searchableAttributes ['country'] customRanking ['asc(a)'] end - add_replica safe_index_name('City_replica2'), :per_environment => true do + add_replica safe_index_name('City_replica2'), :per_environment => true, :synchronous => true do customRanking ['asc(a)', 'desc(c)'] end end @@ -364,8 +365,8 @@ def public? describe 'DisabledIndexing' do it 'should not call get_settings' do - expect_any_instance_of(Algolia::Search::Index).not_to receive(:get_settings) - DisabledIndexing.send(:algolia_ensure_init) + expect_any_instance_of(Algolia::SearchClient).not_to receive(:get_settings) + DisabledIndexing.send(:ensure_init_new) end end @@ -373,7 +374,7 @@ def public? before(:each) do # NOTE: # Redefine below class *each* time to avoid the cache in the class. - # If the cahce is ready, algolia_ensure_init call neither set_settings nor set_settings! ever. + # If the cache is ready, algolia_ensure_init call neither set_settings nor set_settings! ever. Object.send(:remove_const, :EnableCheckSettingsSynchronously) if Object.constants.include?(:EnableCheckSettingsSynchronously) class EnableCheckSettingsSynchronously < ActiveRecord::Base include AlgoliaSearch @@ -389,9 +390,9 @@ class EnableCheckSettingsSynchronously < ActiveRecord::Base end it 'should call set_setting with wait_task(sync)' do - expect_any_instance_of(Algolia::Search::Index).to receive(:set_settings).and_call_original # wait_task use this return val - expect_any_instance_of(Algolia::Search::Index).to receive(:wait_task) - EnableCheckSettingsSynchronously.send(:algolia_ensure_init) + expect_any_instance_of(Algolia::SearchClient).to receive(:set_settings).and_call_original # wait_task use this return val + expect_any_instance_of(Algolia::SearchClient).to receive(:wait_for_task) + EnableCheckSettingsSynchronously.send(:ensure_init_new) end end @@ -401,8 +402,8 @@ class EnableCheckSettingsSynchronously < ActiveRecord::Base end it 'should not call set_setting' do - expect_any_instance_of(Algolia::Search::Index).not_to receive(:set_settings) - EnableCheckSettingsSynchronously.send(:algolia_ensure_init) + expect_any_instance_of(Algolia::SearchClient).not_to receive(:set_settings) + EnableCheckSettingsSynchronously.send(:ensure_init_new) end end end @@ -411,7 +412,7 @@ class EnableCheckSettingsSynchronously < ActiveRecord::Base before(:each) do # NOTE: # Redefine below class *each* time to avoid the cache in the class. - # If the cahce is ready, algolia_ensure_init call neither set_settings nor set_settings! ever. + # If the cache is ready, algolia_ensure_init call neither set_settings nor set_settings! ever. Object.send(:remove_const, :EnableCheckSettingsAsynchronously) if Object.constants.include?(:EnableCheckSettingsAsynchronously) class EnableCheckSettingsAsynchronously < ActiveRecord::Base include AlgoliaSearch @@ -427,9 +428,9 @@ class EnableCheckSettingsAsynchronously < ActiveRecord::Base end it 'should call set_setting without wait_task(sync)' do - expect_any_instance_of(Algolia::Search::Index).to receive(:set_settings) - expect_any_instance_of(Algolia::Search::Index).not_to receive(:wait_task) - EnableCheckSettingsAsynchronously.send(:algolia_ensure_init) + expect_any_instance_of(Algolia::SearchClient).to receive(:set_settings) + expect_any_instance_of(Algolia::SearchClient).not_to receive(:wait_for_task) + EnableCheckSettingsAsynchronously.send(:ensure_init_new) end end @@ -439,8 +440,8 @@ class EnableCheckSettingsAsynchronously < ActiveRecord::Base end it 'should not call set_setting' do - expect_any_instance_of(Algolia::Search::Index).not_to receive(:set_settings) - EnableCheckSettingsAsynchronously.send(:algolia_ensure_init) + expect_any_instance_of(Algolia::SearchClient).not_to receive(:set_settings) + EnableCheckSettingsAsynchronously.send(:ensure_init_new) end end end @@ -451,8 +452,8 @@ class EnableCheckSettingsAsynchronously < ActiveRecord::Base end it 'should call get_settings' do - expect_any_instance_of(Algolia::Search::Index).to receive(:get_settings) - SequelBook.send(:algolia_ensure_init) + expect_any_instance_of(Algolia::SearchClient).to receive(:get_settings) + SequelBook.send(:ensure_init_new) end it "should index the book" do @@ -658,8 +659,8 @@ class SerializedObject < ActiveRecord::Base it "should convert to utf-8" do EncodedString.create! results = EncodedString.raw_search '' - expect(results['hits'].size).to eq(1) - expect(results['hits'].first['value']).to eq("\xC2\xA0\xE2\x80\xA2\xC2\xA0".force_encoding('utf-8')) + expect(results[:hits].size).to eq(1) + expect(results[:hits].first[:value]).to eq("\xC2\xA0\xE2\x80\xA2\xC2\xA0".force_encoding('utf-8')) end end end @@ -768,7 +769,7 @@ class SerializedObject < ActiveRecord::Base describe 'Namespaced::Model' do before(:all) do - Namespaced::Model.index.clear_objects! + Namespaced::Model.clear_index!(true) end it "should have an index name without :: hierarchy" do @@ -825,11 +826,14 @@ class SerializedObject < ActiveRecord::Base @i1.children << NestedItem.create(:hidden => true) << NestedItem.create(:hidden => true) NestedItem.where(:id => [@i1.id, @i2.id]).reindex!(AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZE, true) - result = NestedItem.index.get_object(@i1.id) - result['nb_children'].should == 2 + # result = AlgoliaSearch.client.get_object(NestedItem.index_name, @i1.id) # TODO: should be bugfixed and should replace the line below + result = AlgoliaSearch.client.get_objects(Algolia::Search::GetObjectsParams.new( + requests: [Algolia::Search::GetObjectsRequest.new(object_id: 'objectID1', index_name: 'my_index')] + )).results.first + result[:nb_children].should == 2 result = NestedItem.raw_search('') - result['nbHits'].should == 1 + result[:nbHits].should == 1 if @i2.respond_to? :update_attributes @i2.update_attributes :hidden => false @@ -838,7 +842,7 @@ class SerializedObject < ActiveRecord::Base end result = NestedItem.raw_search('') - result['nbHits'].should == 2 + result[:nbHits].should == 2 end end @@ -870,8 +874,8 @@ class SerializedObject < ActiveRecord::Base it "should be raw searchable" do results = Color.raw_search("blue") - results['hits'].size.should eq(1) - results['nbHits'].should eq(1) + results[:hits].size.should eq(1) + results[:nbHits].should eq(1) end it "should not auto index if scoped" do @@ -940,7 +944,7 @@ class SerializedObject < ActiveRecord::Base it "should index an array of objects" do json = Color.raw_search('') Color.index_objects Color.limit(1), true # reindex last color, `limit` is incompatible with the reindex! method - json['nbHits'].should eq(Color.raw_search('')['nbHits']) + json[:nbHits].should eq(Color.raw_search('')[:nbHits]) end it "should not index non-saved object" do @@ -956,11 +960,11 @@ class SerializedObject < ActiveRecord::Base @blue = Color.create!(:name => "blue", :short_name => "blu", :hex => 0x0000FF) @black = Color.create!(:name => "black", :short_name => "bla", :hex => 0x000000) @green = Color.create!(:name => "green", :short_name => "gre", :hex => 0x00FF00) - facets = Color.search_for_facet_values('short_name', 'bl', :query => 'black') + facets = Color.search_for_facet_values('short_name', 'bl', { :query => 'black' }) expect(facets.size).to eq(1) - expect(facets.first['value']).to eq('bla') - expect(facets.first['highlighted']).to eq('bla') - expect(facets.first['count']).to eq(1) + expect(facets.first.value).to eq('bla') + expect(facets.first.highlighted).to eq('bla') + expect(facets.first.count).to eq(1) end end @@ -1168,18 +1172,18 @@ class SerializedObject < ActiveRecord::Base end it "should be searchable using replica index" do - r = City.index(safe_index_name('City_replica1')).search 'no land' - r['nbHits'].should eq(1) + r = AlgoliaSearch.client.search_single_index(safe_index_name("City_replica1_#{Rails.env.to_s}"), { query: 'no land' }) + r.nb_hits.should eq(1) end it "should be searchable using replica index 2" do r = City.raw_search 'no land', :index => safe_index_name('City_replica1') - r['nbHits'].should eq(1) + r[:nbHits].should eq(1) end it "should be searchable using replica index 3" do r = City.raw_search 'no land', :replica => safe_index_name('City_replica1') - r['nbHits'].should eq(1) + r[:nbHits].should eq(1) end it "should be searchable using replica index 4" do @@ -1194,37 +1198,32 @@ class SerializedObject < ActiveRecord::Base it "should reindex with replicas in place" do City.reindex!(AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZE, true) - expect(City.index.get_settings['replicas'].length).to eq(2) + expect(AlgoliaSearch.client.get_settings(City.index_name).replicas.length).to eq(2) end it "should reindex with replicas using a temporary index" do City.reindex(AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZE, true) - expect(City.index.get_settings['replicas'].length).to eq(2) + expect(AlgoliaSearch.client.get_settings(City.index_name).replicas.length).to eq(2) end it "should not include the replicas setting on replicas" do City.send(:algolia_configurations).to_a.each do |v| if v[0][:replica] - expect(v[1].to_settings[:replicas]).to be_nil + expect(v[1].to_settings.replicas).to be_nil else - expect(v[1].to_settings[:replicas]).to match_array(["#{safe_index_name('City_replica1')}_#{Rails.env}", "#{safe_index_name('City_replica2')}_#{Rails.env}"]) + expect(v[1].to_settings.replicas).to match_array(["#{safe_index_name('City_replica1')}_#{Rails.env}", "#{safe_index_name('City_replica2')}_#{Rails.env}"]) end end end - it "should browse" do - total = City.index.search('')['nbHits'] - n = 0 - City.index.browse_objects do |hit| - n += 1 - end - expect(n).to eq(total) - end - it "should have set the custom ranking on all indices" do - expect(City.index.get_settings['customRanking']).to eq(['desc(b)']) - expect(City.index(safe_index_name('City_replica1')).get_settings['customRanking']).to eq(['asc(a)']) - expect(City.index(safe_index_name('City_replica2')).get_settings['customRanking']).to eq(['asc(a)', 'desc(c)']) + City.ensure_algolia_index + City.ensure_algolia_index(safe_index_name("City_replica1")) + City.ensure_algolia_index(safe_index_name("City_replica2")) + + expect(AlgoliaSearch.client.get_settings(City.index_name).custom_ranking).to eq(['desc(b)']) + expect(AlgoliaSearch.client.get_settings(City.index_name(nil, safe_index_name("City_replica1"))).custom_ranking).to eq(['asc(a)']) + expect(AlgoliaSearch.client.get_settings(City.index_name(nil, safe_index_name("City_replica2"))).custom_ranking).to eq(['asc(a)', 'desc(c)']) end end @@ -1253,23 +1252,26 @@ class ForwardToReplicas < ActiveRecord::Base end after(:each) do - ForwardToReplicas.index.delete! + res = AlgoliaSearch.client.delete_index(ForwardToReplicas.index_name) + AlgoliaSearch.client.wait_for_task(ForwardToReplicas.index_name, res.task_id) end it 'shouldn\'t have inherited from the primary' do - ForwardToReplicas.send :algolia_ensure_init + ForwardToReplicas.send :ensure_init_new # Hacky way to have a wait on set_settings ForwardToReplicas.create(:name => 'val') ForwardToReplicas.reindex! - primary_settings = ForwardToReplicas.index.get_settings - expect(primary_settings['searchableAttributes']).to eq(%w(first_value)) - expect(primary_settings['attributesToHighlight']).to eq(%w(primary_highlight)) - replica_settings = ForwardToReplicas.index(safe_index_name('ForwardToReplicas_replica')).get_settings - expect(replica_settings['searchableAttributes']).to eq(nil) - expect(replica_settings['attributesToHighlight']).to eq(%w(replica_highlight)) + + primary_settings = AlgoliaSearch.client.get_settings(ForwardToReplicas.index_name) + expect(primary_settings.searchable_attributes).to eq(%w(first_value)) + expect(primary_settings.attributes_to_highlight).to eq(%w(primary_highlight)) + + replica_settings = AlgoliaSearch.client.get_settings(ForwardToReplicas.index_name(nil, safe_index_name('ForwardToReplicas_replica'))) + expect(replica_settings.searchable_attributes).to eq(nil) + expect(replica_settings.attributes_to_highlight).to eq(%w(replica_highlight)) end it 'should update the replica settings when changed' do @@ -1293,23 +1295,23 @@ class ForwardToReplicasTwo < ActiveRecord::Base end end - ForwardToReplicas.send :algolia_ensure_init + ForwardToReplicas.send :ensure_init_new - ForwardToReplicasTwo.send :algolia_ensure_init + ForwardToReplicasTwo.send :ensure_init_new # Hacky way to have a wait on set_settings ForwardToReplicasTwo.create(:name => 'val') ForwardToReplicasTwo.reindex! - primary_settings = ForwardToReplicas.index.get_settings - expect(primary_settings['searchableAttributes']).to eq(%w(second_value)) - expect(primary_settings['attributesToHighlight']).to eq(%w(primary_highlight)) + primary_settings = AlgoliaSearch.client.get_settings(ForwardToReplicas.index_name) + expect(primary_settings.searchable_attributes).to eq(%w(second_value)) + expect(primary_settings.attributes_to_highlight).to eq(%w(primary_highlight)) - replica_settings = ForwardToReplicas.index(safe_index_name('ForwardToReplicas_replica')).get_settings - expect(replica_settings['searchableAttributes']).to eq(%w(second_value)) - expect(replica_settings['attributesToHighlight']).to eq(%w(replica_highlight)) + replica_settings = AlgoliaSearch.client.get_settings(ForwardToReplicas.index_name(nil, safe_index_name('ForwardToReplicas_replica'))) + expect(replica_settings.searchable_attributes).to eq(%w(second_value)) + expect(replica_settings.attributes_to_highlight).to eq(%w(replica_highlight)) - expect(ForwardToReplicas.index.name).to eq(ForwardToReplicasTwo.index.name) + expect(ForwardToReplicas.index_name).to eq(ForwardToReplicasTwo.index_name) end it "shouldn't update the replica settings if there is no change" do @@ -1333,15 +1335,15 @@ class ForwardToReplicasTwo < ActiveRecord::Base end end - ForwardToReplicas.send :algolia_ensure_init + ForwardToReplicas.send :ensure_init_new # Hacky way to hook replica settings update ForwardToReplicas.create(:name => 'val') ForwardToReplicas.reindex! - expect_any_instance_of(Algolia::Search::Index).not_to receive(:set_settings!) + expect_any_instance_of(Algolia::SearchClient).not_to receive(:set_settings) - ForwardToReplicasTwo.send :algolia_ensure_init + ForwardToReplicasTwo.send :ensure_init_new # Hacky way to hook replica settings update ForwardToReplicasTwo.create(:name => 'val2') @@ -1542,7 +1544,6 @@ class ForwardToReplicasTwo < ActiveRecord::Base end end - describe 'Disabled' do before(:all) do DisabledBoolean.index.clear_objects! diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f8e6f4a..8860569 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -32,8 +32,8 @@ # Remove all indexes setup in this run in local or CI c.after(:suite) do safe_index_list.each do |i| - index = AlgoliaSearch.client.init_index(i['name']) - index.delete! + res = AlgoliaSearch.client.delete_index(i.name) + AlgoliaSearch.client.wait_for_task(i.name, res.task_id) end end end @@ -48,7 +48,7 @@ def safe_index_name(name) # get a list of safe indexes in local or CI def safe_index_list - list = AlgoliaSearch.client.list_indexes['items'] - list = list.select { |index| index["name"].include?(SAFE_INDEX_PREFIX) } - list.sort_by { |index| index["primary"] || "" } + list = AlgoliaSearch.client.list_indices.items + list = list.select { |index| index.name.include?(SAFE_INDEX_PREFIX) } + list.sort_by { |index| index.primary || "" } end From bc80b19726f4a95027df83f07759ce3aff94ad2d Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:07:07 +0200 Subject: [PATCH 03/40] chore: fix SubReplicas tests --- lib/algoliasearch-rails.rb | 13 ++++++++++++- spec/integration_spec.rb | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/algoliasearch-rails.rb b/lib/algoliasearch-rails.rb index a225c2c..7197ba6 100644 --- a/lib/algoliasearch-rails.rb +++ b/lib/algoliasearch-rails.rb @@ -697,7 +697,18 @@ def algolia_raw_search(q, params = {}) params.delete('index') || params.delete(:replica) || params.delete('replica') - index_name = algolia_index_name(algoliasearch_options, index_name_base) + + opts = algoliasearch_options + unless index_name_base.nil? + algolia_configurations.each do |o, s| + if o[:index_name].to_s == index_name_base.to_s + opts = o + ensure_algolia_index(index_name_base) + end + end + end + + index_name = algolia_index_name(opts, index_name_base) AlgoliaSearch.client.search_single_index(index_name,Hash[params.to_h.map { |k,v| [k.to_s, v.to_s] }].merge({query: q})).to_hash end diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 7beadf2..6434829 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -542,11 +542,11 @@ class SubReplicas < ActiveRecord::Base searchableAttributes ['name'] customRanking ["asc(name)"] - add_index safe_index_name("Additional_Index"), :per_environment => true do + add_index safe_index_name("Additional_Index"), :per_environment => true, :synchronous => true do searchableAttributes ['name'] customRanking ["asc(name)"] - add_replica safe_index_name("Replica_Index"), :per_environment => true do + add_replica safe_index_name("Replica_Index"), :per_environment => true, :synchronous => true do searchableAttributes ['name'] customRanking ["desc(name)"] end From c32aed4271fc0c511019166d91f2de0921054a5f Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:46:18 +0200 Subject: [PATCH 04/40] chore: fix Book tests --- spec/integration_spec.rb | 56 +++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 6434829..3e9f994 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -1411,8 +1411,11 @@ class ForwardToReplicasTwo < ActiveRecord::Base describe 'Book' do before(:all) do Book.clear_index!(true) - Book.index(safe_index_name('BookAuthor')).clear_objects - Book.index(safe_index_name('Book')).clear_objects + index_name_author = Book.index_name(nil, safe_index_name('BookAuthor')) + index_name_book = Book.index_name(nil, safe_index_name('Book')) + + AlgoliaSearch.client.wait_for_task(index_name_author, AlgoliaSearch.client.clear_objects(index_name_author).task_id) + AlgoliaSearch.client.wait_for_task(index_name_book, AlgoliaSearch.client.clear_objects(index_name_book).task_id) end it "should index the book in 2 indexes of 3" do @@ -1421,39 +1424,35 @@ class ForwardToReplicasTwo < ActiveRecord::Base expect(results.size).to eq(1) results.should include(@steve_jobs) - index_author = Book.index(safe_index_name('BookAuthor')) - index_author.should_not be_nil - results = index_author.search('steve') - results['hits'].length.should eq(0) - results = index_author.search('walter') - results['hits'].length.should eq(1) + results = Book.search("steve", index: safe_index_name('BookAuthor')) + results.length.should eq(0) + results = Book.search("walter", index: safe_index_name('BookAuthor')) + results.length.should eq(1) # premium -> not part of the public index - index_book = Book.index(safe_index_name('Book')) - index_book.should_not be_nil - results = index_book.search('steve') - results['hits'].length.should eq(0) + results = Book.search("steve", index: safe_index_name('Book')) + results.length.should eq(0) end it "should sanitize attributes" do @hack = Book.create! :name => "\"> hack0r", :author => "", :premium => true, :released => true b = Book.raw_search('hack') - expect(b['hits'].length).to eq(1) + expect(b[:hits].length).to eq(1) begin - expect(b['hits'][0]['name']).to eq('"> hack0r') - expect(b['hits'][0]['author']).to eq('alert(1)') - expect(b['hits'][0]['_highlightResult']['name']['value']).to eq('"> hack0r') + expect(b[:hits][0][:name]).to eq('"> hack0r') + expect(b[:hits][0][:author]).to eq('alert(1)') + expect(b[:hits][0][:_highlightResult][:name][:value]).to eq('"> hack0r') rescue # rails 4.2's sanitizer begin - expect(b['hits'][0]['name']).to eq('"> hack0r') - expect(b['hits'][0]['author']).to eq('') - expect(b['hits'][0]['_highlightResult']['name']['value']).to eq('"> hack0r') + expect(b[:hits][0][:name]).to eq('"> hack0r') + expect(b[:hits][0][:author]).to eq('') + expect(b[:hits][0][:_highlightResult][:name][:value]).to eq('"> hack0r') rescue # jruby - expect(b['hits'][0]['name']).to eq('"> hack0r') - expect(b['hits'][0]['author']).to eq('') - expect(b['hits'][0]['_highlightResult']['name']['value']).to eq('"> hack0r') + expect(b[:hits][0][:name]).to eq('"> hack0r') + expect(b[:hits][0][:author]).to eq('') + expect(b[:hits][0][:_highlightResult][:name][:value]).to eq('"> hack0r') end end end @@ -1463,9 +1462,8 @@ class ForwardToReplicasTwo < ActiveRecord::Base book = Book.create! :name => 'Public book', :author => 'me', :premium => false, :released => true # should be searchable in the 'Book' index - index = Book.index(safe_index_name('Book')) - results = index.search('Public book') - expect(results['hits'].size).to eq(1) + results = Book.search("Public book", index: safe_index_name('Book')) + expect(results.size).to eq(1) # update the book and make it non-public anymore (not premium, not released) if book.respond_to? :update_attributes @@ -1475,13 +1473,13 @@ class ForwardToReplicasTwo < ActiveRecord::Base end # should be removed from the index - results = index.search('Public book') - expect(results['hits'].size).to eq(0) + results = Book.search("Public book", index: safe_index_name('Book')) + expect(results.size).to eq(0) end it "should use the per_environment option in the additional index as well" do - index = Book.index(safe_index_name('Book')) - expect(index.name).to eq("#{safe_index_name('Book')}_#{Rails.env}") + index_name = Book.index_name(nil, safe_index_name('Book')) + expect(index_name).to eq("#{safe_index_name('Book')}_#{Rails.env}") end end From 4cc7e77bdc001cfc58192f21badbe7bebbe825bd Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:58:10 +0200 Subject: [PATCH 05/40] chore: fix pagination tests --- spec/integration_spec.rb | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 3e9f994..2eea1b0 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -1487,21 +1487,28 @@ class ForwardToReplicasTwo < ActiveRecord::Base before(:all) do require 'kaminari' AlgoliaSearch.configuration = { :application_id => ENV['ALGOLIA_APPLICATION_ID'], :api_key => ENV['ALGOLIA_API_KEY'], :pagination_backend => :kaminari } + + City.create :name => 'San Francisco', :country => 'USA', :lat => 37.75, :lng => -122.68 + City.create :name => 'Mountain View', :country => 'No man\'s land', :lat => 37.38, :lng => -122.08 + end + + after(:all) do + City.clear_index!(true) end it "should paginate" do pagination = City.search '' - pagination.total_count.should eq(City.raw_search('')['nbHits']) + pagination.total_count.should eq(City.raw_search('')[:nbHits]) p1 = City.search '', :page => 1, :hitsPerPage => 1 p1.size.should eq(1) p1[0].should eq(pagination[0]) - p1.total_count.should eq(City.raw_search('')['nbHits']) + p1.total_count.should eq(City.raw_search('')[:nbHits]) p2 = City.search '', :page => 2, :hitsPerPage => 1 p2.size.should eq(1) p2[0].should eq(pagination[1]) - p2.total_count.should eq(City.raw_search('')['nbHits']) + p2.total_count.should eq(City.raw_search('')[:nbHits]) end end @@ -1509,13 +1516,19 @@ class ForwardToReplicasTwo < ActiveRecord::Base before(:all) do require 'will_paginate' AlgoliaSearch.configuration = { :application_id => ENV['ALGOLIA_APPLICATION_ID'], :api_key => ENV['ALGOLIA_API_KEY'], :pagination_backend => :will_paginate } + City.create :name => 'San Francisco', :country => 'USA', :lat => 37.75, :lng => -122.68 + City.create :name => 'Mountain View', :country => 'No man\'s land', :lat => 37.38, :lng => -122.08 + end + + after(:all) do + City.clear_index!(true) end it "should paginate" do p1 = City.search '', :hitsPerPage => 2 p1.length.should eq(2) p1.per_page.should eq(2) - p1.total_entries.should eq(City.raw_search('')['nbHits']) + p1.total_entries.should eq(City.raw_search('')[:nbHits]) end end @@ -1530,13 +1543,14 @@ class ForwardToReplicasTwo < ActiveRecord::Base after(:all) do # Reset the configuration to avoid conflicts with other tests AlgoliaSearch.configuration = { :application_id => ENV['ALGOLIA_APPLICATION_ID'], :api_key => ENV['ALGOLIA_API_KEY'] } + City.clear_index!(true) end it "should paginate" do pagy, cities = City.search '', :hitsPerPage => 2 pagy.page.should eq(1) pagy.items.should eq(2) - pagy.count.should eq(City.raw_search('')['nbHits']) + pagy.count.should eq(City.raw_search('')[:nbHits]) cities.length.should eq(2) cities.should be_an(Array) end From fb275731f62c24f64767c3df21100b4d963c0586 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 09:24:33 +0200 Subject: [PATCH 06/40] chore: fix disabled indexing tests --- spec/integration_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 2eea1b0..01c0f7f 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -1558,24 +1558,24 @@ class ForwardToReplicasTwo < ActiveRecord::Base describe 'Disabled' do before(:all) do - DisabledBoolean.index.clear_objects! - DisabledProc.index.clear_objects! - DisabledSymbol.index.clear_objects! + DisabledBoolean.send(:ensure_init_new) + DisabledProc.send(:ensure_init_new) + DisabledSymbol.send(:ensure_init_new) end it "should disable the indexing using a boolean" do DisabledBoolean.create :name => 'foo' - expect(DisabledBoolean.search('').size).to eq(0) + expect { DisabledBoolean.search('') }.to raise_error Algolia::AlgoliaHttpError # index doesn't exist end it "should disable the indexing using a proc" do DisabledProc.create :name => 'foo' - expect(DisabledProc.search('').size).to eq(0) + expect { DisabledProc.search('') }.to raise_error Algolia::AlgoliaHttpError # index doesn't exist end it "should disable the indexing using a symbol" do DisabledSymbol.create :name => 'foo' - expect(DisabledSymbol.search('').size).to eq(0) + expect { DisabledSymbol.search('') }.to raise_error Algolia::AlgoliaHttpError # index doesn't exist end end From 8ac022576b6af800dac766942f6f05fd958999db Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:02:11 +0200 Subject: [PATCH 07/40] fix tests --- lib/algoliasearch-rails.rb | 10 ++++++++-- spec/integration_spec.rb | 5 +---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/algoliasearch-rails.rb b/lib/algoliasearch-rails.rb index 7197ba6..9abd18b 100644 --- a/lib/algoliasearch-rails.rb +++ b/lib/algoliasearch-rails.rb @@ -241,7 +241,13 @@ def get_setting(name) # TODO def to_settings - Algolia::Search::IndexSettings.new(to_hash) + settings = to_hash + + # Remove the synonyms setting since those need to be set separately + settings.delete(:synonyms) + settings.delete("synonyms") + + Algolia::Search::IndexSettings.new(settings) end def to_hash @@ -954,7 +960,7 @@ def algolia_object_id_changed?(o, options = nil) def algoliasearch_settings_changed?(prev, current) return true if prev.nil? current.each do |k, v| - prev_v = prev[k.to_sym] + prev_v = prev[k.to_sym] || prev[k.to_s] if v.is_a?(Array) and prev_v.is_a?(Array) # compare array of strings, avoiding symbols VS strings comparison return true if v.map { |x| x.to_s } != prev_v.map { |x| x.to_s } diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 01c0f7f..bd998bd 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -826,10 +826,7 @@ class SerializedObject < ActiveRecord::Base @i1.children << NestedItem.create(:hidden => true) << NestedItem.create(:hidden => true) NestedItem.where(:id => [@i1.id, @i2.id]).reindex!(AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZE, true) - # result = AlgoliaSearch.client.get_object(NestedItem.index_name, @i1.id) # TODO: should be bugfixed and should replace the line below - result = AlgoliaSearch.client.get_objects(Algolia::Search::GetObjectsParams.new( - requests: [Algolia::Search::GetObjectsRequest.new(object_id: 'objectID1', index_name: 'my_index')] - )).results.first + result = AlgoliaSearch.client.get_object(NestedItem.index_name, @i1.id.to_s) result[:nb_children].should == 2 result = NestedItem.raw_search('') From b6ea1a3840e12be07b747dfbab6c23f5eb9ecab1 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:02:23 +0200 Subject: [PATCH 08/40] ensure latest gem version --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 7226ff4..4143eab 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source "http://rubygems.org" gem 'json', '>= 1.5.1' -gem 'algolia', '>= 3.4.0' +gem 'algolia', '>= 3.5.0' if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' gem 'rubysl', '~> 2.0', :platform => :rbx From bc48f9aac7ca463f25ef2076c7a02b49a1d136c7 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:07:36 +0200 Subject: [PATCH 09/40] fix: virtual replica test --- spec/integration_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index bd998bd..b741aab 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -1387,10 +1387,10 @@ class ForwardToReplicasTwo < ActiveRecord::Base if v[0][:replica] expect(v[0][:index_name]).to eq(safe_index_name("VirtualReplica_replica")) expect(v[0][:virtual]).to eq(true) - expect(v[1].to_settings[:replicas]).to be_nil + expect(v[1].to_settings.replicas).to be_nil else expect(v[0][:index_name]).to eq(safe_index_name("VirtualReplica_primary")) - expect(v[1].to_settings[:replicas]).to match_array(["virtual(#{safe_index_name("VirtualReplica_replica")})"]) + expect(v[1].to_settings.replicas).to match_array(["virtual(#{safe_index_name("VirtualReplica_replica")})"]) end end end From 799818283d22681f6697d63e2b4f5f4c23bd1aae Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:21:33 +0200 Subject: [PATCH 10/40] test matrix --- .circleci/config.yml | 51 +++++++++----------------------------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 171c83e..7c007b6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -69,45 +69,14 @@ workflows: ci: jobs: - test: - name: 'Rails 5.1 - Ruby 2.4' - version: '2.4' - rails-version: '5.1' - sequel-version: '5.0' + matrix: + parameters: + version: [ '2.5', '2.6', '2.7', '3.0', '3.1' ] + rails-version: [ '6.0', '6.1' ] + sequel-version: [ '5.0' ] - test: - name: 'Rails 5.1 - Ruby 2.5' - version: '2.5' - rails-version: '5.1' - sequel-version: '5.0' - - test: - name: 'Rails 5.1 - Ruby 2.6' - version: '2.6' - rails-version: '5.1' - sequel-version: '5.0' - - - - test: - name: 'Rails 6.0 - Ruby 2.5' - version: '2.5' - rails-version: '6.0' - sequel-version: '5.0' - - test: - name: 'Rails 6.0 - Ruby 2.6' - version: '2.6' - rails-version: '6.0' - sequel-version: '5.0' - - test: - name: 'Rails 6.0 - Ruby 2.7' - version: '2.7' - rails-version: '6.0' - sequel-version: '5.0' - - - test: - name: 'Rails 6.1 - Ruby 2.7' - version: '2.7' - rails-version: '6.1' - sequel-version: '5.0' - - test: - name: 'Rails 6.1 - Ruby 3.0' - version: '3.0' - rails-version: '6.1' - sequel-version: '5.0' + matrix: + parameters: + version: ['3.0', '3.1'] + rails-version: ['7.0'] + sequel-version: ['5.0'] \ No newline at end of file From c41e65d93343b472418cfd32046f9a44e5677a24 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:23:27 +0200 Subject: [PATCH 11/40] Update Gemfile --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 4143eab..29688ef 100644 --- a/Gemfile +++ b/Gemfile @@ -27,7 +27,7 @@ group :test do end group :development do - gem 'rake', '~> 10.1.0' + gem 'rake', '>= 10.1.0' gem 'rdoc' end From bfe1a898959ba196f2810df6bf90df1ce3d34fcf Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:25:24 +0200 Subject: [PATCH 12/40] Update config.yml --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7c007b6..6812d11 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -33,7 +33,7 @@ aliases: references: default_docker_ruby_executor: &default_docker_ruby_executor - image: circleci/ruby:<< parameters.version >> + image: cimg/ruby:<< parameters.version >> environment: BUNDLE_JOBS: 3 BUNDLE_RETRY: 3 From 99e68dbf02c7f5e9fe5f4dfcf83545ef05a2e5fe Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:28:07 +0200 Subject: [PATCH 13/40] Update Gemfile --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 29688ef..83d5347 100644 --- a/Gemfile +++ b/Gemfile @@ -16,7 +16,7 @@ group :test do else gem 'sqlite3', '< 1.4.0', :platform => [:rbx, :ruby] end - gem 'rspec', '>= 2.5.0', '< 3.0' + gem 'rspec', '~> 3.0' gem 'jdbc-sqlite3', :platform => :jruby gem 'activerecord-jdbc-adapter', :platform => :jruby gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby From 544278fa4c8df8c794d3db065f86dadb73fdcd78 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:30:10 +0200 Subject: [PATCH 14/40] Update config.yml --- .circleci/config.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6812d11..b11231e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,6 +6,10 @@ aliases: curl -s https://algoliasearch-client-keygen.herokuapp.com | sh >> $BASH_ENV fi + - &install_sqlite + name: Install SQLite + command: apt-get install libsqlite3-dev + - &check_bundler name: Which bundler? command: bundle -v @@ -57,6 +61,7 @@ jobs: - *default_docker_ruby_executor steps: - checkout + - run: *install_sqlite - run: *check_bundler - restore_cache: *restore_cache - run: *install_bundler From f5f0e3da17ffc6fd44d5cf7a0e0f06e6640b5833 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:32:34 +0200 Subject: [PATCH 15/40] Update config.yml --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b11231e..c6e59d5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ aliases: - &install_sqlite name: Install SQLite - command: apt-get install libsqlite3-dev + command: sudo apt-get update && sudo apt-get install -y sqlite3 libsqlite3-dev - &check_bundler name: Which bundler? From a7f295290efb6e30d51cd626d60bc8860896991c Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:42:51 +0200 Subject: [PATCH 16/40] Update algoliasearch-rails.rb --- lib/algoliasearch-rails.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/algoliasearch-rails.rb b/lib/algoliasearch-rails.rb index 9abd18b..b75000e 100644 --- a/lib/algoliasearch-rails.rb +++ b/lib/algoliasearch-rails.rb @@ -179,10 +179,9 @@ def get_attributes(object) if @options[:sanitize] sanitizer = begin - ::HTML::FullSanitizer.new + ::Rails::Html5::FullSanitizer.new rescue NameError - # from rails 4.2 - ::Rails::Html::FullSanitizer.new + ::HTML::FullSanitizer.new end attributes = sanitize_attributes(attributes, sanitizer) end From 2e25bb1a0d7530bd6a4e2c388116c93fa840ac91 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:52:47 +0200 Subject: [PATCH 17/40] sanitizer --- lib/algoliasearch-rails.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/algoliasearch-rails.rb b/lib/algoliasearch-rails.rb index b75000e..447c42e 100644 --- a/lib/algoliasearch-rails.rb +++ b/lib/algoliasearch-rails.rb @@ -179,7 +179,9 @@ def get_attributes(object) if @options[:sanitize] sanitizer = begin - ::Rails::Html5::FullSanitizer.new + ::Rails::Html::Sanitizer.new + rescue NameError + ::Rails::HTML::FullSanitizer.new rescue NameError ::HTML::FullSanitizer.new end From d158342f235ed38a6e5bf35d124476588260f60b Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:00:58 +0200 Subject: [PATCH 18/40] Update algoliasearch-rails.rb --- lib/algoliasearch-rails.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/algoliasearch-rails.rb b/lib/algoliasearch-rails.rb index 447c42e..3715a61 100644 --- a/lib/algoliasearch-rails.rb +++ b/lib/algoliasearch-rails.rb @@ -179,11 +179,9 @@ def get_attributes(object) if @options[:sanitize] sanitizer = begin - ::Rails::Html::Sanitizer.new + ::Rails::HTML5::FullSanitizer.new rescue NameError ::Rails::HTML::FullSanitizer.new - rescue NameError - ::HTML::FullSanitizer.new end attributes = sanitize_attributes(attributes, sanitizer) end From 9e698f4dedad4dc2f4f5af765d7877ec72bdd3ea Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:08:24 +0200 Subject: [PATCH 19/40] Update algoliasearch-rails.rb --- lib/algoliasearch-rails.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/algoliasearch-rails.rb b/lib/algoliasearch-rails.rb index 3715a61..24a6d62 100644 --- a/lib/algoliasearch-rails.rb +++ b/lib/algoliasearch-rails.rb @@ -179,9 +179,9 @@ def get_attributes(object) if @options[:sanitize] sanitizer = begin - ::Rails::HTML5::FullSanitizer.new + ::Rails::Html::FullSanitizer.new rescue NameError - ::Rails::HTML::FullSanitizer.new + ::HTML::FullSanitizer.new end attributes = sanitize_attributes(attributes, sanitizer) end From 74413b0ed55442c63a6a638d00e602301119c9b2 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:23:38 +0200 Subject: [PATCH 20/40] Update algoliasearch-rails.rb --- lib/algoliasearch-rails.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/algoliasearch-rails.rb b/lib/algoliasearch-rails.rb index 24a6d62..63cca17 100644 --- a/lib/algoliasearch-rails.rb +++ b/lib/algoliasearch-rails.rb @@ -178,11 +178,12 @@ def get_attributes(object) attributes.merge!(attributes_to_hash(@additional_attributes, object)) if @additional_attributes if @options[:sanitize] - sanitizer = begin - ::Rails::Html::FullSanitizer.new - rescue NameError - ::HTML::FullSanitizer.new + sanitizer = if Rails::VERSION::MAJOR >= 7 + Rails::Html::Sanitizer.new + else + Rails::Html::FullSanitizer.new end + attributes = sanitize_attributes(attributes, sanitizer) end From 5b6af12bdc9b20e7ca26707815bb1270f065483c Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:42:56 +0200 Subject: [PATCH 21/40] Update pagy.rb --- lib/algoliasearch/pagination/pagy.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/algoliasearch/pagination/pagy.rb b/lib/algoliasearch/pagination/pagy.rb index b684731..350775c 100644 --- a/lib/algoliasearch/pagination/pagy.rb +++ b/lib/algoliasearch/pagination/pagy.rb @@ -5,6 +5,8 @@ module AlgoliaSearch module Pagination class Pagy + include Pagy::Backend if defined? Pagy::Backend + def self.create(results, total_hits, options = {}) vars = { count: total_hits, @@ -12,8 +14,7 @@ def self.create(results, total_hits, options = {}) items: options[:per_page] } - pagy = ::Pagy.new(vars) - [pagy, results] + pagy(results, vars) end end From f421f5243989eb93cfdba167e958b44d6b07cbdb Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:44:58 +0200 Subject: [PATCH 22/40] Update integration_spec.rb --- spec/integration_spec.rb | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index b741aab..dda460a 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -1434,24 +1434,11 @@ class ForwardToReplicasTwo < ActiveRecord::Base it "should sanitize attributes" do @hack = Book.create! :name => "\"> hack0r", :author => "", :premium => true, :released => true b = Book.raw_search('hack') + expect(b[:hits].length).to eq(1) - begin - expect(b[:hits][0][:name]).to eq('"> hack0r') - expect(b[:hits][0][:author]).to eq('alert(1)') - expect(b[:hits][0][:_highlightResult][:name][:value]).to eq('"> hack0r') - rescue - # rails 4.2's sanitizer - begin - expect(b[:hits][0][:name]).to eq('"> hack0r') - expect(b[:hits][0][:author]).to eq('') - expect(b[:hits][0][:_highlightResult][:name][:value]).to eq('"> hack0r') - rescue - # jruby - expect(b[:hits][0][:name]).to eq('"> hack0r') - expect(b[:hits][0][:author]).to eq('') - expect(b[:hits][0][:_highlightResult][:name][:value]).to eq('"> hack0r') - end - end + expect(b[:hits][0][:name]).to eq('"> hack0r') + expect(b[:hits][0][:author]).to eq('alert(1)') + expect(b[:hits][0][:_highlightResult][:name][:value]).to eq('"> hack0r') end it "should handle removal in an extra index" do From dbbcc769c128e155af33dbe742ef6e2d3f3f6057 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:54:20 +0200 Subject: [PATCH 23/40] Update pagy.rb --- lib/algoliasearch/pagination/pagy.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/algoliasearch/pagination/pagy.rb b/lib/algoliasearch/pagination/pagy.rb index 350775c..bf56761 100644 --- a/lib/algoliasearch/pagination/pagy.rb +++ b/lib/algoliasearch/pagination/pagy.rb @@ -5,7 +5,6 @@ module AlgoliaSearch module Pagination class Pagy - include Pagy::Backend if defined? Pagy::Backend def self.create(results, total_hits, options = {}) vars = { @@ -14,7 +13,8 @@ def self.create(results, total_hits, options = {}) items: options[:per_page] } - pagy(results, vars) + pagy = ::Pagy.new(vars) + [pagy, results] end end From 1ecad6c62b34f1899b6bdcfe19db878252a4c1ee Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:01:01 +0200 Subject: [PATCH 24/40] Update integration_spec.rb --- spec/integration_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index dda460a..4d894f1 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -1437,8 +1437,8 @@ class ForwardToReplicasTwo < ActiveRecord::Base expect(b[:hits].length).to eq(1) expect(b[:hits][0][:name]).to eq('"> hack0r') - expect(b[:hits][0][:author]).to eq('alert(1)') - expect(b[:hits][0][:_highlightResult][:name][:value]).to eq('"> hack0r') + expect(b[:hits][0][:author]).to eq('') + expect(b[:hits][0][:_highlightResult][:name][:value]).to eq('"> hack0r') end it "should handle removal in an extra index" do From 1bba7f374ca8986fccc0612c4cdda374d308beb7 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:01:57 +0200 Subject: [PATCH 25/40] Update pagy.rb --- lib/algoliasearch/pagination/pagy.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/algoliasearch/pagination/pagy.rb b/lib/algoliasearch/pagination/pagy.rb index bf56761..54c9ecd 100644 --- a/lib/algoliasearch/pagination/pagy.rb +++ b/lib/algoliasearch/pagination/pagy.rb @@ -13,7 +13,13 @@ def self.create(results, total_hits, options = {}) items: options[:per_page] } - pagy = ::Pagy.new(vars) + pagy_version = Gem::Version.new(::Pagy::VERSION) + pagy = if pagy_version >= 9 + ::Pagy.new(**vars) + else + ::Pagy.new(vars) + end + [pagy, results] end end From 8a32e9b5ebfcea5a40ab9a5bd6c5f8970f20fe8a Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:17:03 +0200 Subject: [PATCH 26/40] Update pagy.rb --- lib/algoliasearch/pagination/pagy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/algoliasearch/pagination/pagy.rb b/lib/algoliasearch/pagination/pagy.rb index 54c9ecd..520de28 100644 --- a/lib/algoliasearch/pagination/pagy.rb +++ b/lib/algoliasearch/pagination/pagy.rb @@ -14,7 +14,7 @@ def self.create(results, total_hits, options = {}) } pagy_version = Gem::Version.new(::Pagy::VERSION) - pagy = if pagy_version >= 9 + pagy = if pagy_version >= Gem::Version.new('9.0') ::Pagy.new(**vars) else ::Pagy.new(vars) From 28364461c9f7e1e54d46574b4f51c56cc7112183 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:40:13 +0200 Subject: [PATCH 27/40] Update integration_spec.rb --- spec/integration_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 4d894f1..d01ef0e 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -1533,7 +1533,6 @@ class ForwardToReplicasTwo < ActiveRecord::Base it "should paginate" do pagy, cities = City.search '', :hitsPerPage => 2 pagy.page.should eq(1) - pagy.items.should eq(2) pagy.count.should eq(City.raw_search('')[:nbHits]) cities.length.should eq(2) cities.should be_an(Array) From 91ccfc56c4aecfc98a41574e6c3a8e6bd0fc6b76 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:42:14 +0200 Subject: [PATCH 28/40] Update integration_spec.rb --- spec/integration_spec.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index d01ef0e..041d7e2 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -1406,6 +1406,8 @@ class ForwardToReplicasTwo < ActiveRecord::Base end describe 'Book' do + require 'rails-html-sanitizer' + before(:all) do Book.clear_index!(true) index_name_author = Book.index_name(nil, safe_index_name('BookAuthor')) From 079c71da7c51fccf69451380e88f9633f9bc8834 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:46:54 +0200 Subject: [PATCH 29/40] sanitizer --- lib/algoliasearch-rails.rb | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/algoliasearch-rails.rb b/lib/algoliasearch-rails.rb index 63cca17..79668a8 100644 --- a/lib/algoliasearch-rails.rb +++ b/lib/algoliasearch-rails.rb @@ -176,16 +176,7 @@ def get_attributes(object) end attributes.merge!(attributes_to_hash(@additional_attributes, object)) if @additional_attributes - - if @options[:sanitize] - sanitizer = if Rails::VERSION::MAJOR >= 7 - Rails::Html::Sanitizer.new - else - Rails::Html::FullSanitizer.new - end - - attributes = sanitize_attributes(attributes, sanitizer) - end + attributes = sanitize_attributes(attributes, Rails::Html::FullSanitizer.new) if @options[:sanitize] if @options[:force_utf8_encoding] && Object.const_defined?(:RUBY_VERSION) && RUBY_VERSION.to_f > 1.8 attributes = encode_attributes(attributes) From cd3c1de8b392b18240e29b7e9bfb52ea50a10bfa Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 15:42:54 +0200 Subject: [PATCH 30/40] chore: clean up algoliasearch/configuration --- lib/algoliasearch/configuration.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/algoliasearch/configuration.rb b/lib/algoliasearch/configuration.rb index 3b6bda3..13aeaad 100644 --- a/lib/algoliasearch/configuration.rb +++ b/lib/algoliasearch/configuration.rb @@ -2,7 +2,6 @@ module AlgoliaSearch module Configuration REQUIRED_CONFIGURATION = { user_agent: "Algolia for Rails (#{AlgoliaSearch::VERSION}); Rails (#{defined?(::Rails::VERSION::STRING) ? ::Rails::VERSION::STRING : 'unknown'})", - symbolize_keys: false } def initialize @@ -21,14 +20,6 @@ def configuration=(configuration) .merge({ user_agent: user_agent }) end - def client_opts - @@opts ||= {} - end - - def client_opts=(opts) - @@opts = opts - end - def client if @client.nil? setup_client @@ -37,7 +28,6 @@ def client @client end - # TODO def setup_client @client = Algolia::SearchClient.create(@@configuration[:application_id], @@configuration[:api_key]) end From 531d98a4f6d471926104ff57509dfbf9f04b0d34 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 15:48:04 +0200 Subject: [PATCH 31/40] remove `index` method --- lib/algoliasearch-rails.rb | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/algoliasearch-rails.rb b/lib/algoliasearch-rails.rb index 79668a8..87edc4b 100644 --- a/lib/algoliasearch-rails.rb +++ b/lib/algoliasearch-rails.rb @@ -378,7 +378,6 @@ class < Date: Mon, 14 Oct 2024 16:02:28 +0200 Subject: [PATCH 32/40] chore: handle todos --- lib/algoliasearch-rails.rb | 150 ++++++------------------------------- spec/integration_spec.rb | 28 +++---- 2 files changed, 38 insertions(+), 140 deletions(-) diff --git a/lib/algoliasearch-rails.rb b/lib/algoliasearch-rails.rb index 87edc4b..a702677 100644 --- a/lib/algoliasearch-rails.rb +++ b/lib/algoliasearch-rails.rb @@ -230,7 +230,6 @@ def get_setting(name) instance_variable_get("@#{name}") end - # TODO def to_settings settings = to_hash @@ -297,71 +296,6 @@ def additional_indexes autoload :AlgoliaJob, 'algoliasearch/algolia_job' end - # this class wraps an Algolia::Index object ensuring all raised exceptions - # are correctly logged or thrown depending on the `raise_on_failure` option - # TODO - class SafeIndex - def initialize(name, raise_on_failure) - @index = AlgoliaSearch.client.init_index(name) - @raise_on_failure = raise_on_failure.nil? || raise_on_failure - end - - # ::Algolia::Search::Index.instance_methods(false).each do |m| - # define_method(m) do |*args, &block| - # SafeIndex.log_or_throw(m, @raise_on_failure) do - # @index.send(m, *args, &block) - # end - # end - # end - - # special handling of wait_task to handle null task_id - def wait_task(task_id) - return if task_id.nil? && !@raise_on_failure # ok - SafeIndex.log_or_throw(:wait_task, @raise_on_failure) do - @index.wait_task(task_id) - end - end - - # special handling of get_settings to avoid raising errors on 404 - def get_settings(*args) - SafeIndex.log_or_throw(:get_settings, @raise_on_failure) do - begin - @index.get_settings(*args) - rescue Algolia::AlgoliaHttpError => e - return {} if e.code == 404 # not fatal - raise e - end - end - end - - # expose move as well - def self.move_index(old_name, new_name) - SafeIndex.log_or_throw(:move_index, true) do - AlgoliaSearch.client.move_index(old_name, new_name) - end - end - - private - def self.log_or_throw(method, raise_on_failure, &block) - begin - yield - rescue Algolia::AlgoliaError => e - raise e if raise_on_failure - # log the error - (Rails.logger || Logger.new(STDOUT)).error("[algoliasearch-rails] #{e.message}") - # return something - case method.to_s - when 'search' - # some attributes are required - { 'hits' => [], 'hitsPerPage' => 0, 'page' => 0, 'facets' => {}, 'error' => e } - else - # empty answer - { 'error' => e } - end - end - end - end - # these are the class methods added when AlgoliaSearch is included module ClassMethods @@ -503,12 +437,11 @@ def algolia_without_auto_index_scope Thread.current["algolia_without_auto_index_scope_for_#{self.model_name}"] end - # TODO def algolia_reindex!(batch_size = AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZE, synchronous = false) return if algolia_without_auto_index_scope algolia_configurations.each do |options, settings| next if algolia_indexing_disabled?(options) - ensure_init_new(options, settings) + algolia_ensure_init(options, settings) index_name = algolia_index_name(options) next if options[:replica] last_task = nil @@ -535,7 +468,6 @@ def algolia_reindex!(batch_size = AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SI nil end - # TODO # reindex whole database using a extra temporary index + move operation def algolia_reindex(batch_size = AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZE, synchronous = false) return if algolia_without_auto_index_scope @@ -543,11 +475,10 @@ def algolia_reindex(batch_size = AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZ next if algolia_indexing_disabled?(options) next if options[:replica] - ensure_init_new(options, settings) + algolia_ensure_init(options, settings) index_name = algolia_index_name(options) # fetch the master settings - master_settings = AlgoliaSearch.client.get_settings(index_name).to_hash rescue {} # if master doesn't exist yet master_exists = master_settings != {} master_settings.merge!(settings.to_hash) @@ -589,29 +520,36 @@ def algolia_reindex(batch_size = AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZ nil end - # TODO def algolia_set_settings(synchronous = false) algolia_configurations.each do |options, settings| if options[:primary_settings] && options[:inherit] - primary = options[:primary_settings].to_settings + primary = options[:primary_settings].to_settings.to_hash primary.delete :replicas primary.delete 'replicas' - final_settings = primary.merge(settings.to_settings) + final_settings = primary.merge(settings.to_settings.to_hash) else - final_settings = settings.to_settings + final_settings = settings.to_settings.to_hash end - index = SafeIndex.new(algolia_index_name(options), true) - task = index.set_settings(final_settings) - index.wait_task(task.raw_response["taskID"]) if synchronous + s = final_settings.map do |k, v| + [settings.setting_name(k), v] + end.to_h + + synonyms = s.delete("synonyms") || s.delete(:synonyms) + unless synonyms.nil? || synonyms.empty? + resp = AlgoliaSearch.client.save_synonyms(index_name,synonyms.map {|s| Algolia::Search::SynonymHit.new({object_id: s.join("-"), synonyms: s, type: "synonym"}) } ) + AlgoliaSearch.client.wait_for_task(index_name, resp.task_id) if synchronous + end + + resp = AlgoliaSearch.client.set_settings(index_name, Algolia::Search::IndexSettings.new(s)) + AlgoliaSearch.client.wait_for_task(index_name, resp.task_id) if synchronous end end - # TODO def algolia_index_objects(objects, synchronous = false) algolia_configurations.each do |options, settings| next if algolia_indexing_disabled?(options) - ensure_init_new(options, settings) + algolia_ensure_init(options, settings) index_name = algolia_index_name(options) next if options[:replica] @@ -622,7 +560,6 @@ def algolia_index_objects(objects, synchronous = false) end end - # TODO def algolia_index!(object, synchronous = false) return if algolia_without_auto_index_scope algolia_configurations.each do |options, settings| @@ -630,7 +567,7 @@ def algolia_index!(object, synchronous = false) object_id = algolia_object_id_of(object, options) index_name = algolia_index_name(options) - ensure_init_new(options, settings) + algolia_ensure_init(options, settings) next if options[:replica] if algolia_indexable?(object, options) @@ -650,14 +587,13 @@ def algolia_index!(object, synchronous = false) nil end - # TODO def algolia_remove_from_index!(object, synchronous = false) return if algolia_without_auto_index_scope object_id = algolia_object_id_of(object) raise ArgumentError.new("Cannot index a record with a blank objectID") if object_id.blank? algolia_configurations.each do |options, settings| next if algolia_indexing_disabled?(options) - ensure_init_new(options, settings) + algolia_ensure_init(options, settings) index_name = algolia_index_name(options) next if options[:replica] @@ -670,12 +606,11 @@ def algolia_remove_from_index!(object, synchronous = false) nil end - # TODO def algolia_clear_index!(synchronous = false) algolia_configurations.each do |options, settings| next if algolia_indexing_disabled?(options) || options[:replica] - ensure_init_new(options, settings) + algolia_ensure_init(options, settings) index_name = algolia_index_name(options) res = AlgoliaSearch.client.clear_objects(index_name) @@ -686,7 +621,6 @@ def algolia_clear_index!(synchronous = false) nil end - # TODO def algolia_raw_search(q, params = {}) index_name_base = params.delete(:index) || @@ -730,7 +664,6 @@ def algolia_init_raw_answer(json) end end - # TODO def algolia_search(q, params = {}) if AlgoliaSearch.configuration[:pagination_backend] # kaminari, will_paginate, and pagy start pagination at 1, Algolia starts at 0 @@ -764,7 +697,6 @@ def algolia_search(q, params = {}) res end - # TODO def algolia_search_for_facet_values(facet, text, params = {}) index_name = params.delete(:index) || params.delete('index') || @@ -782,11 +714,11 @@ def algolia_search_for_facet_values(facet, text, params = {}) def ensure_algolia_index(name = nil) if name algolia_configurations.each do |o, s| - return ensure_init_new(o, s) if o[:index_name].to_s == name.to_s + return algolia_ensure_init(o, s) if o[:index_name].to_s == name.to_s end raise ArgumentError.new("Invalid index/replica name: #{name}") end - ensure_init_new + algolia_ensure_init end def algolia_index_name(options = nil, index_name = nil) @@ -826,40 +758,7 @@ def algolia_must_reindex?(object) protected - # TODO - deprecate - def algolia_ensure_init(options = nil, settings = nil, index_settings = nil) - raise ArgumentError.new('No `algoliasearch` block found in your model.') if algoliasearch_settings.nil? - - @algolia_indexes ||= {} - - options ||= algoliasearch_options - settings ||= algoliasearch_settings - - return @algolia_indexes[settings] if @algolia_indexes[settings] - - @algolia_indexes[settings] = SafeIndex.new(algolia_index_name(options), algoliasearch_options[:raise_on_failure]) - - index_settings ||= settings.to_settings - index_settings = options[:primary_settings].to_settings.merge(index_settings) if options[:inherit] - replicas = index_settings.delete(:replicas) || - index_settings.delete('replicas') - index_settings[:replicas] = replicas unless replicas.nil? || options[:inherit] - - options[:check_settings] = true if options[:check_settings].nil? - - current_settings = if options[:check_settings] && !algolia_indexing_disabled?(options) - @algolia_indexes[settings].get_settings(:getVersion => 1) rescue nil # if the index doesn't exist - end - - if !algolia_indexing_disabled?(options) && options[:check_settings] && algoliasearch_settings_changed?(current_settings, index_settings) - set_settings_method = options[:synchronous] ? :set_settings! : :set_settings - @algolia_indexes[settings].send(set_settings_method, index_settings) - end - - @algolia_indexes[settings] - end - - def ensure_init_new(options = nil, settings = nil, index_settings_hash = nil) + def algolia_ensure_init(options = nil, settings = nil, index_settings_hash = nil) raise ArgumentError.new('No `algoliasearch` block found in your model.') if algoliasearch_settings.nil? @algolia_indexes_init ||= {} @@ -903,7 +802,6 @@ def ensure_init_new(options = nil, settings = nil, index_settings_hash = nil) private - # TODO def algolia_configurations raise ArgumentError.new('No `algoliasearch` block found in your model.') if algoliasearch_settings.nil? if @configurations.nil? diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 041d7e2..88b952e 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -366,7 +366,7 @@ def public? describe 'DisabledIndexing' do it 'should not call get_settings' do expect_any_instance_of(Algolia::SearchClient).not_to receive(:get_settings) - DisabledIndexing.send(:ensure_init_new) + DisabledIndexing.send(:algolia_ensure_init) end end @@ -392,7 +392,7 @@ class EnableCheckSettingsSynchronously < ActiveRecord::Base it 'should call set_setting with wait_task(sync)' do expect_any_instance_of(Algolia::SearchClient).to receive(:set_settings).and_call_original # wait_task use this return val expect_any_instance_of(Algolia::SearchClient).to receive(:wait_for_task) - EnableCheckSettingsSynchronously.send(:ensure_init_new) + EnableCheckSettingsSynchronously.send(:algolia_ensure_init) end end @@ -403,7 +403,7 @@ class EnableCheckSettingsSynchronously < ActiveRecord::Base it 'should not call set_setting' do expect_any_instance_of(Algolia::SearchClient).not_to receive(:set_settings) - EnableCheckSettingsSynchronously.send(:ensure_init_new) + EnableCheckSettingsSynchronously.send(:algolia_ensure_init) end end end @@ -430,7 +430,7 @@ class EnableCheckSettingsAsynchronously < ActiveRecord::Base it 'should call set_setting without wait_task(sync)' do expect_any_instance_of(Algolia::SearchClient).to receive(:set_settings) expect_any_instance_of(Algolia::SearchClient).not_to receive(:wait_for_task) - EnableCheckSettingsAsynchronously.send(:ensure_init_new) + EnableCheckSettingsAsynchronously.send(:algolia_ensure_init) end end @@ -441,7 +441,7 @@ class EnableCheckSettingsAsynchronously < ActiveRecord::Base it 'should not call set_setting' do expect_any_instance_of(Algolia::SearchClient).not_to receive(:set_settings) - EnableCheckSettingsAsynchronously.send(:ensure_init_new) + EnableCheckSettingsAsynchronously.send(:algolia_ensure_init) end end end @@ -453,7 +453,7 @@ class EnableCheckSettingsAsynchronously < ActiveRecord::Base it 'should call get_settings' do expect_any_instance_of(Algolia::SearchClient).to receive(:get_settings) - SequelBook.send(:ensure_init_new) + SequelBook.send(:algolia_ensure_init) end it "should index the book" do @@ -1254,7 +1254,7 @@ class ForwardToReplicas < ActiveRecord::Base end it 'shouldn\'t have inherited from the primary' do - ForwardToReplicas.send :ensure_init_new + ForwardToReplicas.send :algolia_ensure_init # Hacky way to have a wait on set_settings ForwardToReplicas.create(:name => 'val') @@ -1292,9 +1292,9 @@ class ForwardToReplicasTwo < ActiveRecord::Base end end - ForwardToReplicas.send :ensure_init_new + ForwardToReplicas.send :algolia_ensure_init - ForwardToReplicasTwo.send :ensure_init_new + ForwardToReplicasTwo.send :algolia_ensure_init # Hacky way to have a wait on set_settings ForwardToReplicasTwo.create(:name => 'val') @@ -1332,7 +1332,7 @@ class ForwardToReplicasTwo < ActiveRecord::Base end end - ForwardToReplicas.send :ensure_init_new + ForwardToReplicas.send :algolia_ensure_init # Hacky way to hook replica settings update ForwardToReplicas.create(:name => 'val') @@ -1340,7 +1340,7 @@ class ForwardToReplicasTwo < ActiveRecord::Base expect_any_instance_of(Algolia::SearchClient).not_to receive(:set_settings) - ForwardToReplicasTwo.send :ensure_init_new + ForwardToReplicasTwo.send :algolia_ensure_init # Hacky way to hook replica settings update ForwardToReplicasTwo.create(:name => 'val2') @@ -1543,9 +1543,9 @@ class ForwardToReplicasTwo < ActiveRecord::Base describe 'Disabled' do before(:all) do - DisabledBoolean.send(:ensure_init_new) - DisabledProc.send(:ensure_init_new) - DisabledSymbol.send(:ensure_init_new) + DisabledBoolean.send(:algolia_ensure_init) + DisabledProc.send(:algolia_ensure_init) + DisabledSymbol.send(:algolia_ensure_init) end it "should disable the indexing using a boolean" do From 8338b5295cfd4f12a1ae73707b287605172e4715 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 16:06:50 +0200 Subject: [PATCH 33/40] Update algoliasearch-rails.gemspec --- algoliasearch-rails.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/algoliasearch-rails.gemspec b/algoliasearch-rails.gemspec index af05a53..1273172 100644 --- a/algoliasearch-rails.gemspec +++ b/algoliasearch-rails.gemspec @@ -79,7 +79,7 @@ Gem::Specification.new do |s| if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q, [">= 1.5.1"]) - s.add_runtime_dependency(%q, ["< 3.0.0"]) + s.add_runtime_dependency(%q, [">= 3.5.0"]) s.add_development_dependency(%q, [">= 2.3.15"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) @@ -87,7 +87,7 @@ Gem::Specification.new do |s| s.add_development_dependency "rdoc" else s.add_dependency(%q, [">= 1.5.1"]) - s.add_dependency(%q, ["< 3.0.0"]) + s.add_dependency(%q, [">= 3.5.0"]) end else s.add_dependency(%q, [">= 1.5.1"]) From 7c56ebe394a914e511093999c3e46914a19472ff Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 16:16:14 +0200 Subject: [PATCH 34/40] Update spec_helper.rb --- spec/spec_helper.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8860569..4f4175f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -32,8 +32,12 @@ # Remove all indexes setup in this run in local or CI c.after(:suite) do safe_index_list.each do |i| - res = AlgoliaSearch.client.delete_index(i.name) - AlgoliaSearch.client.wait_for_task(i.name, res.task_id) + begin + res = AlgoliaSearch.client.delete_index(i.name) + AlgoliaSearch.client.wait_for_task(i.name, res.task_id) + rescue + # fail gracefully + end end end end From fc5e4a1cfcbbb0e09c8661a4fc7b83e720fa1f43 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:56:07 +0200 Subject: [PATCH 35/40] address feedback --- lib/algoliasearch-rails.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/algoliasearch-rails.rb b/lib/algoliasearch-rails.rb index a702677..21ee87f 100644 --- a/lib/algoliasearch-rails.rb +++ b/lib/algoliasearch-rails.rb @@ -496,7 +496,7 @@ def algolia_reindex(batch_size = AlgoliaSearch::IndexSettings::DEFAULT_BATCH_SIZ if options[:check_settings] == false && master_exists task_id = AlgoliaSearch.client.operation_index( index_name, - Algolia::Search::OperationIndexParams.new(operation: "copy", destination: tmp_index_name, scope: %w[settings synonyms rules]) + Algolia::Search::OperationIndexParams.new(operation: Algolia::Search::OperationType::COPY, destination: tmp_index_name, scope: %w[settings synonyms rules]) ).task_id AlgoliaSearch.client.wait_for_task(index_name, task_id) end @@ -538,11 +538,11 @@ def algolia_set_settings(synchronous = false) synonyms = s.delete("synonyms") || s.delete(:synonyms) unless synonyms.nil? || synonyms.empty? resp = AlgoliaSearch.client.save_synonyms(index_name,synonyms.map {|s| Algolia::Search::SynonymHit.new({object_id: s.join("-"), synonyms: s, type: "synonym"}) } ) - AlgoliaSearch.client.wait_for_task(index_name, resp.task_id) if synchronous + AlgoliaSearch.client.wait_for_task(index_name, resp.task_id) if synchronous || options[:synchronous] end resp = AlgoliaSearch.client.set_settings(index_name, Algolia::Search::IndexSettings.new(s)) - AlgoliaSearch.client.wait_for_task(index_name, resp.task_id) if synchronous + AlgoliaSearch.client.wait_for_task(index_name, resp.task_id) if synchronous || options[:synchronous] end end From 1d81f478149ef3029370de7ccd82e91220933f72 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:21:22 +0200 Subject: [PATCH 36/40] feat: allow setting user agent --- lib/algoliasearch/configuration.rb | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/algoliasearch/configuration.rb b/lib/algoliasearch/configuration.rb index 13aeaad..83020fb 100644 --- a/lib/algoliasearch/configuration.rb +++ b/lib/algoliasearch/configuration.rb @@ -1,9 +1,5 @@ module AlgoliaSearch module Configuration - REQUIRED_CONFIGURATION = { - user_agent: "Algolia for Rails (#{AlgoliaSearch::VERSION}); Rails (#{defined?(::Rails::VERSION::STRING) ? ::Rails::VERSION::STRING : 'unknown'})", - } - def initialize @client = nil end @@ -13,11 +9,8 @@ def configuration end def configuration=(configuration) - user_agent = [REQUIRED_CONFIGURATION[:user_agent], configuration[:append_to_user_agent]].compact.join('; ') @@configuration = default_configuration - .merge(configuration) - .merge(REQUIRED_CONFIGURATION) - .merge({ user_agent: user_agent }) + .merge(configuration) end def client @@ -29,7 +22,16 @@ def client end def setup_client - @client = Algolia::SearchClient.create(@@configuration[:application_id], @@configuration[:api_key]) + @client = Algolia::SearchClient.create( + @@configuration[:application_id], + @@configuration[:api_key], + { + user_agent_segments: [ + "Algolia for Rails (#{AlgoliaSearch::VERSION})", + "Rails (#{defined?(::Rails::VERSION::STRING) ? ::Rails::VERSION::STRING : 'unknown'})", + @@configuration[:append_to_user_agent] + ].compact + }) end def default_configuration From 72998fd24f62c3bba08cc60f93d34ed5f29b372a Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:29:18 +0200 Subject: [PATCH 37/40] pin version --- Gemfile | 2 +- algoliasearch-rails.gemspec | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 83d5347..180e072 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source "http://rubygems.org" gem 'json', '>= 1.5.1' -gem 'algolia', '>= 3.5.0' +gem 'algolia', '>= 3.5.2' if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' gem 'rubysl', '~> 2.0', :platform => :rbx diff --git a/algoliasearch-rails.gemspec b/algoliasearch-rails.gemspec index 1273172..e23ebb7 100644 --- a/algoliasearch-rails.gemspec +++ b/algoliasearch-rails.gemspec @@ -79,7 +79,7 @@ Gem::Specification.new do |s| if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q, [">= 1.5.1"]) - s.add_runtime_dependency(%q, [">= 3.5.0"]) + s.add_runtime_dependency(%q, [">= 3.5.2"]) s.add_development_dependency(%q, [">= 2.3.15"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) @@ -87,7 +87,7 @@ Gem::Specification.new do |s| s.add_development_dependency "rdoc" else s.add_dependency(%q, [">= 1.5.1"]) - s.add_dependency(%q, [">= 3.5.0"]) + s.add_dependency(%q, [">= 3.5.2"]) end else s.add_dependency(%q, [">= 1.5.1"]) From 5b3ceead349252cd951d1086aee416f1b57fd170 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:32:31 +0200 Subject: [PATCH 38/40] Update algoliasearch-rails.gemspec --- algoliasearch-rails.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algoliasearch-rails.gemspec b/algoliasearch-rails.gemspec index e23ebb7..64645a1 100644 --- a/algoliasearch-rails.gemspec +++ b/algoliasearch-rails.gemspec @@ -91,7 +91,7 @@ Gem::Specification.new do |s| end else s.add_dependency(%q, [">= 1.5.1"]) - s.add_dependency(%q, ["< 3.0.0"]) + s.add_dependency(%q, [">= 3.5.2"]) end end From 54e696fac4c1242a25b4befca4d5633ab526c1dc Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Fri, 18 Oct 2024 09:15:11 +0200 Subject: [PATCH 39/40] Update config.yml --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index c6e59d5..ec150e8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -74,12 +74,14 @@ workflows: ci: jobs: - test: + name: "Ruby << matrix.version >> - Rails << matrix.rails-version >>" matrix: parameters: version: [ '2.5', '2.6', '2.7', '3.0', '3.1' ] rails-version: [ '6.0', '6.1' ] sequel-version: [ '5.0' ] - test: + name: "Ruby << matrix.version >> - Rails << matrix.rails-version >>" matrix: parameters: version: ['3.0', '3.1'] From b23f7f2aba5286989e8b00a5efe199ccec28cf44 Mon Sep 17 00:00:00 2001 From: Devin Beeuwkes <46448173+DevinCodes@users.noreply.github.com> Date: Fri, 18 Oct 2024 11:32:51 +0200 Subject: [PATCH 40/40] prep release --- CHANGELOG.MD | 6 +++- UPGRADING_TO_V3.MD | 66 ++++++++++++++++++++++++++++++++++++ lib/algoliasearch/version.rb | 2 +- 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 UPGRADING_TO_V3.MD diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 6ac3967..27de238 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,6 +1,10 @@ # CHANGELOG -## [Unreleased](https://github.com/algolia/algoliasearch-rails/compare/2.2.1...master) +## [Unreleased](https://github.com/algolia/algoliasearch-rails/compare/3.0.0...master) + +## [3.0.0](https://github.com/algolia/algoliasearch-rails/compare/2.3.2...3.0.0) +This new major version leverages the latest version of the Ruby Algolia API client. It also drops (official) support for Rails 5.x and Ruby versions older than 2.5 +For a list of known breaking changes, please refer to [the upgrade guide](./UPGRADING_TO_V3.MD) ## [2.3.2](https://github.com/algolia/algoliasearch-rails/compare/2.3.1...2.3.2) ### Added diff --git a/UPGRADING_TO_V3.MD b/UPGRADING_TO_V3.MD new file mode 100644 index 0000000..f94a479 --- /dev/null +++ b/UPGRADING_TO_V3.MD @@ -0,0 +1,66 @@ +Version 3 of the `algoliasearch-rails` gem replaces the Algolia API client version in use from version 2 to version 3. +These versions of the API client differ significantly, so you likely need to make code changes when updating. +We've tried keeping most of the changes internal, but there are still some breaking changes you need to be aware of when upgrading. + +If you encounter any breaking changes to the Rail integration that are not listed here, please open a Pull Request to add them to this list. + +## Breaking changes + +`algolia_ensure_init` (this method is protected and shouldn't be called manually, but we list it here anyways): the method no longer returns an initialized `index` object as this is not part of the new API client. The method now returns nothing, but it still ensures the index exists and applies settings if needed. + +--- +`Model.search`, `Model.raw_search`: response keys in the new API client are no longer strings, but are *always* symbols. For example: +```ruby +# Before +results = Product.raw_search('shirt') +p results['hits'] + +# After +results = Product.raw_search('shirt') +p results[:hits] +``` +--- +`Model.search_for_facet_values`: this no longer returns an array of hashes, but an array of objects of type `Algolia::Search::FacetHits`: +```ruby +# Before +facets = Color.search_for_facet_values('short_name', 'bl', :query => 'black') +puts facets.first['value'] + +# After +facets = Color.search_for_facet_values('short_name', 'bl', :query => 'black') +facets.first.value +``` + +--- +`Model.index_name` takes an additional, optional parameter. You can use this if you want to get the name of one of your replica indices, which ensures the index naming takes configuration that modifies the index name into account. +For example, if you have the `:per_environment` option set to true, it will automatically add the environment name in the index name. +```ruby +def Product + include AlgoliaSearch + + algoliasearch({ per_environment: true }) do + add_replica 'Suits', per_environment: true do + # replica settings + end + end + +end +main_index_name = Product.index_name +replica_index_name = Product.index_name('Suits') +``` + +--- +`AlgoliaSearch::Configuration.client_opts`, `AlgoliaSearch::Configuration::REQUIRED_CONFIGURATION` and `AlgoliaSearch::SafeIndex` have been removed. +If you need to configure the API client other than the ways that are provided now, it's recommended to set up an instance manually. + +--- +`Model.index` and `Model.algolia_index` have been removed, as there is no notion of an `Index` object in the new version of the API clients. +Instead, you can use `Model.index_name` to get the name of the index to target, and use this on an instance of the API client directly. + +```ruby +# Before +res = Product.index.search('shoe') + +# After +res = AlgoliaSearch.client.search_single_index(Product.index_name, { query: 'shoe' }) +``` diff --git a/lib/algoliasearch/version.rb b/lib/algoliasearch/version.rb index 2748a12..bbc2c50 100644 --- a/lib/algoliasearch/version.rb +++ b/lib/algoliasearch/version.rb @@ -1,3 +1,3 @@ module AlgoliaSearch - VERSION = '2.3.2' + VERSION = '3.0.0' end