Description
I encountered some serious headaches while working with Elasticsearch-Model
in development.
My problem is that the Invalid single-table inheritance type: X is not a subclass of Y
exception was being thrown when I tried to instantiate records with the Multiple
adapter after my code had been reloaded for the first time. I would have to restart my Rails server every time I made any changes to my code.
What I found was that Elasticsearch::Model::Registry.models
would endlessly accumulate reloaded classes each time my code was being reloaded. If I had five classes that included Elasticsearch::Model
, it would increase by 5 each time my code reloaded. I have monkey-patched the Registry
class with:
module Elasticsearch
module Model
class Registry
def add(klass)
+ existing_model = @models.detect { |model| model.name == klass.name }
+ @models.delete(existing_model)
@models << klass
end
end
end
end
in an initializer and only for development environment to fix this particular issue to ensure this Registry only contains the newly-reloaded classes.
After this change, I continued to encounter the same error. What I found was that Elasticsearch::Model::Adapter::Multiple::Records
was caching the result of __type_for_hit
in a class variable @@__types
, and after my code was reloaded, the stale classes were being returned instead of the newly reloaded classes. I unset this class variable by hooking into Active Support's reloader:
Rails.application.reloader.before_class_unload do
Elasticsearch::Model::Adapter::Multiple::Records.remove_class_variable(:@@__types) }
end
This is in the same environment block that the above monkey-patch is in to avoid affecting production environment. This allowed my records to be instantiated even after my code had been reloaded and fixed my issue.
This issue took a ton of time and effort (and frustration) to debug and fix, it would be nice to see the team provide better support for STI since this is a core feature in Rails. Hopefully this report will help you guys improve on some of these weak spots. I'm happy to provide any other information you might need.