<commit_before>begin
  require "rubygems"
  require "bundler"

  Bundler.setup :default
rescue => e
  puts "AlgoliaSearch: #{e.message}"
end
require 'algoliasearch'

require 'algoliasearch/utilities'

if defined? Rails
  begin
    require 'algoliasearch/railtie'
  rescue LoadError
  end
end

module AlgoliaSearch

  class NotConfigured < StandardError; end
  class BadConfiguration < StandardError; end
  class NoBlockGiven < StandardError; end

  autoload :Configuration, 'algoliasearch/configuration'
  extend Configuration

  autoload :Pagination, 'algoliasearch/pagination'

  class << self
    attr_reader :included_in

    def included(klass)
      @included_in ||= []
      @included_in << klass
      @included_in.uniq!

      klass.send :include, InstanceMethods
      klass.extend ClassMethods
    end

  end

  class IndexOptions

    # AlgoliaSearch settings
    OPTIONS = [:attributesToIndex, :minWordSizefor1Typo,
      :minWordSizefor2Typos, :hitsPerPage, :attributesToRetrieve,
      :attributesToHighlight, :attributesToSnippet, :attributesToIndex,
      :ranking, :customRanking, :queryType, :attributesForFaceting]
    OPTIONS.each do |k|
      define_method k do |v|
        instance_variable_set("@#{k}", v)
      end
    end

    # attributes to consider
    attr_accessor :attributes

    def initialize(block)
      instance_exec(&block) if block
    end

    def attribute(*names)
      self.attributes ||= []
      self.attributes += names
    end

    def get(setting)
      instance_variable_get("@#{setting}")
    end

    def to_settings
      settings = {}
      OPTIONS.each do |k|
        v = get(k)
        settings[k] = v if !v.nil?
      end
      settings
    end
  end

  # these are the class methods added when AlgoliaSearch is included
  module ClassMethods

    def algoliasearch(options = {}, &block)
      @index_options = IndexOptions.new(block_given? ? Proc.new : nil)
      attr_accessor :highlight_result

      if options[:synchronous] == true
        after_validation :mark_synchronous if respond_to?(:before_validation)
      end
      unless options[:auto_index] == false
        after_validation :mark_must_reindex if respond_to?(:after_validation)
        before_save :mark_for_auto_indexing if respond_to?(:before_save)
        after_save :perform_index_tasks if respond_to?(:after_save)
      end
      unless options[:auto_remove] == false
        after_destroy { |searchable| searchable.remove_from_index! } if respond_to?(:after_destroy)
      end

      @options = { type: model_name, per_page: @index_options.get(:hitsPerPage) || 10, page: 1 }.merge(options)
    end

    def reindex!(batch_size = 1000, synchronous = false)
      ensure_init
      last_task = nil
      find_in_batches(batch_size: batch_size) do |group|
        objects = group.map { |o| attributes(o).merge 'objectID' => o.id.to_s }
        last_task = @index.save_objects(objects)
      end
      @index.wait_task(last_task["taskID"]) if last_task and synchronous == true
    end

    def index!(object, synchronous = false)
      ensure_init
      if synchronous
        @index.add_object!(attributes(object), object.id.to_s)
      else
        @index.add_object(attributes(object), object.id.to_s)
      end
    end

    def remove_from_index!(object, synchronous = false)
      ensure_init
      if synchronous
        @index.delete_object!(object.id.to_s)
      else
        @index.delete_object(object.id.to_s)
      end
    end

    def clear_index!
      ensure_init
      @index.delete
      @index = nil
    end

    def search(q, settings = {})
      json = @index.search(q, Hash[settings.map { |k,v| [k.to_s, v.to_s] }])
      results = json['hits'].map do |hit|
        o = Object.const_get(@options[:type]).find(hit['objectID'])
        o.highlight_result = hit['_highlightResult']
        o
      end
      AlgoliaSearch::Pagination.create(results, json['nbHits'].to_i, @options)
    end

    def ensure_init
      new_settings = @index_options.to_settings
      return if @index and !index_settings_changed?(@settings, new_settings)
      @index = Algolia::Index.new(index_name)
      current_settings = @index.get_settings rescue nil # if the index doesn't exist
      @index.set_settings(new_settings) if index_settings_changed?(current_settings, new_settings)<commit_msg>Missing ensure_init (bug introduced this morning)<commit_after>begin
  require "rubygems"
  require "bundler"

  Bundler.setup :default
rescue => e
  puts "AlgoliaSearch: #{e.message}"
end
require 'algoliasearch'

require 'algoliasearch/utilities'

if defined? Rails
  begin
    require 'algoliasearch/railtie'
  rescue LoadError
  end
end

module AlgoliaSearch

  class NotConfigured < StandardError; end
  class BadConfiguration < StandardError; end
  class NoBlockGiven < StandardError; end

  autoload :Configuration, 'algoliasearch/configuration'
  extend Configuration

  autoload :Pagination, 'algoliasearch/pagination'

  class << self
    attr_reader :included_in

    def included(klass)
      @included_in ||= []
      @included_in << klass
      @included_in.uniq!

      klass.send :include, InstanceMethods
      klass.extend ClassMethods
    end

  end

  class IndexOptions

    # AlgoliaSearch settings
    OPTIONS = [:attributesToIndex, :minWordSizefor1Typo,
      :minWordSizefor2Typos, :hitsPerPage, :attributesToRetrieve,
      :attributesToHighlight, :attributesToSnippet, :attributesToIndex,
      :ranking, :customRanking, :queryType, :attributesForFaceting]
    OPTIONS.each do |k|
      define_method k do |v|
        instance_variable_set("@#{k}", v)
      end
    end

    # attributes to consider
    attr_accessor :attributes

    def initialize(block)
      instance_exec(&block) if block
    end

    def attribute(*names)
      self.attributes ||= []
      self.attributes += names
    end

    def get(setting)
      instance_variable_get("@#{setting}")
    end

    def to_settings
      settings = {}
      OPTIONS.each do |k|
        v = get(k)
        settings[k] = v if !v.nil?
      end
      settings
    end
  end

  # these are the class methods added when AlgoliaSearch is included
  module ClassMethods

    def algoliasearch(options = {}, &block)
      @index_options = IndexOptions.new(block_given? ? Proc.new : nil)
      attr_accessor :highlight_result

      if options[:synchronous] == true
        after_validation :mark_synchronous if respond_to?(:before_validation)
      end
      unless options[:auto_index] == false
        after_validation :mark_must_reindex if respond_to?(:after_validation)
        before_save :mark_for_auto_indexing if respond_to?(:before_save)
        after_save :perform_index_tasks if respond_to?(:after_save)
      end
      unless options[:auto_remove] == false
        after_destroy { |searchable| searchable.remove_from_index! } if respond_to?(:after_destroy)
      end

      @options = { type: model_name, per_page: @index_options.get(:hitsPerPage) || 10, page: 1 }.merge(options)
    end

    def reindex!(batch_size = 1000, synchronous = false)
      ensure_init
      last_task = nil
      find_in_batches(batch_size: batch_size) do |group|
        objects = group.map { |o| attributes(o).merge 'objectID' => o.id.to_s }
        last_task = @index.save_objects(objects)
      end
      @index.wait_task(last_task["taskID"]) if last_task and synchronous == true
    end

    def index!(object, synchronous = false)
      ensure_init
      if synchronous
        @index.add_object!(attributes(object), object.id.to_s)
      else
        @index.add_object(attributes(object), object.id.to_s)
      end
    end

    def remove_from_index!(object, synchronous = false)
      ensure_init
      if synchronous
        @index.delete_object!(object.id.to_s)
      else
        @index.delete_object(object.id.to_s)
      end
    end

    def clear_index!
      ensure_init
      @index.delete
      @index = nil
    end

    def search(q, settings = {})
      ensure_init
      json = @index.search(q, Hash[settings.map { |k,v| [k.to_s, v.to_s] }])
      results = json['hits'].map do |hit|
        o = Object.const_get(@options[:type]).find(hit['objectID'])
        o.highlight_result = hit['_highlightResult']
        o
      end
      AlgoliaSearch::Pagination.create(results, json['nbHits'].to_i, @options)
    end

    def ensure_init
      new_settings = @index_options.to_settings
      return if @index and !index_settings_changed?(@settings, new_settings)
      @index = Algolia::Index.new(index_name)
      current_settings = @index.get_settings rescue nil # if the index doesn't exist
      @index.set_settings(new_settings) if index_settings_changed?(current_settings, new_settings)
{'fraction_non_alphanumeric': 0.09613615455381785, 'fraction_numerical': 0.0020699172033118675, 'mean_word_length': 3.119848413074372, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3681138', 'n_tokens_mistral': 2767, 'n_tokens_neox': 2692, 'n_words': 613}