module Elasticsearch::Model::Proxy

This module provides a proxy interfacing between the including class and `Elasticsearch::Model`, preventing the pollution of the including class namespace.

The only “gateway” between the model and Elasticsearch::Model is the `#__elasticsearch__` class and instance method.

The including class must be compatible with [ActiveModel](github.com/rails/rails/tree/master/activemodel).

@example Include the `Elasticsearch::Model` module into an `Article` model

class Article < ActiveRecord::Base
  include Elasticsearch::Model
end

Article.__elasticsearch__.respond_to?(:search)
# => true

article = Article.first

article.respond_to? :index_document
# => false

article.__elasticsearch__.respond_to?(:index_document)
# => true

Public Class Methods

__elasticsearch__(&block) click to toggle source

`ClassMethodsProxy` instance, accessed as `MyModel.__elasticsearch__`

# File lib/elasticsearch/model/proxy.rb, line 60
def self.__elasticsearch__ &block
  @__elasticsearch__ ||= ClassMethodsProxy.new(self)
  @__elasticsearch__.instance_eval(&block) if block_given?
  @__elasticsearch__
end
included(base) click to toggle source

Define the `__elasticsearch__` class and instance methods in the including class and register a callback for intercepting changes in the model.

@note The callback is triggered only when `Elasticsearch::Model` is included in the

module and the functionality is accessible via the proxy.
# File lib/elasticsearch/model/proxy.rb, line 55
def self.included(base)

  base.class_eval do

    # `ClassMethodsProxy` instance, accessed as `MyModel.__elasticsearch__`
    def self.__elasticsearch__ &block
      @__elasticsearch__ ||= ClassMethodsProxy.new(self)
      @__elasticsearch__.instance_eval(&block) if block_given?
      @__elasticsearch__
    end

    # Mix the importing module into the `ClassMethodsProxy`
    self.__elasticsearch__.class_eval do
      include Adapter.from_class(base).importing_mixin
    end

    # Register a callback for storing changed attributes for models which implement
    # `before_save` method and return changed attributes (ie. when `Elasticsearch::Model` is included)
    #
    # @see http://api.rubyonrails.org/classes/ActiveModel/Dirty.html
    #
    before_save do |obj|
      if obj.respond_to?(:changes_to_save) # Rails 5.1
        changes_to_save = obj.changes_to_save
      elsif obj.respond_to?(:changes)
        changes_to_save = obj.changes
      end

      if changes_to_save
        attrs = obj.__elasticsearch__.instance_variable_get(:@__changed_model_attributes) || {}
        latest_changes = changes_to_save.inject({}) { |latest_changes, (k,v)| latest_changes.merge!(k => v.last) }
        obj.__elasticsearch__.instance_variable_set(:@__changed_model_attributes, attrs.merge(latest_changes))
      end
    end if respond_to?(:before_save)
  end

  # {InstanceMethodsProxy}, accessed as `@mymodel.__elasticsearch__`
  #
  def __elasticsearch__ &block
    @__elasticsearch__ ||= InstanceMethodsProxy.new(self)
    @__elasticsearch__.instance_eval(&block) if block_given?
    @__elasticsearch__
  end
end

Public Instance Methods

__elasticsearch__(&block) click to toggle source

{InstanceMethodsProxy}, accessed as `@mymodel.__elasticsearch__`

# File lib/elasticsearch/model/proxy.rb, line 93
def __elasticsearch__ &block
  @__elasticsearch__ ||= InstanceMethodsProxy.new(self)
  @__elasticsearch__.instance_eval(&block) if block_given?
  @__elasticsearch__
end
initialize_dup(_) click to toggle source

@overload dup

Returns a copy of this object. Resets the __elasticsearch__ proxy so the duplicate will build its own proxy.

Calls superclass method
# File lib/elasticsearch/model/proxy.rb, line 104
def initialize_dup(_)
  @__elasticsearch__ = nil
  super
end