Class: Chewy::Index::Adapter::Object

Inherits:
Base
  • Object
show all
Defined in:
lib/chewy/index/adapter/object.rb

Overview

This adapter provides an ability to import documents from any source. You can actually use any class or even a symbol as a target.

In case if a class is used - some of the additional features are available: it is possible to provide the default import data (used on reset) and source objects loading logic.

See Also:

Constant Summary

Constants inherited from Base

Base::BATCH_SIZE

Instance Attribute Summary

Attributes inherited from Base

#options, #target

Instance Method Summary collapse

Methods inherited from Base

accepts?, #type_name

Constructor Details

#initialize(target, **options) ⇒ Object

The signature of the index scope definition.

Examples:

index_scope :geoname
index_scope Geoname
index_scope -> { Geoname.all_the_places }, name: 'geoname'

Parameters:

  • target (Class, Symbol, String, Proc)

    a source of data and everything

  • options (Hash)

    a customizable set of options

Options Hash (**options):

  • :name (String, Symbol)

    redefines the inferred name if necessary

  • :import_all_method (String, Symbol)

    redefines import method name

  • :load_all_method (String, Symbol)

    redefines batch load method name

  • :load_one_method (String, Symbol)

    redefines per-object load method name



29
30
31
32
# File 'lib/chewy/index/adapter/object.rb', line 29

def initialize(target, **options)
  @target = target
  @options = options
end

Instance Method Details

#identify(collection) ⇒ Array<Object>

While for ORM adapters it returns an array of ids for the passed collection, for the object adapter it returns the collection itself.

Parameters:

  • collection (Array<Object>, Object)

    a collection or an object

Returns:



52
53
54
# File 'lib/chewy/index/adapter/object.rb', line 52

def identify(collection)
  Array.wrap(collection)
end

#import(*args, &block) ⇒ true, false

This method is used internally by ‘Chewy::Index.import`.

The idea is that any object can be imported to ES if it responds to ‘#to_json` method.

If method ‘destroyed?` is defined for object (or, in case of hash object, it has `:_destroyed` or `’_destroyed’‘ key) and returns `true` or object satisfy `delete_if` option then object will be deleted from index. But in order to be destroyable, objects need to respond to `id` method or have an `id` key so ElasticSearch could know which one to delete.

If nothing is passed the method tries to call ‘import_all_method`, which is `call` by default, on target to get the default objects batch.

Examples:

class Geoname
  self < class
    def self.call
      FancyGeoAPI.all_points_collection
    end
    alias_method :import_all, :call
  end
end

# All the following variants will work:
index_scope Geoname
index_scope Geoname, import_all_method: 'import_all'
index_scope -> { FancyGeoAPI.all_points_collection }, name: 'geoname'

Parameters:

  • args (Array<#to_json>)
  • options (Hash)

    a customizable set of options

Returns:

  • (true, false)


88
89
90
91
# File 'lib/chewy/index/adapter/object.rb', line 88

def import(*args, &block)
  collection, options = import_args(*args)
  import_objects(collection, options, &block)
end

#import_fields(*args, &block) ⇒ Object

For the object adapter this method tries to fetch :id and requested fields from the passed collection or the target’s ‘import_all_method` when defined. Otherwise it tries to call the target `pluck_method`, which is configurable and `pluck` by default. The `pluck_method` have to act exactly the same way as the AR one. It returns an empty array when none of the methods are found.

Examples:

class Geoname
  self < class
    def self.pluck(*fields)
      if fields.one?
        whatever_source.map { |object| object.send(fields.first) }
      else
        whatever_source.map do |object|
          fields.map { |field| object.send(field) }
        end
      end
    end
  end
end

See Also:



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/chewy/index/adapter/object.rb', line 116

def import_fields(*args, &block)
  return enum_for(:import_fields, *args) unless block_given?

  options = args.extract_options!
  options[:batch_size] ||= BATCH_SIZE

  if args.empty? && @target.respond_to?(pluck_method)
    @target.send(pluck_method, :id, *options[:fields]).each_slice(options[:batch_size], &block)
  elsif options[:fields].blank?
    import_references(*args, options) do |batch|
      yield batch.map { |object| object_field(object, :id) || object }
    end
  else
    import_references(*args, options) do |batch|
      batch = batch.map do |object|
        options[:fields].map { |field| object_field(object, field) }
          .unshift(object_field(object, :id) || object)
      end
      yield batch
    end
  end
end

#import_references(*args, &block) ⇒ Object

For the Object adapter returns the objects themselves in batches.



142
143
144
145
146
147
# File 'lib/chewy/index/adapter/object.rb', line 142

def import_references(*args, &block)
  return enum_for(:import_references, *args) unless block_given?

  collection, options = import_args(*args)
  collection.each_slice(options[:batch_size], &block)
end

#load(ids, **options) ⇒ Array<Object>?

This method is used internally by the request DSL when the collection of ORM/ODM objects is requested.

Options usage is implemented by ‘load_all_method` and `load_one_method`.

If none of the ‘load_all_method` or `load_one_method` is implemented for the target - the method will return nil. This means that the loader will return an array `Chewy::Index` objects that actually was passed.

To use loading for objects it is obviously required to provide some meaningful ids for ES documents.

Examples:

class Geoname
  def self.load_all(wrappers, options)
    if options[:additional_data]
      wrappers.map do |wrapper|
        FancyGeoAPI.point_by_name(wrapper.name)
      end
    else
      wrappers
    end
  end
end

MyIndex.load(additional_data: true).objects

Parameters:

  • ids (Array<Hash>)

    an array of ids from ES hits

  • options (Hash)

    any options passed here with the request DSL ‘load` method.

Returns:



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/chewy/index/adapter/object.rb', line 179

def load(ids, **options)
  if target.respond_to?(load_all_method)
    if target.method(load_all_method).arity == 1
      target.send(load_all_method, ids)
    else
      target.send(load_all_method, ids, options)
    end
  elsif target.respond_to?(load_one_method)
    if target.method(load_one_method).arity == 1
      ids.map { |hit| target.send(load_one_method, hit) }
    else
      ids.map { |hit| target.send(load_one_method, hit, options) }
    end
  end
end

#nameString

Inferred from the target by default if possible.

Examples:

# defines name = Geoname
index_scope :geoname
# still defines name = Geoname
index_scope -> { Geoname.all_the_places }, name: 'geoname'

Returns:

  • (String)


43
44
45
# File 'lib/chewy/index/adapter/object.rb', line 43

def name
  @name ||= (options[:name] || @target).to_s.camelize.demodulize
end