Coder Social home page Coder Social logo

Comments (11)

jhoffner avatar jhoffner commented on September 23, 2024 5

@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.

bcackerman avatar bcackerman commented on September 23, 2024 2

@iffyuva what was your work around?

from elasticsearch-rails.

dimroc avatar dimroc commented on September 23, 2024 2

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.

karmi avatar karmi commented on September 23, 2024

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.

wdiechmann avatar wdiechmann commented on September 23, 2024

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.

karmi avatar karmi commented on September 23, 2024

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.

iffyuva avatar iffyuva commented on September 23, 2024

cool. i have a workaround for this problem. will let you know if we run into some problems.

from elasticsearch-rails.

karmi avatar karmi commented on September 23, 2024

@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.

bublik avatar bublik commented on September 23, 2024

any new changes?

from elasticsearch-rails.

iffyuva avatar iffyuva commented on September 23, 2024

@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.

bcackerman avatar bcackerman commented on September 23, 2024

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'
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.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

from elasticsearch-rails.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.