|
#
|
|
# Copyright 2014 Red Hat, Inc.
|
|
#
|
|
# This software is licensed to you under the GNU General Public
|
|
# License as published by the Free Software Foundation; either version
|
|
# 2 of the License (GPLv2) or (at your option) any later version.
|
|
# There is NO WARRANTY for this software, express or implied,
|
|
# including the implied warranties of MERCHANTABILITY,
|
|
# NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
|
|
# have received a copy of GPLv2 along with this software; if not, see
|
|
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
|
|
|
module Katello
|
|
module Ext::IndexedModel
|
|
|
|
# TODO: move methods out into submodule
|
|
# rubocop:disable MethodLength
|
|
def self.included(base)
|
|
base.class_eval do
|
|
|
|
cattr_accessor :class_index_options
|
|
|
|
def self.display_attributes
|
|
self.class_index_options[:display_attrs].sort{|a, b| a.to_s <=> b.to_s}
|
|
end
|
|
|
|
if Rails.env.development? || Rails.env.production?
|
|
include Tire::Model::Search
|
|
include Tire::Model::Callbacks
|
|
index_name Katello.config.elastic_index + '_' + self.base_class.name.downcase
|
|
|
|
#Shared analyzers. If you need a model-specific analyzer for some reason,
|
|
# we'll need to refactor this to support that.
|
|
settings :analysis => {
|
|
:filter => Util::Search.custom_filters,
|
|
:analyzer => Util::Search.custom_analyzers
|
|
}
|
|
|
|
def self.index_import(list)
|
|
self.index.import(list)
|
|
end
|
|
|
|
after_save :refresh_index
|
|
|
|
else
|
|
#stub mapping
|
|
def self.mapping(*args)
|
|
{}
|
|
end
|
|
def self.index_import(list)
|
|
end
|
|
def self.index_name(name)
|
|
end
|
|
end
|
|
|
|
def disable_auto_reindex!
|
|
@disable_auto_reindex = true
|
|
end
|
|
|
|
def enable_auto_reindex!
|
|
@disable_auto_reindex = false
|
|
end
|
|
|
|
def refresh_index
|
|
return if @disable_auto_reindex
|
|
self.class.index.refresh if self.class.respond_to?(:index)
|
|
end
|
|
|
|
##
|
|
# :json - normal to_json options, :only or :except allowed
|
|
# :extended_json - function to call to return a hash to merge into document
|
|
# :display_attrs - list of attributes to display as searchable
|
|
##
|
|
def self.index_options(options = {})
|
|
self.class_index_options = options
|
|
end
|
|
|
|
# If this object (e.g. host_collection) is updated or deleted and another model (e.g. system) has an
|
|
# association (e.g. has_many) to it, we need to update the related indexes on that model (e.g system)
|
|
# relation - the association for the other model
|
|
# attribute - the attribute on the current model, which if changes needs to trigger the index update
|
|
def self.update_related_indexes(relation, attribute)
|
|
after_save lambda{|record| reindex_on_update(relation, attribute)}
|
|
before_destroy lambda{|record| save_indexed_relation(relation)}
|
|
after_destroy lambda{|record| reindex_relation}
|
|
end
|
|
|
|
# If this model (e.g. host_collection) has an association (e.g. has_many) to another model (e.g. system)
|
|
# and objects (e.g. systems) are added or removed for that association, we need to update the related
|
|
# indexes on that model.
|
|
def self.update_association_indexes
|
|
{ :after_add => :reindex_on_association_change, :after_remove => :reindex_on_association_change }
|
|
end
|
|
|
|
def reindex_on_association_change(record)
|
|
record.update_index if record.respond_to? :update_index
|
|
record.class.index.refresh if record.class.respond_to? :index
|
|
end
|
|
|
|
def reindex_on_update(relation, attribute)
|
|
return if @disable_auto_reindex
|
|
# If the specified attribute (e.g. name) on the current model has changed, update the related indexes
|
|
if self.send("#{attribute}_changed?")
|
|
related_objects = self.send(relation)
|
|
update_related_objects related_objects
|
|
end
|
|
end
|
|
|
|
def save_indexed_relation(relation)
|
|
# If an object (e.g. host_collection) is being deleted and another object (e.g. system) has a model
|
|
# relationship (e.g. has_many :through) with it, we need to update the indexes on that other model.
|
|
# Unfortunately, in order to do that, the update needs to be performed after this object is destroyed
|
|
# (i.e. after_destroy); however, at that point, the object (e.g. host_collection) no longer references
|
|
# the other (e.g. system).
|
|
#
|
|
# Temporarily save a list of the related objects that need indexes updated, for use in the 'after_destroy'.
|
|
@related_objects = self.send(relation)
|
|
end
|
|
|
|
def reindex_relation
|
|
update_related_objects @related_objects
|
|
end
|
|
|
|
def update_related_objects(objects)
|
|
unless objects.blank?
|
|
objects.each do |object|
|
|
object.update_index if object.respond_to? :update_index
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.use_index_of(model)
|
|
if Rails.env.development? || Rails.env.production?
|
|
index_name model.index_name
|
|
document_type model.document_type
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
#mocked methods for testing
|
|
unless Rails.env.development? || Rails.env.production?
|
|
def update_index
|
|
end
|
|
end
|
|
|
|
def indexed_attributes
|
|
attrs = self.attributes.keys.collect{|key| key.to_sym}
|
|
attrs += self.lazy_attributes if self.respond_to?(:lazy_attributes)
|
|
if self.class.class_index_options[:json]
|
|
options = self.class.class_index_options[:json]
|
|
if options[:only]
|
|
attrs = options[:only]
|
|
elsif options[:except]
|
|
attrs -= options[:except]
|
|
end
|
|
end
|
|
attrs
|
|
end
|
|
|
|
def to_indexed_json
|
|
return {} if @disable_auto_reindex
|
|
to_ret = {}
|
|
|
|
attrs = self.indexed_attributes
|
|
|
|
(attrs).each do |attr|
|
|
to_ret[attr] = self.send(attr)
|
|
end
|
|
|
|
if self.class.class_index_options[:extended_json]
|
|
to_ret.merge!(self.send(self.class.class_index_options[:extended_json]))
|
|
end
|
|
|
|
to_ret.to_json
|
|
end
|
|
|
|
end
|
|
end
|