I am working with Elasticsearch persistence model, and have some common methods for each index.
Given an Events Index, I have a service class where some methods are defined, the same goes for other n indexes built of their models.
class EventSearchService
class << self
def with_index(index_name)
old_repository = repository
@repository = EventSearchService::ElasticsearchEventRepository.new(index_name: index_name)
yield
ensure
@repository = old_repository
end
def index_name
repository.index_name
end
def index_all(event_documents)
return unless event_documents.present?
actions = event_documents.map do |e|
{ index: { _index: index_name, _id: e.id, _type: "_doc", data: e.to_hash }}
end
repository.client.bulk(body: actions)
end
protected
def repository
@repository ||= EventSearchService::ElasticsearchEventRepository.new
end
end
end
My problem is that I have ended up with n files with the same class methods. When I try to extract it out to an abstract class directly, I get an error whose investigation reaches me to a point that singleton classes can't be inherited.
After searching for some answers, I followed this thread and I tried to DRY it up
require 'forwardable'
require 'singleton'
class ElasticsearchService
include Singleton
class << self
extend Forwardable
def_delegators(
:with_index,
:index_name,
:index_all,
:repository
)
end
def with_index(index_name)
old_repository = repository
@repository = search_repository.new(index_name: index_name)
yield
ensure
@repository = old_repository
end
def index_name
repository.index_name
end
def index_all(documents)
return unless documents.present?
actions = documents.map do |d|
{ index: { _index: index_name, _id: d.id, _type: "_doc", data: e.to_hash }}
end
repository.client.bulk(body: actions)
end
def search_repository
fail "Needs to be overriden"
end
protected
def repository
@repository ||= search_repository.new
end
end
And I include it as
class EventSearchService < ElasticsearchService
def search_repository
EventSearchService::ElasticsearchEventRepository
end
end
I have redacted the code to keep it small, simple, and related to the cause, but wanted to show different aspects of it. Sorry if it's too long a read.
The error I get is:
`<class:ElasticsearchService>': undefined local variable or method `' for ElasticsearchService:Class (NameError)
This one is very sneaky. There are some non-ASCII space characters inside your code which the ruby interpreter is recognizing as the name of a method that's being called.
I threw your code inside my terminal, getting precisely the same error as you, but after writing it by hand and executing method by method, did not get it.
Found a conversor online and after copy/pasting your code (here's the link to the one I used), the code ran without that error.
So formatting the file properly should do the trick with that particular error you're experiencing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With