module Esse::Index::ClassMethods

Constants

TEMPLATE_DIRS

Attributes

abstract_class[RW]

Set this to true if this is an abstract class

cluster_id[R]
type_hash[W]

Public Instance Methods

Index(source) click to toggle source

Lets you create a Index subclass with its elasticsearch cluster

Example:

# Using a custom cluster
Esse.config.clusters(:v1).client = Elasticsearch::Client.new
class UsersIndex < Esse::Index(:v1)
end

# Using :default cluster
class UsersIndex < Esse::Index
end
# File lib/esse/index/base.rb, line 45
      def Index(source) # rubocop:disable Naming/MethodName
        klass = Class.new(self)

        valid_ids = Esse.config.cluster_ids
        klass.cluster_id = \
          case source
          when Esse::Cluster
            source.id
          when String, Symbol
            id = source.to_sym
            id if valid_ids.include?(id)
          end

        msg = <<~MSG
          We could not resolve the index cluster using the argument %<arg>p. \n
          It must be previously defined in the `Esse.config' settings. \n
          Here is the list of cluster ids we have configured: %<ids>s\n

          You can ignore this cluster id entirely. That way the :default id will be used.\n
          Example: \n
            class UsersIndex < Esse::Index\n
            end\n
        MSG
        unless klass.cluster_id
          raise ArgumentError.new, format(msg, arg: source, ids: valid_ids.map(&:inspect).join(', '))
        end

        klass.type_hash = {}
        klass
      end
abstract_class?() click to toggle source
# File lib/esse/index/inheritance.rb, line 9
def abstract_class?
  return @abstract_class == true if defined?(@abstract_class)

  !index_name?
end
backend() click to toggle source
# File lib/esse/index/backend.rb, line 6
def backend
  Esse::Backend::Index.new(self)
end
cluster() click to toggle source

@return [Esse::Cluster] an instance of cluster based on its cluster_id

# File lib/esse/index/base.rb, line 92
      def cluster
        unless Esse.config.cluster_ids.include?(cluster_id)
          raise NotImplementedError, <<~MSG
            There is no cluster configured for this index. Use `Esse.config.clusters(cluster_id) { ... }' define the elasticsearch
            client connection.
          MSG
        end

        Esse.synchronize { Esse.config.clusters(cluster_id) }
      end
cluster_id=(cluster_id) click to toggle source

Sets the client_id associated with the Index class. This can be used directly on Esse::Index to set the :default es cluster to be used by subclasses, or to override the es client used for specific indices:

Esse::Index.cluster_id = :v1
ArtistIndex = Class.new(Esse::Index)
ArtistIndex.cluster_id = :v2
# File lib/esse/index/base.rb, line 82
def cluster_id=(cluster_id)
  @cluster_id = cluster_id
end
def_Index(index_module) click to toggle source

Define a Index method on the given module that calls the Index method on the receiver. This is how the Esse::Index() method is defined, and allows you to define Index() methods on other modules, making it easier to have custom index settings for all indexes under a namespace. Example:

module V1
  EsIndex = Class.new(Esse::Index)
  EsIndex.def_Index(self)

  class Bar < EsIndex
    # Uses :default elasticsearch client connection
  end

  class Baz < EsIndex(:v1)
    # Uses :v1 elasticsearch client connection
  end
end
# File lib/esse/index/base.rb, line 26
def def_Index(index_module) # rubocop:disable Naming/MethodName
  tap do |model|
    index_module.define_singleton_method(:Index) do |source|
      model.Index(source)
    end
  end
end
define_type(type_name, &block) click to toggle source
# File lib/esse/index/type.rb, line 12
def define_type(type_name, &block)
  type_class = Class.new(Esse::IndexType)

  const_set(Hstring.new(type_name).camelize.demodulize.to_s, type_class)

  index = self

  type_class.send(:define_singleton_method, :index) { index }
  type_class.send(:define_singleton_method, :type_name) { type_name.to_s }

  type_class.class_eval(&block) if block

  self.type_hash = type_hash.merge(type_class.type_name => type_class)
  type_class
end
index_directory() click to toggle source
# File lib/esse/index/naming.rb, line 35
def index_directory
  return unless uname
  return if uname == 'Esse::Index'

  Esse.config.indices_directory.join(uname).to_s
end
index_name() click to toggle source
# File lib/esse/index/naming.rb, line 15
def index_name
  @index_name || index_prefixed_name(normalized_name)
end
index_name=(value) click to toggle source
# File lib/esse/index/naming.rb, line 11
def index_name=(value)
  @index_name = index_prefixed_name(value)
end
index_name?() click to toggle source
# File lib/esse/index/naming.rb, line 19
def index_name?
  !index_name.nil?
end
index_version() click to toggle source
# File lib/esse/index/naming.rb, line 27
def index_version
  @index_version
end
index_version=(value) click to toggle source
# File lib/esse/index/naming.rb, line 23
def index_version=(value)
  @index_version = Hstring.new(value.to_s).underscore.presence
end
inspect() click to toggle source
Calls superclass method
# File lib/esse/index/base.rb, line 103
def inspect
  if self == Index
    super
  elsif abstract_class?
    "#{super}(abstract)"
  elsif index_name?
    "#{super}(Index: #{index_name})"
  else
    "#{super}(Index is not defined)"
  end
end
mappings(hash = {}, &block) click to toggle source

This method is only used to define mapping

# File lib/esse/index/mappings.rb, line 17
def mappings(hash = {}, &block)
  @mapping = Esse::IndexMapping.new(body: hash, paths: template_dirs)
  return unless block_given?

  @mapping.define_singleton_method(:as_json, &block)
end
mappings_hash() click to toggle source

This is the actually content that will be passed through the ES api

# File lib/esse/index/mappings.rb, line 12
def mappings_hash
  { Esse::MAPPING_ROOT_KEY => (index_mapping || type_mapping) }
end
settings(hash = {}, &block) click to toggle source

Define /_settings definition by each index.

hash: The body of the request includes the updated settings. block: Overwrite default :as_json from IndexSetting instance

Example:

class UserIndex < Esse::Index
  settings {
    number_of_replicas: 4,
  }
end

class UserIndex < Esse::Index
  settings do
    # do something to load settings..
  end
end
# File lib/esse/index/settings.rb, line 31
def settings(hash = {}, &block)
  @setting = Esse::IndexSetting.new(body: hash, paths: template_dirs, globals: cluster.index_settings)
  return unless block_given?

  @setting.define_singleton_method(:as_json, &block)
end
settings_hash(cluster_settings: true) click to toggle source
# File lib/esse/index/settings.rb, line 8
def settings_hash(cluster_settings: true)
  hash = cluster_settings ? cluster.index_settings.merge(setting.body) : setting.body
  { Esse::SETTING_ROOT_KEY => (hash.key?(Esse::SETTING_ROOT_KEY) ? hash[Esse::SETTING_ROOT_KEY] : hash) }
end
template_dirs() click to toggle source
# File lib/esse/index/naming.rb, line 42
def template_dirs
  return [] unless index_directory

  TEMPLATE_DIRS.map { |term| format(term, dirname: index_directory) }
end
type_hash() click to toggle source
# File lib/esse/index/type.rb, line 8
def type_hash
  @type_hash ||= {}
end
uname() click to toggle source
# File lib/esse/index/naming.rb, line 31
def uname
  Hstring.new(name).underscore.presence
end

Protected Instance Methods

index_prefixed_name(value) click to toggle source
# File lib/esse/index/naming.rb, line 50
def index_prefixed_name(value)
  return if value == '' || value.nil?
  return value.to_s unless cluster.index_prefix

  [cluster.index_prefix, value].join('_')
end
normalized_name() click to toggle source
# File lib/esse/index/naming.rb, line 57
def normalized_name
  Hstring.new(name).demodulize.underscore.sub(/_(index)$/, '')
end

Private Instance Methods

index_mapping() click to toggle source
# File lib/esse/index/mappings.rb, line 30
def index_mapping
  return if mapping.empty?

  hash = mapping.body
  hash.key?(Esse::MAPPING_ROOT_KEY) ? hash[Esse::MAPPING_ROOT_KEY] : hash
end
mapping() click to toggle source
# File lib/esse/index/mappings.rb, line 26
def mapping
  @mapping ||= Esse::IndexMapping.new(paths: template_dirs)
end
setting() click to toggle source
# File lib/esse/index/settings.rb, line 40
def setting
  @setting ||= Esse::IndexSetting.new(paths: template_dirs, globals: cluster.index_settings)
end
type_mapping() click to toggle source
# File lib/esse/index/mappings.rb, line 37
def type_mapping
  return {} if type_hash.empty?

  type_hash.values.map(&:mappings_hash).reduce(&:merge)
end