Plugins are the primary extension mechanism in Esse. They can:
- Add class methods to indices and repositories.
- Hook into the index load process.
- Wrap or override existing behavior.
- Add custom DSL methods.
Official extensions (esse-active_record, esse-async_indexing, esse-jbuilder, etc.) are all plugins.
Using plugins
class UsersIndex < Esse::Index plugin :active_record plugin :async_indexing plugin MyCustomPlugin, option: 'value'end
UsersIndex.plugins # => [Esse::Plugins::ActiveRecord, Esse::Plugins::AsyncIndexing, MyCustomPlugin]You can pass a symbol (which is required from esse/plugins/<name>) or a module directly. Options and blocks are forwarded to apply / configure.
Writing a plugin
A plugin is a module under Esse::Plugins:: with any of the following hooks:
module Esse module Plugins module MyPlugin # Called once when the plugin is added to the index def self.apply(index, **options, &block) # install class-level defaults, validate options, etc. end
# Called after apply, for DSL-style configuration def self.configure(index, **options, &block) index.some_setting = options[:default] end
# Mixed into index classes (available on MyIndex.*) module IndexClassMethods def custom_index_method # ... end end
# Mixed into each repository class (available on MyIndex::Repo.*) module RepositoryClassMethods def custom_repo_method # ... end end end endendLoad the plugin (either autoload via plugin :my_plugin which requires esse/plugins/my_plugin, or require it manually), then:
class UsersIndex < Esse::Index plugin :my_plugin, default: :fooend
UsersIndex.custom_index_methodUsersIndex.repo(:user).custom_repo_methodPlugin execution order
plugin :namecallsapply(index, **opts, &block)on the module.configure(index, **opts, &block)runs.IndexClassMethodsare extended into the index class.RepositoryClassMethodsare extended into each repository as they’re declared.
Plugins declared earlier apply first; later plugins can override earlier behavior.
Inheriting plugins
Plugins are inherited by subclasses:
class AppIndex < Esse::Index plugin :active_recordend
class UsersIndex < AppIndex # active_record is already appliedendExample: a simple plugin
module Esse::Plugins::DefaultLogger def self.apply(index, **) Esse.logger.info "Loaded index #{index.name}" end
module IndexClassMethods def log_info Esse.logger.info "#{name}: #{cluster_id}" end endend
class UsersIndex < Esse::Index plugin Esse::Plugins::DefaultLoggerend
UsersIndex.log_infoExample: an ORM-style plugin
This is a simplified version of what esse-active_record does:
module Esse::Plugins::MyORM module RepositoryClassMethods def collection(klass, **opts, &block) coll_class = Class.new(Esse::Collection) do define_method(:each) do klass.find_in_batches(batch_size: opts[:batch_size] || 1_000) do |batch| yield(batch, @params) end end end super(coll_class, **opts, &block) end endendUsing existing extensions
See extensions.md for the curated list. For each, plugin :<name> enables it — the rest is ORM-specific DSL documented in its own docs/.