Comments (11)
@dimroc to build off of what you have, this also makes it so that mappings get directed back to the root ancestor
module ClassMethods
def inherited(subclass)
search_class = self.search_class
index_name = self.index_name
document_type = self.document_type
subclass.instance_eval do
@search_class = search_class
index_name(index_name)
document_type(document_type)
def self.mapping(*args, &block)
search_class.mapping(*args, &block)
end
end
super
end
def search_class
@search_class || self
end
end
from elasticsearch-rails.
@iffyuva what was your work around?
from elasticsearch-rails.
Copying and pasting document_type
and index_name
in every subclass is not a manageable solution in larger code bases.
index_name
should definitely "just work" with STI, and keep in line with the Rails philosophy. Here is my work around that does not require ancestry lookups:
class Animal < ActiveRecord::Base
document_type 'mammal'
index_name 'mammals'
def self.inherited(subclass)
subclass.instance_eval do
document_type 'mammal'
index_name 'mammals'
end
super
end
end
class Dog < Animal
end
class Cat < Animal
end
This could easily be placed into the standard Elasticsearch::Model concern. Here is a robust catch all solution:
module Searchable
extend ActiveSupport::Concern
included do
include Elasticsearch::Model
include BackgroundIndexer
index_name { "#{Rails.env}-#{es_type_name.pluralize}" }
document_type es_type_name
delegate :update_document, :index_document, :delete_document, to: :__elasticsearch__
end
module ClassMethods
# Callback so that subclasses still have index_name assigned.
def inherited(subclass)
subclass.instance_eval do
index_name { "#{Rails.env}-#{es_type_name.pluralize}" }
document_type es_type_name
end
super
end
def es_type_name
name.full_deconstantize.underscore
# full_deconstantize string ext method -> self.split("::").first || self
end
end
end
from elasticsearch-rails.
Is this a bug?
Depends on the perspective. I consider "single table inheritance" itself to be a bug :)
The index_name
method is bound to the @index_name
"class instance variable". The method would have to traverse the ancestor hierarchy, check whether they have an index_name
method, and use it, or fall back to defaults.
I don't think it's worth it for STI, it might be wort when there's some other use-case.
For reference, Tire issues related to STI: https://github.com/karmi/retire/search?q=STI&type=Issues
from elasticsearch-rails.
I use STI all the time - and like to think it saves me a lot of time :)
...and like has_paper_trail it would be a real treat to be able to write has_elastic_search
Everything works for me - except for the #import thing - doing that requires me to 'move' the include Searchable to the 'final' class - Employee in the example below
(tried to dig into the elasticsearch_rails - but that is still waaaayy beyond my 'rails-fu-level' <:) )
/W
class Abstracted < ActiveRecord::Base
self.abstract_class=true
include Exceptions
include PrintEngine
include Searchable
#
# all models inheriting from this will have versions
has_paper_trail
# has_paper_trail :ignore => [:state, :cups_state]
has_many :eventables, as: :eventable
#
# return that part of records which by default will be considered pertinent
# this way we will - later - be able to add some generic views - like
# not providing the deleted records, old records, records in other systems, etc
def self.pertinent
all
end
#
# translate the key
def self.oxt(key, *args)
I18n.t(key, args[0])
end
def oxt(key, *args)
self.class.oxt(key, args[0])
end
#
# when implementing searches on models (using params)
def self.find_with_params(params=nil)
self.search( params )
end
def self.logit( log_type, msg )
Rails.logger.send(log_type, "[OXEN] #{Time.now} [#{log_type.to_s}] #{msg}")
end
def logit( log_type, msg )
Rails.logger.send(log_type, "[OXEN] #{Time.now} [#{log_type.to_s}] #{msg}")
end
# list_title
def list_title
self.respond_to?( "name") ? self.name : "please define list_title on model (#{self.class.to_s})!"
end
# implement on relevant models
def default_record_template
'/record.html.haml'
end
def self.default_list_template
'list.html.haml'
end
def self.default_label_template
'label.html.haml'
end
def print_label options={}
params = {}
params[:print_job] = {}
params[:print_job][:view_template_path] = options[:template] || default_label_template
params[:print_job][:print_driver] = options[:print_driver] || :cab
params[:print_job][:print_format] = options[:print_format] || 'label'
params[:print_job][:paper] = options[:paper] || "Pakkelabel"
params[:printer_name] = options[:printer_name]
params[:user] = options[:user]
self.class.print [self], params
end
def print_record(options={})
params = {}
params[:print_job] = {}
params[:print_job][:view_template_path] = options[:template] || default_record_template
params[:print_job][:print_driver] = options[:print_driver] || :pdf
params[:print_job][:print_format] = options[:print_format] || 'sheet'
params[:print_job][:paper] = options[:paper] || "A4"
params[:printer_name] = options[:printer_name]
params[:user] = options[:user]
self.class.print [self], params
end
def self.print_list(options={})
params = {}
params[:print_job] = {}
params[:print_job][:view_template_path] = options[:template] || self.default_list_template
params[:print_job][:print_driver] = options[:print_driver] || :pdf
params[:print_job][:print_format] = options[:print_format] || 'list'
params[:print_job][:paper] = options[:paper] || "A4"
params[:printer_name] = options[:printer_name]
params[:user] = options[:user]
self.print options[:resources], params
end
# add the child to an association of children
def attach child
case child.class.to_s
when "Event","WageEvent"
ev = Eventable.create( event: child, eventable: self)
self.eventables << ev
when "Printer"
pr = Printable.create( printer: child, printable: self)
else
children = eval child.class.to_s.underscore.pluralize
children << child
end
end
# remove the child from an association of children
def detach child
case child.class.to_s
when "Event","WageEvent"
ev = Eventable.where( event: child, eventable: self).first
ev.delete
when "Printer"
pr = Printable.where( printer: child, printable: self).first
pr.delete
else
children = eval child.class.to_s.downcase.pluralize
children.delete child
end
end
end
module Searchable
extend ActiveSupport::Concern
included do
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
__elasticsearch__.client = Elasticsearch::Client.new log: true
__elasticsearch__.client.transport.logger.formatter = proc { |s, d, p, m| "\e[32m#{m}\n\e[0m" }
include Indexing
after_touch() { __elasticsearch__.index_document }
# mapping do
# # ...
# end
#
# def self.search(query)
# # ...
# end
end
module Indexing
# Customize the JSON serialization for Elasticsearch
# def as_indexed_json(options={})
# self.as_json(
# include: { categories: { only: :title},
# authors: { methods: [:full_name], only: [:full_name] },
# comments: { only: :text }
# })
# end
end
end
class Employee < Abstracted
end
[1] oxen40 » Employee.base_class
=> class Employee < Abstracted {
:id => :integer,
:ox_id => :integer,
:name => :string,
:born_at => :datetime,
:enter_code => :string,
:active => :boolean,
:security_code => :string,
:entrance_code => :string,
:last_came_at => :datetime,
:last_went_at => :datetime,
:hour_pay_cents => :integer,
:wage_union_agreement => :string,
:last_wage_at => :datetime,
:datetime => :datetime,
:over_time_saving => :string,
:wage_service_bureau_emp_nbr => :string,
:bank_account_number => :string,
:lock_version => :integer,
:created_at => :datetime,
:updated_at => :datetime,
:hired_at => :datetime,
:currency => :string,
:white_collar => :boolean
}
[2] oxen40 »
from elasticsearch-rails.
After mulling it over for a while, I think I'll close this one. I really don't like complicating the code with ancestry lookup etc. If there's some great demand for a feature like this, let's reconsider it!
from elasticsearch-rails.
cool. i have a workaround for this problem. will let you know if we run into some problems.
from elasticsearch-rails.
@mathieugagne It would be better to open a specific issue for your problem, since "problems with STI" is too broad. There are definitely solutions for those problems -- not only "workaround".
from elasticsearch-rails.
any new changes?
from elasticsearch-rails.
@bcackerman as described in the issue
class Animal < ActiveRecord::Base
document_type 'mammal'
index_name 'mammals'
end
class Dog < Animal
document_type 'mammal'
index_name 'mammals'
end
class Cat < Animal
document_type 'mammal'
index_name 'mammals'
end
manually declare document_type
and index_name
in each derived class.
from elasticsearch-rails.
Huge +1 to you. Thanks!!
Bruce
On Apr 1, 2016, at 5:49 AM, Yuva [email protected] wrote:
@bcackerman as described in the issue
class Animal < ActiveRecord::Base
document_type 'mammal'
index_name 'mammals'
endclass Dog < Animal
document_type 'mammal'
index_name 'mammals
endclass Cat < Animal
document_type 'mammal'
index_name 'mammals
end
manually declare document_type and index_name in each derived class.—
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
from elasticsearch-rails.
Related Issues (20)
- NPE happens on short prefix query on a field with index_prefixes
- Indexes are not refreshing, even with refresh_interval being set
- Disable automatic callbacks in rspec
- Not getting any records from elasticsearch HOT 1
- FYI gem version 6.1.1 was pushed without any changes HOT 1
- elasticsearch-model 7.2.1 introduces circular dependency with ruby 2.7 and rubygems 3.2.5 HOT 1
- specify an alias near the index_name in an AR model HOT 1
- Illegal argument "type" sent in all requests upgrading to 8.x HOT 1
- Not able to update single record too please help me to here HOT 1
- How to import into two clusters
- Mapping Two Ruby on Rails Models with Different Attribute Names to a Shared Elasticsearch Index using 'elasticsearch-rails'
- update_document not selective enough
- Backward compatibility for older Elasticsearch version HOT 1
- Faraday::ConnectionFailed (end of file reached) HOT 1
- Elasticsearch - Unexpected Character Error (Minus Sign) HOT 1
- Unexpected behavior when searching from a scope
- Feature Suggestion - Get Indexed Document for Instance
- Deprecation warning in Rails 7.1 (support Rails 7.2) HOT 2
- ElasticSearch::Model does not register a subclass HOT 3
- rake elasticsearch:import:model - ArgumentError: unknown keyword: :type (ArgumentError)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from elasticsearch-rails.