diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 2b1cccd91..de4efe5b1 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -30,16 +30,16 @@ Lint/EmptyBlock: - 'spec/chewy/search/scrolling_spec.rb' - 'spec/chewy/strategy/atomic_spec.rb' - 'spec/chewy/strategy_spec.rb' - - 'spec/chewy/type/import/bulk_request_spec.rb' - - 'spec/chewy/type/witchcraft_spec.rb' + - 'spec/chewy/index/import/bulk_request_spec.rb' + - 'spec/chewy/index/witchcraft_spec.rb' - 'spec/chewy_spec.rb' # Offense count: 3 Lint/MissingSuper: Exclude: - 'lib/chewy/strategy/atomic.rb' - - 'lib/chewy/type/adapter/object.rb' - - 'lib/chewy/type/adapter/orm.rb' + - 'lib/chewy/index/adapter/object.rb' + - 'lib/chewy/index/adapter/orm.rb' # Offense count: 35 # Configuration parameters: IgnoredMethods, CountRepeatedAttributes. @@ -85,8 +85,8 @@ Style/DocumentDynamicEvalDefinition: - 'lib/chewy/index/actions.rb' - 'lib/chewy/repository.rb' - 'lib/chewy/search/pagination/kaminari.rb' - - 'lib/chewy/type/crutch.rb' - - 'lib/chewy/type/witchcraft.rb' + - 'lib/chewy/index/crutch.rb' + - 'lib/chewy/index/witchcraft.rb' # Offense count: 58 Style/Documentation: @@ -120,8 +120,8 @@ Style/IfUnlessModifier: - 'lib/chewy/railtie.rb' - 'lib/chewy/rspec/update_index.rb' - 'lib/chewy/search/query_proxy.rb' - - 'lib/chewy/type/import.rb' - - 'lib/chewy/type/witchcraft.rb' + - 'lib/chewy/index/import.rb' + - 'lib/chewy/index/witchcraft.rb' - 'spec/support/active_record.rb' # Offense count: 53 diff --git a/lib/chewy.rb b/lib/chewy.rb index 97fcc3bd9..8aeb123ab 100644 --- a/lib/chewy.rb +++ b/lib/chewy.rb @@ -44,88 +44,43 @@ def try_require(path) require 'chewy/log_subscriber' require 'chewy/strategy' require 'chewy/index' -require 'chewy/type' require 'chewy/fields/base' require 'chewy/fields/root' require 'chewy/journal' require 'chewy/railtie' if defined?(::Rails::Railtie) ActiveSupport.on_load(:active_record) do - extend Chewy::Type::Observe::ActiveRecordMethods + extend Chewy::Index::Observe::ActiveRecordMethods end module Chewy @adapters = [ - Chewy::Type::Adapter::ActiveRecord, - Chewy::Type::Adapter::Object + Chewy::Index::Adapter::ActiveRecord, + Chewy::Index::Adapter::Object ] class << self attr_accessor :adapters - # Derives a single type for the passed string identifier if possible. + # Derives an index for the passed string identifier if possible. # # @example - # Chewy.derive_types(UsersIndex::User) # => UsersIndex::User - # Chewy.derive_types('namespace/users') # => Namespace::UsersIndex::User - # Chewy.derive_types('places') # => raises Chewy::UnderivableType - # Chewy.derive_types('places#city') # => PlacesIndex::City + # Chewy.derive_name(UsersIndex) # => UsersIndex + # Chewy.derive_name('namespace/users') # => Namespace::UsersIndex + # Chewy.derive_name('missing') # => raises Chewy::UndefinedIndex # - # @param name [String, Chewy::Type] string type identifier - # @raise [Chewy::UnderivableType] in cases when it is impossble to find index or type or more than one type found - # @return [Chewy::Type] an array of derived types - def derive_type(name) - return name if name.is_a?(Class) && name < Chewy::Type - - types = derive_types(name) - unless types.one? - raise Chewy::UnderivableType, - "Index `#{types.first.index}` has more than one type, please specify type via `#{types.first.index.derivable_name}#type_name`" - end - - types.first - end - - # Derives all the types for the passed string identifier if possible. - # - # @example - # Chewy.derive_types('namespace/users') # => [Namespace::UsersIndex::User] - # Chewy.derive_types('places') # => [PlacesIndex::City, PlacesIndex::Country] - # Chewy.derive_types('places#city') # => [PlacesIndex::City] - # - # @param from [String] string type identifier - # @raise [Chewy::UnderivableType] in cases when it is impossible to find index or type - # @return [Array] an array of derived types - def derive_types(from) - return from.types if from.is_a?(Class) && (from < Chewy::Index || from < Chewy::Type) + # @param index_name [String, Chewy::Index] index identifier or class + # @raise [Chewy::UndefinedIndex] in cases when it is impossible to find index + # @return [Chewy::Index] + def derive_name(index_name) + return index_name if index_name.is_a?(Class) && index_name < Chewy::Index - index_name, type_name = from.split('#', 2) class_name = "#{index_name.camelize.gsub(/Index\z/, '')}Index" index = class_name.safe_constantize - raise Chewy::UnderivableType, "Can not find index named `#{class_name}`" unless index && index < Chewy::Index - - if type_name.present? - type = index.type_hash[type_name] or raise Chewy::UnderivableType, - "Index `#{class_name}` doesn`t have type named `#{type_name}`" - [type] - else - index.types - end - end - - # Creates Chewy::Type ancestor defining index and adapter methods. - # - def create_type(index, target, options = {}, &block) - type = Class.new(Chewy::Type) - - adapter = adapters.find { |klass| klass.accepts?(target) }.new(target, **options) - index.const_set(adapter.name, type) - type.send(:define_singleton_method, :index) { index } - type.send(:define_singleton_method, :adapter) { adapter } + return index if index && index < Chewy::Index - type.class_eval(&block) if block - type + raise Chewy::UndefinedIndex, "Can not find index named `#{class_name}`" end # Main elasticsearch-ruby client instance diff --git a/lib/chewy/index.rb b/lib/chewy/index.rb index 3a645db19..0b88eb766 100644 --- a/lib/chewy/index.rb +++ b/lib/chewy/index.rb @@ -1,23 +1,48 @@ require 'chewy/search' require 'chewy/index/actions' +require 'chewy/index/adapter/active_record' +require 'chewy/index/adapter/object' require 'chewy/index/aliases' +require 'chewy/index/crutch' +require 'chewy/index/import' +require 'chewy/index/mapping' +require 'chewy/index/observe' require 'chewy/index/settings' require 'chewy/index/specification' +require 'chewy/index/syncer' +require 'chewy/index/witchcraft' +require 'chewy/index/wrapper' module Chewy class Index + IMPORT_OPTIONS_KEYS = %i[ + batch_size bulk_size consistency direct_import journal + pipeline raw_import refresh replication + ].freeze + include Search include Actions include Aliases + include Import + include Mapping + include Observe + include Crutch + include Witchcraft + include Wrapper singleton_class.delegate :client, to: 'Chewy' - class_attribute :type_hash - self.type_hash = {} + class_attribute :adapter + self.adapter = Chewy::Index::Adapter::Object.new(:default) + + class_attribute :index_scope_defined class_attribute :_settings self._settings = Chewy::Index::Settings.new + class_attribute :_default_import_options + self._default_import_options = {} + class << self # @overload index_name(suggest) # If suggested name is passed, it is set up as the new base name for @@ -113,70 +138,67 @@ def prefix Chewy.configuration[:prefix] end - # Defines type for the index. Arguments depends on adapter used. For + # Defines scope and options for the index. Arguments depends on adapter used. For # ActiveRecord you can pass model or scope and options # # class CarsIndex < Chewy::Index - # define_type Car do - # ... - # end # defines VehiclesIndex::Car type + # index_scope Car + # ... # end # # Type name might be passed in complicated cases: # - # class VehiclesIndex < Chewy::Index - # define_type Vehicle.cars.includes(:manufacturer), name: 'cars' do - # ... - # end # defines VehiclesIndex::Cars type + # class CarsIndex < Chewy::Index + # index_scope Vehicle.cars.includes(:manufacturer), name: 'cars' + # ... + # end # - # define_type Vehicle.motocycles.includes(:manufacturer), name: 'motocycles' do - # ... - # end # defines VehiclesIndex::Motocycles type + # class MotorcyclesIndex < Chewy::Index + # index_scope Vehicle.motorcycles.includes(:manufacturer), name: 'motorcycles' + # ... # end # - # For plain objects: + # For plain objects you can completely omit this directive, unless you need to specify some options: # # class PlanesIndex < Chewy::Index - # define_type :plane do - # ... - # end # defines PlanesIndex::Plane type + # ... # end # # The main difference between using plain objects or ActiveRecord models for indexing - # is import. If you will call `CarsIndex::Car.import` - it will import all the cars - # automatically, while `PlanesIndex::Plane.import(my_planes)` requires import data to be + # is import. If you will call `CarsIndex.import` - it will import all the cars + # automatically, while `PlanesIndex.import(my_planes)` requires import data to be # passed. # - def define_type(target, options = {}, &block) - raise 'Multiple types are deprecated' if type_hash.present? + def index_scope(target, options = {}) + raise 'Index scope is already defined' if index_scope_defined? - type_class = Chewy.create_type(self, target, options, &block) - self.type_hash = type_hash.merge(type_class.type_name => type_class) + self.adapter = Chewy.adapters.find { |klass| klass.accepts?(target) }.new(target, **options) + self.index_scope_defined = true end # Returns defined type: # # UsersIndex.types # => [UsersIndex::User] # - def types - type_hash.values - end + # def types + # type_hash.values + # end # Returns defined types names: # # UsersIndex.type_names # => ['admin', 'manager', 'user'] # - def type_names - type_hash.keys - end + # def type_names + # type_hash.keys + # end # Returns named type: # # UserIndex.type('admin') # => UsersIndex::Admin # - def type(type_name) - type_hash.fetch(type_name) { raise UndefinedType, "Unknown type in #{name}: #{type_name}" } - end + # def type(type_name) + # type_hash.fetch(type_name) { raise UndefinedType, "Unknown type in #{name}: #{type_name}" } + # end # Used as a part of index definition DSL. Defines settings: # @@ -212,7 +234,7 @@ def settings_hash end def mappings_hash - mappings = types.map(&:mappings_hash).inject(:merge) + mappings = root.mappings_hash mappings.present? ? {mappings: mappings} : {} end @@ -230,6 +252,11 @@ def specification_hash def specification @specification ||= Specification.new(self) end + + def default_import_options(params) + params.assert_valid_keys(IMPORT_OPTIONS_KEYS) + self._default_import_options = _default_import_options.merge(params) + end end end end diff --git a/lib/chewy/index/actions.rb b/lib/chewy/index/actions.rb index a7bcc517c..c1f434d77 100644 --- a/lib/chewy/index/actions.rb +++ b/lib/chewy/index/actions.rb @@ -129,37 +129,6 @@ def purge!(suffix = nil) create! suffix end - # Perform import operation for every defined type - # - # UsersIndex.import # imports default data for every index type - # UsersIndex.import user: User.active # imports specified objects for user type and default data for other types - # UsersIndex.import refresh: false # to disable index refreshing after import - # UsersIndex.import suffix: Time.now.to_i # imports data to index with specified suffix if such is exists - # UsersIndex.import batch_size: 300 # import batch size - # - # See [import.rb](lib/chewy/type/import.rb) for more details. - # - %i[import import!].each do |method| - class_eval <<-METHOD, __FILE__, __LINE__ + 1 - def #{method}(*args) - return true if args.first.blank? && !args.first.nil? - - options = args.extract_options! - if args.one? && type_names.one? - objects = {type_names.first.to_sym => args.first} - elsif args.one? - fail ArgumentError, "Please pass objects for `#{method}` as a hash with type names" - else - objects = options.reject { |k, v| !type_names.map(&:to_sym).include?(k) } - end - types.map do |type| - args = [objects[type.type_name.to_sym], options.dup].reject(&:blank?) - type.#{method} *args - end.all? - end - METHOD - end - # Deletes, creates and imports data to the index. Returns the # import result. If index name suffix is passed as the first # argument - performs zero-downtime index resetting. @@ -213,6 +182,7 @@ def reset!(suffix = nil, apply_journal: true, journal: false, **import_options) specification.lock! result end + alias_method :reset, :reset! # A {Chewy::Journal} instance for the particular index # @@ -243,13 +213,28 @@ def reindex(source: index_name, dest: index_name) # @example # Chewy.client.update_mapping('cities', {properties: {new_field: {type: :text}}}) # - def update_mapping(name = index_name, body = mappings_hash) + def update_mapping(name = index_name, body = root.mappings_hash) client.indices.put_mapping( index: name, body: body )['acknowledged'] end + # Performs missing and outdated objects synchronization for the current index. + # + # @example + # UsersIndex.sync + # + # @see Chewy::Index::Syncer + # @param parallel [true, Integer, Hash] options for parallel execution or the number of processes + # @return [Hash{Symbol, Object}, nil] a number of missing and outdated documents re-indexed and their ids, + # nil in case of errors + def sync(parallel: nil) + syncer = Syncer.new(self, parallel: parallel) + count = syncer.perform + {count: count, missing: syncer.missing_ids, outdated: syncer.outdated_ids} if count + end + private def optimize_index_settings(index_name) diff --git a/lib/chewy/type/adapter/active_record.rb b/lib/chewy/index/adapter/active_record.rb similarity index 98% rename from lib/chewy/type/adapter/active_record.rb rename to lib/chewy/index/adapter/active_record.rb index 371eeb05b..7526e2f4a 100644 --- a/lib/chewy/type/adapter/active_record.rb +++ b/lib/chewy/index/adapter/active_record.rb @@ -1,7 +1,7 @@ -require 'chewy/type/adapter/orm' +require 'chewy/index/adapter/orm' module Chewy - class Type + class Index module Adapter class ActiveRecord < Orm def self.accepts?(target) diff --git a/lib/chewy/type/adapter/base.rb b/lib/chewy/index/adapter/base.rb similarity index 99% rename from lib/chewy/type/adapter/base.rb rename to lib/chewy/index/adapter/base.rb index 5076a3f44..c6171ab01 100644 --- a/lib/chewy/type/adapter/base.rb +++ b/lib/chewy/index/adapter/base.rb @@ -1,5 +1,5 @@ module Chewy - class Type + class Index module Adapter # Basic adapter class. Contains interface, need to implement to add any classes support class Base diff --git a/lib/chewy/type/adapter/object.rb b/lib/chewy/index/adapter/object.rb similarity index 99% rename from lib/chewy/type/adapter/object.rb rename to lib/chewy/index/adapter/object.rb index 3ea167656..6de856bd5 100644 --- a/lib/chewy/type/adapter/object.rb +++ b/lib/chewy/index/adapter/object.rb @@ -1,7 +1,7 @@ -require 'chewy/type/adapter/base' +require 'chewy/index/adapter/base' module Chewy - class Type + class Index module Adapter # This adapter provides an ability to import documents from any # source. You can actually use any class or even a symbol as diff --git a/lib/chewy/type/adapter/orm.rb b/lib/chewy/index/adapter/orm.rb similarity index 97% rename from lib/chewy/type/adapter/orm.rb rename to lib/chewy/index/adapter/orm.rb index d516b4b15..e2f2767a2 100644 --- a/lib/chewy/type/adapter/orm.rb +++ b/lib/chewy/index/adapter/orm.rb @@ -1,7 +1,7 @@ -require 'chewy/type/adapter/base' +require 'chewy/index/adapter/base' module Chewy - class Type + class Index module Adapter class Orm < Base attr_reader :default_scope @@ -99,7 +99,7 @@ def import_fields(*args, &block) def load(ids, **options) scope = all_scope_where_ids_in(ids) - additional_scope = options[options[:_type].type_name.to_sym].try(:[], :scope) || options[:scope] + additional_scope = options[options[:_index].to_sym].try(:[], :scope) || options[:scope] loaded_objects = load_scope_objects(scope, additional_scope) .index_by do |object| diff --git a/lib/chewy/type/crutch.rb b/lib/chewy/index/crutch.rb similarity index 73% rename from lib/chewy/type/crutch.rb rename to lib/chewy/index/crutch.rb index 833a43372..a36fc4ef8 100644 --- a/lib/chewy/type/crutch.rb +++ b/lib/chewy/index/crutch.rb @@ -1,5 +1,5 @@ module Chewy - class Type + class Index module Crutch extend ActiveSupport::Concern @@ -9,13 +9,13 @@ module Crutch end class Crutches - def initialize(type, collection) - @type = type + def initialize(index, collection) + @index = index @collection = collection - @type._crutches.each_key do |name| + @index._crutches.each_key do |name| singleton_class.class_eval <<-METHOD, __FILE__, __LINE__ + 1 def #{name} - @#{name} ||= @type._crutches[:#{name}].call @collection + @#{name} ||= @index._crutches[:#{name}].call @collection end METHOD end diff --git a/lib/chewy/type/import.rb b/lib/chewy/index/import.rb similarity index 87% rename from lib/chewy/type/import.rb rename to lib/chewy/index/import.rb index 3dcc8be3c..d31d88341 100644 --- a/lib/chewy/type/import.rb +++ b/lib/chewy/index/import.rb @@ -1,38 +1,38 @@ -require 'chewy/type/import/journal_builder' -require 'chewy/type/import/bulk_builder' -require 'chewy/type/import/bulk_request' -require 'chewy/type/import/routine' +require 'chewy/index/import/journal_builder' +require 'chewy/index/import/bulk_builder' +require 'chewy/index/import/bulk_request' +require 'chewy/index/import/routine' module Chewy - class Type + class Index module Import extend ActiveSupport::Concern - IMPORT_WORKER = lambda do |type, options, total, ids, index| - ::Process.setproctitle("chewy [#{type}]: import data (#{index + 1}/#{total})") - routine = Routine.new(type, **options) - type.adapter.import(*ids, routine.options) do |action_objects| + IMPORT_WORKER = lambda do |index, options, total, ids, iteration| + ::Process.setproctitle("chewy [#{index}]: import data (#{iteration + 1}/#{total})") + routine = Routine.new(index, **options) + index.adapter.import(*ids, routine.options) do |action_objects| routine.process(**action_objects) end {errors: routine.errors, import: routine.stats, leftovers: routine.leftovers} end - LEFTOVERS_WORKER = lambda do |type, options, total, body, index| - ::Process.setproctitle("chewy [#{type}]: import leftovers (#{index + 1}/#{total})") - routine = Routine.new(type, **options) + LEFTOVERS_WORKER = lambda do |index, options, total, body, iteration| + ::Process.setproctitle("chewy [#{index}]: import leftovers (#{iteration + 1}/#{total})") + routine = Routine.new(index, **options) routine.perform_bulk(body) routine.errors end module ClassMethods # @!method import(*collection, **options) - # Basically, one of the main methods for type. Performs any objects import - # to the index for a specified type. Does all the objects handling routines. + # Basically, one of the main methods for an index. Performs any objects import + # to the index. Does all the objects handling routines. # Performs document import by utilizing bulk API. Bulk size and objects batch # size are controlled by the corresponding options. # # It accepts ORM/ODM objects, PORO, hashes, ids which are used by adapter to - # fetch objects from the source depenting on the used adapter. It destroys + # fetch objects from the source depending on the used adapter. It destroys # passed objects from the index if they are not in the default type scope # or marked for destruction. # @@ -51,7 +51,7 @@ module ClassMethods # # Utilizes `ActiveSupport::Notifications`, so it is possible to get imported # objects later by listening to the `import_objects.chewy` queue. It is also - # possible to get the list of occured errors from the payload if something + # possible to get the list of occurred errors from the payload if something # went wrong. # # Import can also be run in parallel using the Parallel gem functionality. @@ -116,7 +116,7 @@ def bulk(**options) # @param fields [Array] and array of fields to restrict the generated document # @return [Hash] a JSON-ready hash def compose(object, crutches = nil, fields: []) - crutches ||= Chewy::Type::Crutch::Crutches.new self, [object] + crutches ||= Chewy::Index::Crutch::Crutches.new self, [object] if witchcraft? && root.children.present? cauldron(fields: fields).brew(object, crutches) @@ -149,7 +149,7 @@ def empty_objects_or_scope?(objects_or_scope) end def import_linear(objects, routine) - ActiveSupport::Notifications.instrument 'import_objects.chewy', type: self do |payload| + ActiveSupport::Notifications.instrument 'import_objects.chewy', index: self do |payload| adapter.import(*objects, routine.options) do |action_objects| routine.process(**action_objects) end @@ -161,11 +161,9 @@ def import_linear(objects, routine) end def import_parallel(objects, routine) - unless '::Parallel'.safe_constantize - raise "The `parallel` gem is required for parallel import, please add `gem 'parallel'` to your Gemfile" - end + raise "The `parallel` gem is required for parallel import, please add `gem 'parallel'` to your Gemfile" unless '::Parallel'.safe_constantize - ActiveSupport::Notifications.instrument 'import_objects.chewy', type: self do |payload| + ActiveSupport::Notifications.instrument 'import_objects.chewy', index: self do |payload| batches = adapter.import_references(*objects, routine.options.slice(:batch_size)).to_a ::ActiveRecord::Base.connection.close if defined?(::ActiveRecord::Base) diff --git a/lib/chewy/type/import/bulk_builder.rb b/lib/chewy/index/import/bulk_builder.rb similarity index 81% rename from lib/chewy/type/import/bulk_builder.rb rename to lib/chewy/index/import/bulk_builder.rb index 4f87c3e09..c139761c0 100644 --- a/lib/chewy/type/import/bulk_builder.rb +++ b/lib/chewy/index/import/bulk_builder.rb @@ -1,5 +1,5 @@ module Chewy - class Type + class Index module Import # This class purpose is to build ES client-acceptable bulk # request body from the passed objects for index and deletion. @@ -9,13 +9,13 @@ module Import # If fields are passed - it creates partial update entries except for # the cases when the type has parent and parent_id has been changed. class BulkBuilder - # @param type [Chewy::Type] desired type - # @param index [Array] objects to index + # @param index [Chewy::Index] desired index + # @param to_index [Array] objects to index # @param delete [Array] objects or ids to delete # @param fields [Array] and array of fields for documents update - def initialize(type, index: [], delete: [], fields: []) - @type = type + def initialize(index, to_index: [], delete: [], fields: []) @index = index + @to_index = to_index @delete = delete @fields = fields.map!(&:to_sym) end @@ -24,7 +24,7 @@ def initialize(type, index: [], delete: [], fields: []) # @see https://github.com/elastic/elasticsearch-ruby/blob/master/elasticsearch-api/lib/elasticsearch/api/actions/bulk.rb # @return [Array] bulk body def bulk_body - @bulk_body ||= @index.flat_map(&method(:index_entry)).concat( + @bulk_body ||= @to_index.flat_map(&method(:index_entry)).concat( @delete.flat_map(&method(:delete_entry)) ) end @@ -40,7 +40,7 @@ def index_objects_by_id private def crutches - @crutches ||= Chewy::Type::Crutch::Crutches.new @type, @index + @crutches ||= Chewy::Index::Crutch::Crutches.new @index, @to_index end def parents @@ -53,7 +53,7 @@ def parents ids.concat(@delete.map do |object| object.respond_to?(:id) ? object.id : object end) - @type.filter(ids: {values: ids}).order('_doc').pluck(:_id, :_parent).to_h + @index.filter(ids: {values: ids}).order('_doc').pluck(:_id, :_parent).to_h end end @@ -67,15 +67,15 @@ def index_entry(object) end if parent && entry[:parent].to_s != parent - entry[:data] = @type.compose(object, crutches) + entry[:data] = @index.compose(object, crutches) [{delete: entry.except(:data).merge(parent: parent)}, {index: entry}] elsif @fields.present? return [] unless entry[:_id] - entry[:data] = {doc: @type.compose(object, crutches, fields: @fields)} + entry[:data] = {doc: @index.compose(object, crutches, fields: @fields)} [{update: entry}] else - entry[:data] = @type.compose(object, crutches) + entry[:data] = @index.compose(object, crutches) [{index: entry}] end end @@ -109,14 +109,14 @@ def entry_id(object) end def index_object_ids - @index_object_ids ||= @index.each_with_object({}) do |object, result| + @index_object_ids ||= @to_index.each_with_object({}) do |object, result| id = entry_id(object) result[object] = id if id.present? end end def type_root - @type_root ||= @type.root + @type_root ||= @index.root end end end diff --git a/lib/chewy/type/import/bulk_request.rb b/lib/chewy/index/import/bulk_request.rb similarity index 88% rename from lib/chewy/type/import/bulk_request.rb rename to lib/chewy/index/import/bulk_request.rb index fb94e4aa5..9cae80ddd 100644 --- a/lib/chewy/type/import/bulk_request.rb +++ b/lib/chewy/index/import/bulk_request.rb @@ -1,5 +1,5 @@ module Chewy - class Type + class Index module Import # Adds additional features to elasticsearch-api bulk method: # * supports Chewy index suffix if necessary; @@ -10,12 +10,12 @@ module Import # # @see https://github.com/elastic/elasticsearch-ruby/blob/master/elasticsearch-api/lib/elasticsearch/api/actions/bulk.rb class BulkRequest - # @param type [Chewy::Type] a type for the request + # @param index [Chewy::Index] an index for the request # @param suffix [String] an index name optional suffix # @param bulk_size [Integer] bulk size in bytes # @param bulk_options [Hash] options passed to the elasticsearch-api bulk method - def initialize(type, suffix: nil, bulk_size: nil, **bulk_options) - @type = type + def initialize(index, suffix: nil, bulk_size: nil, **bulk_options) + @index = index @suffix = suffix @bulk_size = bulk_size - 1.kilobyte if bulk_size # 1 kilobyte for request header and newlines @bulk_options = bulk_options @@ -33,7 +33,7 @@ def perform(body) return [] if body.blank? request_bodies(body).each_with_object([]) do |request_body, results| - response = @type.client.bulk request_base.merge(body: request_body) if request_body.present? + response = @index.client.bulk request_base.merge(body: request_body) if request_body.present? next unless response.try(:[], 'errors') @@ -47,7 +47,7 @@ def perform(body) def request_base @request_base ||= { - index: @type.index_name(suffix: @suffix) + index: @index.index_name(suffix: @suffix) }.merge!(@bulk_options) end diff --git a/lib/chewy/type/import/journal_builder.rb b/lib/chewy/index/import/journal_builder.rb similarity index 67% rename from lib/chewy/type/import/journal_builder.rb rename to lib/chewy/index/import/journal_builder.rb index cd88b21b8..9d7fccce0 100644 --- a/lib/chewy/type/import/journal_builder.rb +++ b/lib/chewy/index/import/journal_builder.rb @@ -1,18 +1,18 @@ module Chewy - class Type + class Index module Import class JournalBuilder - def initialize(type, index: [], delete: []) - @type = type + def initialize(index, to_index: [], delete: []) @index = index + @to_index = to_index @delete = delete end def bulk_body - Chewy::Type::Import::BulkBuilder.new( - Chewy::Stash::Journal::Journal, - index: [ - entries(:index, @index), + Chewy::Index::Import::BulkBuilder.new( + Chewy::Stash::Journal, + to_index: [ + entries(:index, @to_index), entries(:delete, @delete) ].compact ).bulk_body.each do |item| @@ -28,8 +28,7 @@ def entries(action, objects) return unless objects.present? { - index_name: @type.index.derivable_name, - type_name: @type.type_name, + index_name: @index.derivable_name, action: action, references: identify(objects).map { |item| Base64.encode64(::Elasticsearch::API.serializer.dump(item)) }, created_at: Time.now.utc @@ -37,7 +36,7 @@ def entries(action, objects) end def identify(objects) - @type.adapter.identify(objects) + @index.adapter.identify(objects) end end end diff --git a/lib/chewy/type/import/routine.rb b/lib/chewy/index/import/routine.rb similarity index 84% rename from lib/chewy/type/import/routine.rb rename to lib/chewy/index/import/routine.rb index bcc71c134..556510572 100644 --- a/lib/chewy/type/import/routine.rb +++ b/lib/chewy/index/import/routine.rb @@ -1,5 +1,5 @@ module Chewy - class Type + class Index module Import # This class performs the import routine for the options and objects given. # @@ -20,7 +20,7 @@ module Import # when the document doesn't exist only if `update_failover` option is true. In order to # restore, it indexes such an objects completely on the next iteration. # - # @see Chewy::Type::Import::ClassMethods#import + # @see Chewy::Index::Import::ClassMethods#import class Routine BULK_OPTIONS = %i[ suffix bulk_size @@ -33,18 +33,18 @@ class Routine refresh: true, update_fields: [], update_failover: true, - batch_size: Chewy::Type::Adapter::Base::BATCH_SIZE + batch_size: Chewy::Index::Adapter::Base::BATCH_SIZE }.freeze attr_reader :options, :parallel_options, :errors, :stats, :leftovers # Basically, processes passed options, extracting bulk request specific options. - # @param type [Chewy::Type] chewy type - # @param options [Hash] import options, see {Chewy::Type::Import::ClassMethods#import} - def initialize(type, **options) - @type = type + # @param index [Chewy::Index] chewy index + # @param options [Hash] import options, see {Chewy::Index::Import::ClassMethods#import} + def initialize(index, **options) + @index = index @options = options - @options.reverse_merge!(@type._default_import_options) + @options.reverse_merge!(@index._default_import_options) @options.reverse_merge!(journal: Chewy.configuration[:journal]) @options.reverse_merge!(DEFAULT_OPTIONS) @bulk_options = @options.slice(*BULK_OPTIONS) @@ -61,13 +61,13 @@ def initialize(type, **options) @leftovers = [] end - # Creates the journal index and the type corresponding index if necessary. + # Creates the journal index and the corresponding index if necessary. # @return [Object] whatever def create_indexes! Chewy::Stash::Journal.create if @options[:journal] return if Chewy.configuration[:skip_index_creation_on_import] - @type.index.create!(**@bulk_options.slice(:suffix)) unless @type.index.exists? + @index.create!(**@bulk_options.slice(:suffix)) unless @index.exists? end # The main process method. Converts passed objects to the bulk request body, @@ -78,11 +78,11 @@ def create_indexes! # @param delete [Array] any acceptable objects for deleting # @return [true, false] the result of the request, true if no errors def process(index: [], delete: []) - bulk_builder = BulkBuilder.new(@type, index: index, delete: delete, fields: @options[:update_fields]) + bulk_builder = BulkBuilder.new(@index, to_index: index, delete: delete, fields: @options[:update_fields]) bulk_body = bulk_builder.bulk_body if @options[:journal] - journal_builder = JournalBuilder.new(@type, index: index, delete: delete) + journal_builder = JournalBuilder.new(@index, to_index: index, delete: delete) bulk_body.concat(journal_builder.bulk_body) end @@ -127,11 +127,11 @@ def extract_leftovers(errors, index_objects_by_id) errors_to_cleanup.each { |error| errors.delete(error) } failed_objects = index_objects_by_id.values_at(*failed_ids_for_reimport) - BulkBuilder.new(@type, index: failed_objects).bulk_body + BulkBuilder.new(@index, to_index: failed_objects).bulk_body end def bulk - @bulk ||= BulkRequest.new(@type, **@bulk_options) + @bulk ||= BulkRequest.new(@index, **@bulk_options) end end end diff --git a/lib/chewy/type/mapping.rb b/lib/chewy/index/mapping.rb similarity index 98% rename from lib/chewy/type/mapping.rb rename to lib/chewy/index/mapping.rb index 5efd5ffec..e8f717696 100644 --- a/lib/chewy/type/mapping.rb +++ b/lib/chewy/index/mapping.rb @@ -1,5 +1,5 @@ module Chewy - class Type + class Index module Mapping extend ActiveSupport::Concern @@ -35,7 +35,7 @@ module ClassMethods # end # def root(**options) - self.root_object ||= Chewy::Fields::Root.new(type_name, **Chewy.default_root_options.merge(options)) + self.root_object ||= Chewy::Fields::Root.new(:root, **Chewy.default_root_options.merge(options)) root_object.update_options!(**options) yield if block_given? root_object diff --git a/lib/chewy/type/observe.rb b/lib/chewy/index/observe.rb similarity index 81% rename from lib/chewy/type/observe.rb rename to lib/chewy/index/observe.rb index 347fe11c3..bdc4c8d1d 100644 --- a/lib/chewy/type/observe.rb +++ b/lib/chewy/index/observe.rb @@ -1,25 +1,25 @@ module Chewy - class Type + class Index module Observe extend ActiveSupport::Concern module Helpers - def update_proc(type_name, *args, &block) + def update_proc(index_name, *args, &block) options = args.extract_options! method = args.first proc do - reference = if type_name.is_a?(Proc) - if type_name.arity.zero? - instance_exec(&type_name) + reference = if index_name.is_a?(Proc) + if index_name.arity.zero? + instance_exec(&index_name) else - type_name.call(self) + index_name.call(self) end else - type_name + index_name end - type = Chewy.derive_type(reference) + index = Chewy.derive_name(reference) next if Chewy.strategy.current.name == :bypass @@ -31,7 +31,7 @@ def update_proc(type_name, *args, &block) instance_eval(&block) end - type.update_index(backreference, options) + index.update_index(backreference, options) end end diff --git a/lib/chewy/type/syncer.rb b/lib/chewy/index/syncer.rb similarity index 94% rename from lib/chewy/type/syncer.rb rename to lib/chewy/index/syncer.rb index 7ffc2ec39..ef3ae1a42 100644 --- a/lib/chewy/type/syncer.rb +++ b/lib/chewy/index/syncer.rb @@ -1,5 +1,5 @@ module Chewy - class Type + class Index # This class is able to find missing and outdated documents in the ES # comparing ids from the data source and the ES index. Also, if `outdated_sync_field` # exists in the index definition, it performs comparison of this field @@ -24,7 +24,7 @@ class Type # ATTENTION: synchronization may be slow in case when synchronized tables # are missing compound index on primary key and `outdated_sync_field`. # - # @see Chewy::Type::Actions::ClassMethods#sync + # @see Chewy::Index::Actions::ClassMethods#sync class Syncer DEFAULT_SYNC_BATCH_SIZE = 20_000 ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/.freeze @@ -34,7 +34,7 @@ class Syncer next unless source_data_hash[id] outdated = if outdated_sync_field_type == 'date' - !Chewy::Type::Syncer.dates_equal(typecast_date(source_data_hash[id]), Time.iso8601(index_sync_value)) + !Chewy::Index::Syncer.dates_equal(typecast_date(source_data_hash[id]), Time.iso8601(index_sync_value)) else source_data_hash[id] != index_sync_value end @@ -71,14 +71,6 @@ def self.dates_equal(one, two) [one.to_i, one.usec / 1000] == [two.to_i, two.usec / 1000] end - # In ActiveSupport ~> 4.0 json dumpled times without any - # milliseconds, so ES stored time with the seconds precision. - if ActiveSupport::VERSION::STRING < '4.1.0' - def self.dates_equal(one, two) - one.to_i == two.to_i - end - end - # @param type [Chewy::Type] chewy type # @param parallel [true, Integer, Hash] options for parallel execution or the number of processes def initialize(type, parallel: nil) diff --git a/lib/chewy/type/witchcraft.rb b/lib/chewy/index/witchcraft.rb similarity index 91% rename from lib/chewy/type/witchcraft.rb rename to lib/chewy/index/witchcraft.rb index a246cae1f..a6b8dc0a7 100644 --- a/lib/chewy/type/witchcraft.rb +++ b/lib/chewy/index/witchcraft.rb @@ -7,7 +7,7 @@ end module Chewy - class Type + class Index module Witchcraft extend ActiveSupport::Concern @@ -23,15 +23,9 @@ def witchcraft! def check_requirements! messages = [] - unless Proc.method_defined?(:source) - messages << "MethodSource gem is required for the Witchcraft, please add `gem 'method_source'` to your Gemfile" - end - unless '::Parser'.safe_constantize - messages << "Parser gem is required for the Witchcraft, please add `gem 'parser'` to your Gemfile" - end - unless '::Unparser'.safe_constantize - messages << "Unparser gem is required for the Witchcraft, please add `gem 'unparser'` to your Gemfile" - end + messages << "MethodSource gem is required for the Witchcraft, please add `gem 'method_source'` to your Gemfile" unless Proc.method_defined?(:source) + messages << "Parser gem is required for the Witchcraft, please add `gem 'parser'` to your Gemfile" unless '::Parser'.safe_constantize + messages << "Unparser gem is required for the Witchcraft, please add `gem 'unparser'` to your Gemfile" unless '::Unparser'.safe_constantize messages = messages.join("\n") raise messages if messages.present? @@ -49,10 +43,10 @@ def cauldron(**options) class Cauldron attr_reader :locals - # @param type [Chewy::Type] type for composition + # @param index [Chewy::Index] index for composition # @param fields [Array] restricts the fields for composition - def initialize(type, fields: []) - @type = type + def initialize(index, fields: []) + @index = index @locals = [] @fields = fields end @@ -66,7 +60,7 @@ def brew(object, crutches = nil) def alicorn @alicorn ||= singleton_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1 -> (locals, object0, crutches) do - #{composed_values(@type.root, 0)} + #{composed_values(@index.root, 0)} end RUBY end diff --git a/lib/chewy/type/wrapper.rb b/lib/chewy/index/wrapper.rb similarity index 97% rename from lib/chewy/type/wrapper.rb rename to lib/chewy/index/wrapper.rb index 68af3aace..e69a316ea 100644 --- a/lib/chewy/type/wrapper.rb +++ b/lib/chewy/index/wrapper.rb @@ -1,5 +1,5 @@ module Chewy - class Type + class Index module Wrapper extend ActiveSupport::Concern @@ -28,7 +28,7 @@ def initialize(attributes = {}) def ==(other) return true if super - if other.is_a?(Chewy::Type) + if other.is_a?(Chewy::Index) self.class == other.class && (respond_to?(:id) ? id == other.id : attributes == other.attributes) elsif other.respond_to?(:id) self.class.adapter.target.is_a?(Class) && diff --git a/lib/chewy/journal.rb b/lib/chewy/journal.rb index 90e6ab80f..41d3b3233 100644 --- a/lib/chewy/journal.rb +++ b/lib/chewy/journal.rb @@ -2,19 +2,18 @@ module Chewy # A class to perform journal-related actions for the specified indexes/types. # # @example - # journal = Chewy::Journal.new('places#city', UsersIndex) + # journal = Chewy::Journal.new('places', UsersIndex) # journal.apply(20.minutes.ago) # journal.clean # class Journal - # @param only [Array] indexes/types or even string references to - # perform actions on + # @param only [Array] indexes or string references to perform actions on def initialize(*only) @only = only end # Applies all changes that were done since the specified time to the - # specified indexes/types. + # specified indexes. # # @param since_time [Time, DateTime] timestamp from which changes will be applied # @param retries [Integer] maximum number of attempts to make journal empty, 10 by default @@ -28,8 +27,8 @@ def apply(since_time, retries: 10, **import_options) count += entries.size groups = reference_groups(entries) ActiveSupport::Notifications.instrument 'apply_journal.chewy', stage: stage, groups: groups - groups.each do |type, references| - type.import(references, import_options.merge(journal: false)) + groups.each do |index, references| + index.import(references, import_options.merge(journal: false)) end stage += 1 since_time = entries.map(&:created_at).max @@ -48,9 +47,9 @@ def clean(until_time = nil) private def reference_groups(entries) - entries.group_by(&:type).transform_values do |grouped_entries| - grouped_entries.map(&:references).inject(:|) - end + entries.group_by(&:index_name) + .transform_keys { |index_name| Chewy.derive_name(index_name) } + .transform_values { |grouped_entries| grouped_entries.map(&:references).inject(:|) } end end end diff --git a/lib/chewy/minitest/helpers.rb b/lib/chewy/minitest/helpers.rb index c09316d20..1c7a90bfd 100644 --- a/lib/chewy/minitest/helpers.rb +++ b/lib/chewy/minitest/helpers.rb @@ -6,7 +6,7 @@ module Helpers extend ActiveSupport::Concern # Assert that an index *changes* during a block. - # @param index [Chewy::Type] the index / type to watch, eg EntitiesIndex::Entity. + # @param index [Chewy::Index] the index to watch, eg EntitiesIndex. # @param strategy [Symbol] the Chewy strategy to use around the block. See Chewy docs. # @param bypass_actual_index [true, false] # True to preempt the http call to Elastic, false otherwise. @@ -15,10 +15,10 @@ module Helpers # @return [SearchIndexReceiver] for optional further assertions on the nature of the index changes. # def assert_indexes(index, strategy: :atomic, bypass_actual_index: true, &block) - type = Chewy.derive_type index + index_class = Chewy.derive_name index receiver = SearchIndexReceiver.new - bulk_method = type.method :bulk + bulk_method = index_class.method :bulk # Manually mocking #bulk because we need to properly capture `self` bulk_mock = lambda do |*bulk_args| receiver.catch bulk_args, self @@ -28,11 +28,11 @@ def assert_indexes(index, strategy: :atomic, bypass_actual_index: true, &block) {} end - type.define_singleton_method :bulk, bulk_mock + index_class.define_singleton_method :bulk, bulk_mock Chewy.strategy(strategy, &block) - type.define_singleton_method :bulk, bulk_method + index_class.define_singleton_method :bulk, bulk_method assert_includes receiver.updated_indexes, index, "Expected #{index} to be updated but it wasn't" diff --git a/lib/chewy/rake_helper.rb b/lib/chewy/rake_helper.rb index b7e295cee..4da82ec70 100644 --- a/lib/chewy/rake_helper.rb +++ b/lib/chewy/rake_helper.rb @@ -3,7 +3,7 @@ module RakeHelper IMPORT_CALLBACK = lambda do |output, _name, start, finish, _id, payload| duration = (finish - start).ceil stats = payload.fetch(:import, {}).map { |key, count| "#{key} #{count}" }.join(', ') - output.puts " Imported #{payload[:type]} in #{human_duration(duration)}, stats: #{stats}" + output.puts " Imported #{payload[:index]} in #{human_duration(duration)}, stats: #{stats}" payload[:errors]&.each do |action, errors| output.puts " #{action.to_s.humanize} errors:" errors.each do |error, documents| @@ -85,23 +85,21 @@ def upgrade(only: nil, except: nil, parallel: nil, output: $stdout) # # @example # Chewy::RakeHelper.update # updates everything - # Chewy::RakeHelper.update(only: 'places') # updates only PlacesIndex::City and PlacesIndex::Country - # Chewy::RakeHelper.update(only: 'places#city') # updates PlacesIndex::City only - # Chewy::RakeHelper.update(except: PlacesIndex::Country) # updates everything, but PlacesIndex::Country - # Chewy::RakeHelper.update(only: 'places', except: 'places#country') # updates PlacesIndex::City only + # Chewy::RakeHelper.update(only: 'places') # updates only PlacesIndex + # Chewy::RakeHelper.update(except: PlacesIndex) # updates everything, but PlacesIndex::Country # - # @param only [Array, Chewy::Index, Chewy::Type, String] indexes or types to update; if nothing is passed - uses all the types defined in the app - # @param except [Array, Chewy::Index, Chewy::Type, String] indexes or types to exclude from processing + # @param only [Array, Chewy::Index, String] indexes to update; if nothing is passed - uses all the indexes defined in the app + # @param except [Array, Chewy::Index, String] indexes to exclude from processing # @param parallel [true, Integer, Hash] any acceptable parallel options for import # @param output [IO] output io for logging - # @return [Array] types that were actually updated + # @return [Array] indexes that were actually updated def update(only: nil, except: nil, parallel: nil, output: $stdout) subscribed_task_stats(output) do - types_from(only: only, except: except).group_by(&:index).each_with_object([]) do |(index, types), update_types| + indexes_from(only: only, except: except).each_with_object([]) do |index, updated_indexes| if index.exists? output.puts "Updating #{index}" - types.each { |type| type.import(parallel: parallel) } - update_types.concat(types) + index.import(parallel: parallel) + updated_indexes.push(index) else output.puts "Skipping #{index}, it does not exists (use rake chewy:reset[#{index.derivable_name}] to create and update it)" end @@ -113,31 +111,29 @@ def update(only: nil, except: nil, parallel: nil, output: $stdout) # # @example # Chewy::RakeHelper.sync # synchronizes everything - # Chewy::RakeHelper.sync(only: 'places') # synchronizes only PlacesIndex::City and PlacesIndex::Country - # Chewy::RakeHelper.sync(only: 'places#city') # synchronizes PlacesIndex::City only - # Chewy::RakeHelper.sync(except: PlacesIndex::Country) # synchronizes everything, but PlacesIndex::Country - # Chewy::RakeHelper.sync(only: 'places', except: 'places#country') # synchronizes PlacesIndex::City only + # Chewy::RakeHelper.sync(only: 'places') # synchronizes only PlacesIndex + # Chewy::RakeHelper.sync(except: PlacesIndex) # synchronizes everything, but PlacesIndex # - # @param only [Array, Chewy::Index, Chewy::Type, String] indexes or types to synchronize; if nothing is passed - uses all the types defined in the app - # @param except [Array, Chewy::Index, Chewy::Type, String] indexes or types to exclude from processing + # @param only [Array, Chewy::Index, String] indexes to synchronize; if nothing is passed - uses all the indexes defined in the app + # @param except [Array, Chewy::Index, String] indexes to exclude from processing # @param parallel [true, Integer, Hash] any acceptable parallel options for sync # @param output [IO] output io for logging - # @return [Array] types that were actually updated + # @return [Array] indexes that were actually updated def sync(only: nil, except: nil, parallel: nil, output: $stdout) subscribed_task_stats(output) do - types_from(only: only, except: except).each_with_object([]) do |type, synced_types| - output.puts "Synchronizing #{type}" - output.puts " #{type} doesn't support outdated synchronization" unless type.supports_outdated_sync? + indexes_from(only: only, except: except).each_with_object([]) do |index, synced_indexes| + output.puts "Synchronizing #{index}" + output.puts " #{index} doesn't support outdated synchronization" unless index.supports_outdated_sync? time = Time.now - sync_result = type.sync(parallel: parallel) + sync_result = index.sync(parallel: parallel) if !sync_result - output.puts " Something went wrong with the #{type} synchronization" + output.puts " Something went wrong with the #{index} synchronization" elsif (sync_result[:count]).positive? output.puts " Missing documents: #{sync_result[:missing]}" if sync_result[:missing].present? output.puts " Outdated documents: #{sync_result[:outdated]}" if sync_result[:outdated].present? - synced_types.push(type) + synced_indexes.push(index) else - output.puts " Skipping #{type}, up to date" + output.puts " Skipping #{index}, up to date" end output.puts " Took #{human_duration(Time.now - time)}" end @@ -145,50 +141,46 @@ def sync(only: nil, except: nil, parallel: nil, output: $stdout) end # Applies changes that were done after the specified time for the - # specified indexes/types or all of them. + # specified indexes or all of them. # # @example # Chewy::RakeHelper.journal_apply(time: 1.minute.ago) # applies entries created for the last minute - # Chewy::RakeHelper.journal_apply(time: 1.minute.ago, only: 'places') # applies only PlacesIndex::City and PlacesIndex::Country entries reated for the last minute - # Chewy::RakeHelper.journal_apply(time: 1.minute.ago, only: 'places#city') # applies PlacesIndex::City entries reated for the last minute only - # Chewy::RakeHelper.journal_apply(time: 1.minute.ago, except: PlacesIndex::Country) # applies everything, but PlacesIndex::Country entries reated for the last minute - # Chewy::RakeHelper.journal_apply(time: 1.minute.ago, only: 'places', except: 'places#country') # applies PlacesIndex::City entries reated for the last minute only + # Chewy::RakeHelper.journal_apply(time: 1.minute.ago, only: 'places') # applies only PlacesIndex entries created for the last minute + # Chewy::RakeHelper.journal_apply(time: 1.minute.ago, except: PlacesIndex) # applies everything, but PlacesIndex, entries created for the last minute # # @param time [Time, DateTime] use only journal entries created after this time - # @param only [Array, Chewy::Index, Chewy::Type, String] indexes or types to synchronize; if nothing is passed - uses all the types defined in the app - # @param except [Array, Chewy::Index, Chewy::Type, String] indexes or types to exclude from processing + # @param only [Array, Chewy::Index, String] indexes to synchronize; if nothing is passed - uses all the indexes defined in the app + # @param except [Array, Chewy::Index, String] indexes to exclude from processing # @param output [IO] output io for logging - # @return [Array] types that were actually updated + # @return [Array] indexes that were actually updated def journal_apply(time: nil, only: nil, except: nil, output: $stdout) raise ArgumentError, 'Please specify the time to start with' unless time subscribed_task_stats(output) do output.puts "Applying journal entries created after #{time}" - count = Chewy::Journal.new(types_from(only: only, except: except)).apply(time) + count = Chewy::Journal.new(indexes_from(only: only, except: except)).apply(time) output.puts 'No journal entries were created after the specified time' if count.zero? end end # Removes journal records created before the specified timestamp for - # the specified indexes/types or all of them. + # the specified indexes or all of them. # # @example # Chewy::RakeHelper.journal_clean # cleans everything # Chewy::RakeHelper.journal_clean(time: 1.minute.ago) # leaves only entries created for the last minute - # Chewy::RakeHelper.journal_clean(only: 'places') # cleans only PlacesIndex::City and PlacesIndex::Country entries - # Chewy::RakeHelper.journal_clean(only: 'places#city') # cleans PlacesIndex::City entries only - # Chewy::RakeHelper.journal_clean(except: PlacesIndex::Country) # cleans everything, but PlacesIndex::Country entries - # Chewy::RakeHelper.journal_clean(only: 'places', except: 'places#country') # cleans PlacesIndex::City entries only + # Chewy::RakeHelper.journal_clean(only: 'places') # cleans only PlacesIndex entries + # Chewy::RakeHelper.journal_clean(except: PlacesIndex) # cleans everything, but PlacesIndex entries # # @param time [Time, DateTime] clean all the journal entries created before this time - # @param only [Array, Chewy::Index, Chewy::Type, String] indexes or types to synchronize; if nothing is passed - uses all the types defined in the app - # @param except [Array, Chewy::Index, Chewy::Type, String] indexes or types to exclude from processing + # @param only [Array, Chewy::Index, String] indexes to synchronize; if nothing is passed - uses all the indexes defined in the app + # @param except [Array, Chewy::Index, String] indexes to exclude from processing # @param output [IO] output io for logging - # @return [Array] types that were actually updated + # @return [Array] indexes that were actually updated def journal_clean(time: nil, only: nil, except: nil, output: $stdout) subscribed_task_stats(output) do output.puts "Cleaning journal entries created before #{time}" if time - response = Chewy::Journal.new(types_from(only: only, except: except)).clean(time) + response = Chewy::Journal.new(indexes_from(only: only, except: except)).clean(time) count = response['deleted'] || response['_indices']['_all']['deleted'] output.puts "Cleaned up #{count} journal entries" end @@ -227,7 +219,7 @@ def reindex(source:, dest:, output: $stdout) def update_mapping(name:, output: $stdout) subscribed_task_stats(output) do output.puts "Index name is #{name}" - Chewy::Index.update_mapping(name) + normalize_index(name).update_mapping output.puts "#{name} index successfully updated" end end @@ -239,7 +231,7 @@ def normalize_indexes(*identifiers) def normalize_index(identifier) return identifier if identifier.is_a?(Class) && identifier < Chewy::Index - "#{identifier.to_s.gsub(/identifier\z/i, '').camelize}Index".constantize + "#{identifier.to_s.camelize}Index".constantize end def subscribed_task_stats(output = $stdout, &block) @@ -268,30 +260,6 @@ def indexes_from(only: nil, except: nil) indexes.sort_by(&:derivable_name) end - def types_from(only: nil, except: nil) - types = if only.present? - normalize_types(Array.wrap(only)) - else - all_indexes.flat_map(&:types) - end - - types = if except.present? - types - normalize_types(Array.wrap(except)) - else - types - end - - types.sort_by(&:derivable_name) - end - - def normalize_types(*identifiers) - identifiers.flatten(1).flat_map { |identifier| normalize_type(identifier) } - end - - def normalize_type(identifier) - Chewy.derive_types(identifier) - end - def human_duration(seconds) [[60, :s], [60, :m], [24, :h]].map do |amount, unit| if seconds.positive? diff --git a/lib/chewy/rspec/update_index.rb b/lib/chewy/rspec/update_index.rb index ced885629..309fee015 100644 --- a/lib/chewy/rspec/update_index.rb +++ b/lib/chewy/rspec/update_index.rb @@ -2,7 +2,7 @@ # Rspec matcher `update_index` # To use it - add `require 'chewy/rspec'` to the `spec_helper.rb` -# Simple usage - just pass type as argument. +# Simple usage - just pass index as argument. # # specify { expect { user.save! }.to update_index(UsersIndex::User) } # specify { expect { user.save! }.to update_index('users#user') } @@ -20,7 +20,7 @@ # specify { expect { user1.destroy!; user2.save! } } # .to update_index(UsersIndex::User).and_reindex(user2).and_delete(user1) } # -RSpec::Matchers.define :update_index do |type_name, options = {}| # rubocop:disable Metrics/BlockLength +RSpec::Matchers.define :update_index do |index_name, options = {}| # rubocop:disable Metrics/BlockLength if !respond_to?(:failure_message) && respond_to?(:failure_message_for_should) alias_method :failure_message, :failure_message_for_should alias_method :failure_message_when_negated, :failure_message_for_should_not @@ -98,13 +98,13 @@ def supports_block_expectations? @missed_reindex = [] @missed_delete = [] - type = Chewy.derive_type(type_name) + index = Chewy.derive_name(index_name) if defined?(Mocha) && RSpec.configuration.mock_framework.to_s == 'RSpec::Core::MockingAdapters::Mocha' - Chewy::Type::Import::BulkRequest.stubs(:new).with(type, any_parameters).returns(mock_bulk_request) + Chewy::Index::Import::BulkRequest.stubs(:new).with(index, any_parameters).returns(mock_bulk_request) else - mocked_already = ::RSpec::Mocks.space.proxy_for(Chewy::Type::Import::BulkRequest).method_double_if_exists_for_message(:new) - allow(Chewy::Type::Import::BulkRequest).to receive(:new).and_call_original unless mocked_already - allow(Chewy::Type::Import::BulkRequest).to receive(:new).with(type, any_args).and_return(mock_bulk_request) + mocked_already = ::RSpec::Mocks.space.proxy_for(Chewy::Index::Import::BulkRequest).method_double_if_exists_for_message(:new) + allow(Chewy::Index::Import::BulkRequest).to receive(:new).and_call_original unless mocked_already + allow(Chewy::Index::Import::BulkRequest).to receive(:new).with(index, any_args).and_return(mock_bulk_request) end Chewy.strategy(options[:strategy] || :atomic) { block.call } @@ -146,9 +146,9 @@ def supports_block_expectations? output = '' if mock_bulk_request.updates.none? - output << "Expected index `#{type_name}` to be updated, but it was not\n" + output << "Expected index `#{index_name}` to be updated, but it was not\n" elsif @missed_reindex.present? || @missed_delete.present? - message = "Expected index `#{type_name}` " + message = "Expected index `#{index_name}` " message << [ ("to update documents #{@reindex.keys}" if @reindex.present?), ("to delete documents #{@delete.keys}" if @delete.present?) @@ -197,9 +197,9 @@ def supports_block_expectations? failure_message_when_negated do if mock_bulk_request.updates.present? - "Expected index `#{type_name}` not to be updated, but it was with #{mock_bulk_request.updates.map(&:values).flatten.group_by { |documents| documents[:_id] }.map do |id, documents| - "\n document id `#{id}` (#{documents.count} times)" - end.join}\n" + "Expected index `#{index_name}` not to be updated, but it was with #{mock_bulk_request.updates.map(&:values).flatten.group_by { |documents| documents[:_id] }.map do |id, documents| + "\n document id `#{id}` (#{documents.count} times)" + end.join}\n" end end diff --git a/lib/chewy/search.rb b/lib/chewy/search.rb index 452a02da2..9f6f66cdf 100644 --- a/lib/chewy/search.rb +++ b/lib/chewy/search.rb @@ -81,10 +81,10 @@ def search_class def build_search_class(base) search_class = Class.new(base) - if self < Chewy::Type - index_scopes = index.scopes - scopes - delegate_scoped index, search_class, index_scopes - end + # if self < Chewy::Type + # index_scopes = index.scopes - scopes + # delegate_scoped index, search_class, index_scopes + # end delegate_scoped self, search_class, scopes const_set('Query', search_class) diff --git a/lib/chewy/search/loader.rb b/lib/chewy/search/loader.rb index 5f8c3c066..f984e2093 100644 --- a/lib/chewy/search/loader.rb +++ b/lib/chewy/search/loader.rb @@ -3,33 +3,28 @@ module Search # This class is used for two different purposes: load ORM/ODM # source objects. # - # @see Chewy::Type::Import + # @see Chewy::Index::Import # @see Chewy::Search::Request#load # @see Chewy::Search::Response#objects # @see Chewy::Search::Scrolling#scroll_objects class Loader - # @param indexes [Array] list of indexes to lookup types + # @param indexes [Array] list of indexes to lookup # @param options [Hash] adapter-specific load options - # @see Chewy::Type::Adapter::Base#load + # @see Chewy::Index::Adapter::Base#load def initialize(indexes: [], **options) @indexes = indexes @options = options end - # Returns a {Chewy::Type} object for index name and type name passed. Caches - # the result for each pair to make lookup faster. - # - # @param index [String] index name - # @param type [String] type name - # @return [Chewy::Type] - # @raise [Chewy::UnderivableType] when index or hash were not found - def derive_type(index, type) - (@derive_type ||= {})[[index, type]] ||= begin - index_class = derive_index(index) - raise Chewy::UnderivableType, "Can not find index named `#{index}`" unless index_class + def derive_index(index_name) + index = (@derive_index ||= {})[index_name] ||= indexes_hash[index_name] || + indexes_hash[indexes_hash.keys.sort_by(&:length) + .reverse.detect do |name| + index_name.match(/#{name}(_.+|\z)/) + end] + raise Chewy::UndefinedIndex, "Can not find index named `#{index}`" unless index - index_class.type_hash.values.first - end + index end # For each passed hit this method loads an ORM/ORD source object @@ -38,17 +33,17 @@ def derive_type(index, type) # will be returned at the corresponding position in array. # # Records/documents are loaded in an efficient manner, performing - # a single query for each type present. + # a single query for each index present. # # @param hits [Array] ES hits array # @return [Array] the array of corresponding ORM/ODM objects def load(hits) - hit_groups = hits.group_by { |hit| [hit['_index'], hit['_type']] } - loaded_objects = hit_groups.each_with_object({}) do |((index_name, type_name), hit_group), result| - type = derive_type(index_name, type_name) + hit_groups = hits.group_by { |hit| hit['_index'] } + loaded_objects = hit_groups.each_with_object({}) do |(index_name, hit_group), result| + index = derive_index(index_name) ids = hit_group.map { |hit| hit['_id'] } - loaded = type.adapter.load(ids, **@options.merge(_type: type)) - loaded ||= hit_group.map { |hit| type.build(hit) } + loaded = index.adapter.load(ids, **@options.merge(_index: index.base_name)) + loaded ||= hit_group.map { |hit| index.build(hit) } result.merge!(hit_group.zip(loaded).to_h) end @@ -58,14 +53,6 @@ def load(hits) private - def derive_index(index_name) - (@derive_index ||= {})[index_name] ||= indexes_hash[index_name] || - indexes_hash[indexes_hash.keys.sort_by(&:length) - .reverse.detect do |name| - index_name.match(/#{name}(_.+|\z)/) - end] - end - def indexes_hash @indexes_hash ||= @indexes.index_by(&:index_name) end diff --git a/lib/chewy/search/request.rb b/lib/chewy/search/request.rb index fbd5a6643..3221f2365 100644 --- a/lib/chewy/search/request.rb +++ b/lib/chewy/search/request.rb @@ -52,8 +52,8 @@ class Request alias_method :total_count, :total alias_method :total_entries, :total - # The class is initialized with the list of chewy indexes and/or - # types, which are later used to compose requests. + # The class is initialized with the list of chewy indexes, + # which are later used to compose requests. # Any symbol/string passed is treated as an index identifier. # # @example @@ -61,25 +61,22 @@ class Request # # => ["places"]}> # Chewy::Search::Request.new(PlacesIndex) # # => ["places"]}> - # Chewy::Search::Request.new(PlacesIndex::City) - # # => ["places"]}> - # Chewy::Search::Request.new(UsersIndex, PlacesIndex::City) + # Chewy::Search::Request.new(UsersIndex, PlacesIndex) # # => ["users", "places"]}> - # @param indexes_or_types [Array] indices and types in any combinations - def initialize(*indices_or_types) - indices = indices_or_types.reject do |klass| - klass.is_a?(Class) && klass < Chewy::Type - end - - types = indices_or_types.select do |klass| - klass.is_a?(Class) && klass < Chewy::Type - end - - indices += types.map(&:index) - + # @param indexes [Array] indexes + def initialize(*indexes) parameters.modify!(:indices) do - replace!(indices: indices) + replace!(indices: indexes) end + # indices = indices_or_types.reject do |klass| + # klass.is_a?(Class) && klass < Chewy::Type + # end + # + # types = indices_or_types.select do |klass| + # klass.is_a?(Class) && klass < Chewy::Type + # end + # + # indices += types.map(&:index) end # Underlying parameter storage collection. diff --git a/lib/chewy/search/response.rb b/lib/chewy/search/response.rb index 9169d0367..0a5becb24 100644 --- a/lib/chewy/search/response.rb +++ b/lib/chewy/search/response.rb @@ -64,12 +64,12 @@ def aggs end alias_method :aggregations, :aggs - # {Chewy::Type} wrappers collection instantiated on top of hits. + # {Chewy::Index} wrappers collection instantiated on top of hits. # - # @return [Array] + # @return [Array] def wrappers @wrappers ||= hits.map do |hit| - @loader.derive_type(hit['_index'], hit['_type']).build(hit) + @loader.derive_index(hit['_index']).build(hit) end end @@ -102,7 +102,7 @@ def objects # end # @see #wrappers # @see #objects - # @return [{Chewy::Type => Object}] a hash with wrappers as keys and ORM/ODM objects as values + # @return [{Chewy::Index => Object}] a hash with wrappers as keys and ORM/ODM objects as values def object_hash @object_hash ||= wrappers.zip(objects).to_h end diff --git a/lib/chewy/search/scrolling.rb b/lib/chewy/search/scrolling.rb index 25e35e88f..2f8c09f6c 100644 --- a/lib/chewy/search/scrolling.rb +++ b/lib/chewy/search/scrolling.rb @@ -90,7 +90,7 @@ def scroll_wrappers(**options) return enum_for(:scroll_wrappers, **options) unless block_given? scroll_hits(**options).each do |hit| - yield loader.derive_type(hit['_index'], hit['_type']).build(hit) + yield loader.derive_index(hit['_index']).build(hit) end end diff --git a/lib/chewy/stash.rb b/lib/chewy/stash.rb index b9fc900d2..2181ee492 100644 --- a/lib/chewy/stash.rb +++ b/lib/chewy/stash.rb @@ -9,11 +9,9 @@ module Stash class Specification < Chewy::Index index_name 'chewy_specifications' - define_type :specification do - default_import_options journal: false + default_import_options journal: false - field :specification, type: 'binary' - end + field :specification, type: 'binary' end class Journal < Chewy::Index @@ -43,33 +41,26 @@ def self.clean(until_time = nil, only: []) # @param indices [Chewy::Index, Array] def self.for(*something) something = something.flatten.compact - types = something.flat_map { |s| Chewy.derive_types(s) } - return none if something.present? && types.blank? + indexes = something.flat_map { |s| Chewy.derive_name(s) } + return none if something.present? && indexes.blank? scope = all - types.map(&:index).uniq.each do |index| + indexes.each do |index| scope = scope.or(filter(term: {index_name: index.derivable_name})) end scope end - define_type :journal do - default_import_options journal: false - - field :index_name, type: 'keyword' - field :type_name, type: 'keyword' - field :action, type: 'keyword' - field :references, type: 'binary' - field :created_at, type: 'date' + default_import_options journal: false - def type - @type ||= Chewy.derive_type("#{index_name}##{type_name}") - end + field :index_name, type: 'keyword' + field :action, type: 'keyword' + field :references, type: 'binary' + field :created_at, type: 'date' - def references - @references ||= Array.wrap(@attributes['references']).map do |item| - JSON.load(Base64.decode64(item)) # rubocop:disable Security/JSONLoad - end + def references + @references ||= Array.wrap(@attributes['references']).map do |item| + JSON.load(Base64.decode64(item)) # rubocop:disable Security/JSONLoad end end end diff --git a/lib/chewy/type.rb b/lib/chewy/type.rb deleted file mode 100644 index 159b44ecf..000000000 --- a/lib/chewy/type.rb +++ /dev/null @@ -1,119 +0,0 @@ -require 'chewy/search' -require 'chewy/type/adapter/object' -require 'chewy/type/adapter/active_record' -require 'chewy/type/mapping' -require 'chewy/type/wrapper' -require 'chewy/type/observe' -require 'chewy/type/actions' -require 'chewy/type/syncer' -require 'chewy/type/crutch' -require 'chewy/type/import' -require 'chewy/type/witchcraft' - -module Chewy - class Type - IMPORT_OPTIONS_KEYS = %i[ - batch_size bulk_size consistency direct_import journal - pipeline raw_import refresh replication - ].freeze - - include Search - include Mapping - include Wrapper - include Observe - include Actions - include Crutch - include Witchcraft - include Import - - singleton_class.delegate :index_name, :client, to: :index - - class_attribute :_default_import_options - self._default_import_options = {} - - class << self - # Chewy index current type belongs to. Defined inside `Chewy.create_type` - # - def index - raise NotImplementedError, - 'Looks like this type was defined outside the index scope and `.index` method is undefined for it' - end - - # Current type adapter. Defined inside `Chewy.create_type`, derived from - # `Chewy::Index.define_type` arguments. - # - def adapter - raise NotImplementedError - end - - # Returns type name string - # - def type_name - adapter.type_name - end - - # Appends type name to {Chewy::Index.derivable_name} - # - # @example - # class Namespace::UsersIndex < Chewy::Index - # define_type User - # end - # UsersIndex::User.derivable_name # => 'namespace/users#user' - # - # @see Chewy::Index.derivable_name - # @return [String, nil] derivable name or nil when it is impossible to calculate - def derivable_name - @derivable_name ||= [index.derivable_name, type_name].join('#') if index&.derivable_name - end - - # This method is an API shared with {Chewy::Index}, added for convenience. - # - # @return [Chewy::Type] array containing itself - def types - [self] - end - - # Returns list of public class methods defined in current type - # - def scopes - public_methods - Chewy::Type.public_methods - end - - def default_import_options(params) - params.assert_valid_keys(IMPORT_OPTIONS_KEYS) - self._default_import_options = _default_import_options.merge(params) - end - - def method_missing(method, *args, &block) - if index.scopes.include?(method) - define_singleton_method method do |*method_args, &method_block| - all.scoping { index.public_send(method, *method_args, &method_block) } - end - send(method, *args, &block) - else - super - end - end - - def respond_to_missing?(method, _) - index.scopes.include?(method) || super - end - - def const_missing(name) - to_resolve = "#{self}::#{name}" - to_resolve[index.to_s] = '' - - @__resolved_constants ||= {} - - if to_resolve.empty? || @__resolved_constants[to_resolve] - super - else - @__resolved_constants[to_resolve] = true - to_resolve.constantize - end - rescue NotImplementedError - super - end - end - end -end diff --git a/lib/chewy/type/actions.rb b/lib/chewy/type/actions.rb deleted file mode 100644 index 452b4216a..000000000 --- a/lib/chewy/type/actions.rb +++ /dev/null @@ -1,44 +0,0 @@ -module Chewy - class Type - module Actions - extend ActiveSupport::Concern - - module ClassMethods - # Deletes all documents of a type and reimports them - # - # @example - # UsersIndex::User.reset - # - # @see Chewy::Type::Import::ClassMethods#import - # @see Chewy::Type::Import::ClassMethods#import - # @return [true, false] the result of import - def reset - delete_all - import - end - - # Performs missing and outdated objects synchronization for the current type. - # - # @example - # UsersIndex::User.sync - # - # @see Chewy::Type::Syncer - # @param parallel [true, Integer, Hash] options for parallel execution or the number of processes - # @return [Hash{Symbol, Object}, nil] a number of missing and outdated documents reindexed and their ids, - # nil in case of errors - def sync(parallel: nil) - syncer = Syncer.new(self, parallel: parallel) - count = syncer.perform - {count: count, missing: syncer.missing_ids, outdated: syncer.outdated_ids} if count - end - - # A {Chewy::Journal} instance for the particular type - # - # @return [Chewy::Journal] journal instance - def journal - @journal ||= Chewy::Journal.new(self) - end - end - end - end -end diff --git a/spec/chewy/fields/base_spec.rb b/spec/chewy/fields/base_spec.rb index 135559676..1d427e990 100644 --- a/spec/chewy/fields/base_spec.rb +++ b/spec/chewy/fields/base_spec.rb @@ -141,14 +141,12 @@ context 'default field type' do before do stub_index(:events) do - define_type :event do + field :id + field :category do field :id - field :category do + field :licenses do field :id - field :licenses do - field :id - field :created_at, type: 'time' - end + field :created_at, type: 'time' end end end @@ -162,18 +160,20 @@ end specify do - expect(EventsIndex::Event.mappings_hash).to eq( - properties: { - id: {type: 'integer'}, - category: { - type: 'object', - properties: { - id: {type: 'integer'}, - licenses: { - type: 'object', - properties: { - id: {type: 'integer'}, - created_at: {type: 'time'} + expect(EventsIndex.mappings_hash).to eq( + mappings: { + properties: { + id: {type: 'integer'}, + category: { + type: 'object', + properties: { + id: {type: 'integer'}, + licenses: { + type: 'object', + properties: { + id: {type: 'integer'}, + created_at: {type: 'time'} + } } } } @@ -186,14 +186,12 @@ context 'objects, hashes and arrays' do before do stub_index(:events) do - define_type :event do + field :id + field :category do field :id - field :category do + field :licenses do field :id - field :licenses do - field :id - field :name - end + field :name end end end @@ -201,13 +199,13 @@ specify do expect( - EventsIndex::Event.root.compose({id: 1, category: {id: 2, licenses: {id: 3, name: 'Name'}}}) + EventsIndex.root.compose({id: 1, category: {id: 2, licenses: {id: 3, name: 'Name'}}}) ).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}}) end specify do expect( - EventsIndex::Event.root.compose({id: 1, category: [ + EventsIndex.root.compose({id: 1, category: [ {id: 2, 'licenses' => {id: 3, name: 'Name1'}}, {id: 4, licenses: nil} ]}) @@ -219,7 +217,7 @@ specify do expect( - EventsIndex::Event.root.compose({ + EventsIndex.root.compose({ 'id' => 1, category: { id: 2, licenses: [ @@ -242,7 +240,7 @@ specify do expect( - EventsIndex::Event.root.compose({id: 1, category: [ + EventsIndex.root.compose({id: 1, category: [ {id: 2, licenses: [ {id: 3, 'name' => 'Name1'}, {id: 4, name: 'Name2'} ]}, @@ -261,13 +259,13 @@ end specify do expect( - EventsIndex::Event.root.compose(double(id: 1, category: double(id: 2, licenses: double(id: 3, name: 'Name')))) + EventsIndex.root.compose(double(id: 1, category: double(id: 2, licenses: double(id: 3, name: 'Name')))) ).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}}) end specify do expect( - EventsIndex::Event.root.compose(double(id: 1, category: [ + EventsIndex.root.compose(double(id: 1, category: [ double(id: 2, licenses: double(id: 3, name: 'Name1')), double(id: 4, licenses: nil) ])) @@ -279,7 +277,7 @@ specify do expect( - EventsIndex::Event.root.compose(double(id: 1, category: double(id: 2, licenses: [ + EventsIndex.root.compose(double(id: 1, category: double(id: 2, licenses: [ double(id: 3, name: 'Name1'), double(id: 4, name: 'Name2') ]))) ).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => [ @@ -289,7 +287,7 @@ specify do expect( - EventsIndex::Event.root.compose(double(id: 1, category: [ + EventsIndex.root.compose(double(id: 1, category: [ double(id: 2, licenses: [ double(id: 3, name: 'Name1'), double(id: 4, name: 'Name2') ]), @@ -309,14 +307,12 @@ context 'custom methods' do before do stub_index(:events) do - define_type :event do + field :id, type: 'integer' + field :category, value: -> { categories } do field :id, type: 'integer' - field :category, value: -> { categories } do + field :licenses, value: -> { license } do field :id, type: 'integer' - field :licenses, value: -> { license } do - field :id, type: 'integer' - field :name - end + field :name end end end @@ -324,7 +320,7 @@ specify do expect( - EventsIndex::Event.root.compose( + EventsIndex.root.compose( double( id: 1, categories: double( id: 2, license: double( @@ -340,34 +336,34 @@ context 'objects and multi_fields' do before do stub_index(:events) do - define_type :event do - field :id, type: 'integer' - field :name, type: 'integer' do - field :raw, analyzer: 'my_own' - end - field :category, type: 'object' + field :id, type: 'integer' + field :name, type: 'integer' do + field :raw, analyzer: 'my_own' end + field :category, type: 'object' end end specify do - expect(EventsIndex::Event.mappings_hash).to eq( - properties: { - id: {type: 'integer'}, - name: { - type: 'integer', - fields: { - raw: {analyzer: 'my_own', type: Chewy.default_field_type} - } - }, - category: {type: 'object'} + expect(EventsIndex.mappings_hash).to eq( + mappings: { + properties: { + id: {type: 'integer'}, + name: { + type: 'integer', + fields: { + raw: {analyzer: 'my_own', type: Chewy.default_field_type} + } + }, + category: {type: 'object'} + } } ) end specify do expect( - EventsIndex::Event.root.compose( + EventsIndex.root.compose( double( id: 1, name: 'Jonny', category: double( id: 2, as_json: {'name' => 'Borogoves'} @@ -383,7 +379,7 @@ specify do expect( - EventsIndex::Event.root.compose( + EventsIndex.root.compose( double(id: 1, name: 'Jonny', category: [ double(id: 2, as_json: {'name' => 'Borogoves1'}), double(id: 3, as_json: {'name' => 'Borogoves2'}) @@ -415,14 +411,13 @@ context 'text fields with and without ignore_blank option' do before do stub_index(:countries) do - define_type Country do + index_scope Country + field :id + field :cities do field :id - field :cities do - field :id - field :name - field :historical_name, ignore_blank: false - field :description, ignore_blank: true - end + field :name + field :historical_name, ignore_blank: false + field :description, ignore_blank: true end end end @@ -437,7 +432,7 @@ end specify do - expect(CountriesIndex::Country.root.compose(country_with_cities)).to eq( + expect(CountriesIndex.root.compose(country_with_cities)).to eq( 'id' => 1, 'cities' => [ {'id' => 1, 'name' => '', 'historical_name' => ''}, {'id' => 2, 'name' => '', 'historical_name' => ''} @@ -450,14 +445,13 @@ context 'with ignore_blank: true option' do before do stub_index(:countries) do - define_type Country do + index_scope Country + field :id + field :cities, ignore_blank: true do field :id - field :cities, ignore_blank: true do - field :id - field :name - field :historical_name, ignore_blank: true - field :description - end + field :name + field :historical_name, ignore_blank: true + field :description end end end @@ -466,14 +460,14 @@ context('without cities') do let(:cities) { [] } specify do - expect(CountriesIndex::Country.root.compose(country)) + expect(CountriesIndex.root.compose(country)) .to eq('id' => 1) end end context('with cities') do let(:cities) { [City.create!(id: 1, name: '', historical_name: '')] } specify do - expect(CountriesIndex::Country.root.compose(country)).to eq( + expect(CountriesIndex.root.compose(country)).to eq( 'id' => 1, 'cities' => [ {'id' => 1, 'name' => '', 'description' => nil} ] @@ -485,14 +479,13 @@ context 'with ignore_blank: false option' do before do stub_index(:countries) do - define_type Country do + index_scope Country + field :id + field :cities, ignore_blank: false do field :id - field :cities, ignore_blank: false do - field :id - field :name - field :historical_name - field :description - end + field :name + field :historical_name + field :description end end end @@ -500,7 +493,7 @@ let(:country_with_cities) { Country.create!(id: 1) } specify do - expect(CountriesIndex::Country.root.compose(country_with_cities)) + expect(CountriesIndex.root.compose(country_with_cities)) .to eq('id' => 1, 'cities' => []) end end @@ -508,14 +501,13 @@ context 'without ignore_blank: true option' do before do stub_index(:countries) do - define_type Country do + index_scope Country + field :id + field :cities do field :id - field :cities do - field :id - field :name - field :historical_name - field :description - end + field :name + field :historical_name + field :description end end end @@ -523,7 +515,7 @@ let(:country_with_cities) { Country.create!(id: 1) } specify do - expect(CountriesIndex::Country.root.compose(country_with_cities)) + expect(CountriesIndex.root.compose(country_with_cities)) .to eq('id' => 1, 'cities' => []) end end @@ -533,15 +525,14 @@ context 'with ignore_blank: true option' do before do stub_index(:countries) do - define_type Country do + index_scope Country + field :id + field :cities do field :id - field :cities do - field :id - field :name - field :location, type: :geo_point, ignore_blank: true do - field :lat - field :lon - end + field :name + field :location, type: :geo_point, ignore_blank: true do + field :lat + field :lon end end end @@ -549,7 +540,7 @@ specify do expect( - CountriesIndex::Country.root.compose({ + CountriesIndex.root.compose({ 'id' => 1, 'cities' => [ {'id' => 1, 'name' => 'City1', 'location' => {}}, @@ -568,15 +559,14 @@ context 'without ignore_blank option' do before do stub_index(:countries) do - define_type Country do + index_scope Country + field :id + field :cities do field :id - field :cities do - field :id - field :name - field :location, type: :geo_point do - field :lat - field :lon - end + field :name + field :location, type: :geo_point do + field :lat + field :lon end end end @@ -584,7 +574,7 @@ specify do expect( - CountriesIndex::Country.root.compose({ + CountriesIndex.root.compose({ 'id' => 1, 'cities' => [ {'id' => 1, 'name' => 'City1', 'location' => {}}, @@ -603,15 +593,14 @@ context 'with ignore_blank: false flag' do before do stub_index(:countries) do - define_type Country do + index_scope Country + field :id + field :cities do field :id - field :cities do - field :id - field :name - field :location, type: :geo_point, ignore_blank: false do - field :lat - field :lon - end + field :name + field :location, type: :geo_point, ignore_blank: false do + field :lat + field :lon end end end @@ -619,7 +608,7 @@ specify do expect( - CountriesIndex::Country.root.compose({ + CountriesIndex.root.compose({ 'id' => 1, 'cities' => [ {'id' => 1, 'location' => {}, 'name' => 'City1'}, @@ -646,12 +635,11 @@ Country.has_many :cities, -> { order :id } stub_index(:countries) do - define_type Country do + index_scope Country + field :id + field :cities do field :id - field :cities do - field :id - field :name - end + field :name end end end @@ -663,7 +651,7 @@ end specify do - expect(CountriesIndex::Country.root.compose(country_with_cities)).to eq('id' => 1, 'cities' => [ + expect(CountriesIndex.root.compose(country_with_cities)).to eq('id' => 1, 'cities' => [ {'id' => 1, 'name' => 'City1'}, {'id' => 2, 'name' => 'City2'} ]) end @@ -671,19 +659,18 @@ context 'nested object' do before do stub_index(:cities) do - define_type City do + index_scope City + field :id + field :country do field :id - field :country do - field :id - field :name - end + field :name end end end specify do expect( - CitiesIndex::City.root.compose(City.create!(id: 1, country: Country.create!(id: 1, name: 'Country'))) + CitiesIndex.root.compose(City.create!(id: 1, country: Country.create!(id: 1, name: 'Country'))) ).to eq('id' => 1, 'country' => {'id' => 1, 'name' => 'Country'}) end end diff --git a/spec/chewy/fields/root_spec.rb b/spec/chewy/fields/root_spec.rb index dc6bfb3c7..18bf7cb0c 100644 --- a/spec/chewy/fields/root_spec.rb +++ b/spec/chewy/fields/root_spec.rb @@ -46,18 +46,18 @@ before do stub_model(:city) stub_index(:places) do - define_type City + index_scope City end end let(:city) { City.new(name: 'London', rating: 100) } specify do - expect(PlacesIndex::City.root.compose(city)) + expect(PlacesIndex.root.compose(city)) .to match(hash_including('name' => 'London', 'rating' => 100)) end specify do - expect(PlacesIndex::City.root.compose(city, fields: %i[name borogoves])) + expect(PlacesIndex.root.compose(city, fields: %i[name borogoves])) .to eq('name' => 'London') end end @@ -65,20 +65,18 @@ context 'has children' do before do stub_index(:places) do - define_type :city do - field :name, :rating - end + field :name, :rating end end let(:city) { double(name: 'London', rating: 100) } specify do - expect(PlacesIndex::City.root.compose(city)) + expect(PlacesIndex.root.compose(city)) .to eq('name' => 'London', 'rating' => 100) end specify do - expect(PlacesIndex::City.root.compose(city, fields: %i[name borogoves])) + expect(PlacesIndex.root.compose(city, fields: %i[name borogoves])) .to eq('name' => 'London') end end @@ -86,21 +84,19 @@ context 'root value provided' do before do stub_index(:places) do - define_type :city do - root value: ->(o) { {name: "#{o.name}Modified", rating: o.rating.next} } - end + root value: ->(o) { {name: "#{o.name}Modified", rating: o.rating.next} } end end let(:city) { double(name: 'London', rating: 100) } specify do - expect(PlacesIndex::City.root.compose(city)) + expect(PlacesIndex.root.compose(city)) .to eq('name' => 'LondonModified', 'rating' => 101) end specify do - expect(PlacesIndex::City.root.compose(city, fields: %i[name borogoves])) + expect(PlacesIndex.root.compose(city, fields: %i[name borogoves])) .to eq('name' => 'LondonModified') end end @@ -108,11 +104,9 @@ context 'complex evaluations' do before do stub_index(:places) do - define_type :city do - root value: ->(o) { {name: "#{o.name}Modified", rating: o.rating.next} } do - field :name, value: ->(o) { "#{o[:name]}Modified" } - field :rating - end + root value: ->(o) { {name: "#{o.name}Modified", rating: o.rating.next} } do + field :name, value: ->(o) { "#{o[:name]}Modified" } + field :rating end end end @@ -120,12 +114,12 @@ let(:city) { double(name: 'London', rating: 100) } specify do - expect(PlacesIndex::City.root.compose(city)) + expect(PlacesIndex.root.compose(city)) .to eq('name' => 'LondonModifiedModified', 'rating' => 101) end specify do - expect(PlacesIndex::City.root.compose(city, fields: %i[name borogoves])) + expect(PlacesIndex.root.compose(city, fields: %i[name borogoves])) .to eq('name' => 'LondonModifiedModified') end end @@ -134,14 +128,12 @@ describe '#child_hash' do before do stub_index(:places) do - define_type :city do - field :name, :rating - end + field :name, :rating end end specify do - expect(PlacesIndex::City.root.child_hash).to match( + expect(PlacesIndex.root.child_hash).to match( name: an_instance_of(Chewy::Fields::Base).and(have_attributes(name: :name)), rating: an_instance_of(Chewy::Fields::Base).and(have_attributes(name: :rating)) ) diff --git a/spec/chewy/fields/time_fields_spec.rb b/spec/chewy/fields/time_fields_spec.rb index 395033f34..31aef9777 100644 --- a/spec/chewy/fields/time_fields_spec.rb +++ b/spec/chewy/fields/time_fields_spec.rb @@ -5,14 +5,12 @@ before do stub_index(:posts) do - define_type :post do - field :published_at, type: 'date' - end + field :published_at, type: 'date' end end before do - PostsIndex::Post.import( + PostsIndex.import( double(published_at: ActiveSupport::TimeZone[-28_800].parse('2014/12/18 19:00')), double(published_at: ActiveSupport::TimeZone[-21_600].parse('2014/12/18 20:00')), double(published_at: ActiveSupport::TimeZone[-21_600].parse('2014/12/17 20:00')) diff --git a/spec/chewy/index/actions_spec.rb b/spec/chewy/index/actions_spec.rb index 9a943940d..0ca812d92 100644 --- a/spec/chewy/index/actions_spec.rb +++ b/spec/chewy/index/actions_spec.rb @@ -349,7 +349,7 @@ before do stub_model(:city) stub_index(:cities) do - define_type City + index_scope City end end let!(:dummy_cities) { Array.new(3) { |i| City.create(id: i + 1, name: "name#{i}") } } @@ -371,9 +371,8 @@ context do before do stub_index(:cities) do - define_type City do - field :name, type: 'object' - end + index_scope City + field :name, type: 'object' end end @@ -385,7 +384,7 @@ before do stub_model(:city) stub_index(:cities) do - define_type City + index_scope City end end let!(:dummy_cities) { Array.new(3) { |i| City.create(id: i + 1, name: "name#{i}") } } @@ -407,9 +406,8 @@ context do before do stub_index(:cities) do - define_type City do - field :name, type: 'object' - end + index_scope City + field :name, type: 'object' end end @@ -421,7 +419,7 @@ before do stub_model(:city) stub_index(:cities) do - define_type City + index_scope City end end @@ -512,7 +510,7 @@ before do stub_index(:cities) do settings index: {refresh_interval: '2s'} - define_type City + index_scope City end end @@ -588,12 +586,11 @@ xcontext 'applying journal' do before do stub_index(:cities) do - define_type City do - field :name, value: (lambda do - sleep(rating) - name - end) - end + index_scope City + field :name, value: (lambda do + sleep(rating) + name + end) end end @@ -663,12 +660,12 @@ context 'other options' do specify do - expect(CitiesIndex::City).to receive(:import).with(parallel: true, journal: false).once.and_return(true) + expect(CitiesIndex).to receive(:import).with(parallel: true, journal: false).once.and_return(true) expect(CitiesIndex.reset!(parallel: true)).to eq(true) end specify do - expect(CitiesIndex::City) + expect(CitiesIndex) .to receive(:import) .with(suffix: 'suffix', parallel: true, journal: false, refresh: true) .once.and_return(true) @@ -677,6 +674,64 @@ end end + describe '.reset' do + before do + stub_model(:city) + stub_index(:cities) do + index_scope City + end + end + + context do + before { City.create!(id: 1, name: 'Moscow') } + + specify { expect(CitiesIndex.reset).to eq(true) } + specify { expect(CitiesIndex.reset('2013')).to eq(true) } + + context do + before { CitiesIndex.reset } + + specify { expect(CitiesIndex.all).to have(1).item } + specify { expect(CitiesIndex.aliases).to eq([]) } + specify { expect(CitiesIndex.indexes).to eq(['cities']) } + end + end + end + + describe '.sync' do + before do + stub_model(:city) + stub_index(:cities) do + index_scope City + field :name + field :updated_at, type: 'date' + end + end + + let!(:cities) { Array.new(3) { |i| City.create!(name: "Name#{i + 1}") } } + + before do + CitiesIndex.import + cities.first.destroy + cities.last.update(name: 'Name5') + end + + let!(:additional_city) { City.create!(name: 'Name4') } + + specify do + expect(CitiesIndex.sync).to match( + count: 3, + missing: contain_exactly(cities.first.id.to_s, additional_city.id.to_s), + outdated: [cities.last.id.to_s] + ) + end + specify do + expect { CitiesIndex.sync }.to update_index(CitiesIndex) + .and_reindex(additional_city, cities.last) + .and_delete(cities.first).only + end + end + describe '.journal' do specify { expect(DummiesIndex.journal).to be_a(Chewy::Journal) } end @@ -685,7 +740,7 @@ before do stub_model(:city) stub_index(:cities) do - define_type City + index_scope City end end @@ -703,7 +758,7 @@ .to receive(:clear_cache) .and_call_original expect { CitiesIndex.clear_cache({index: index_name_with_prefix}) } - .not_to raise_error Elasticsearch::Transport::Transport::Errors::NotFound + .not_to raise_error end end @@ -727,7 +782,7 @@ .to receive(:clear_cache) .and_call_original expect { CitiesIndex.clear_cache } - .not_to raise_error Elasticsearch::Transport::Transport::Errors::NotFound + .not_to raise_error end end end @@ -736,7 +791,7 @@ before do stub_model(:city) stub_index(:cities) do - define_type City + index_scope City end CitiesIndex.create(source_index) DummiesIndex.create(dest_index) @@ -807,7 +862,7 @@ before do stub_model(:city) stub_index(:cities) do - define_type City + index_scope City end CitiesIndex.create end diff --git a/spec/chewy/type/adapter/active_record_spec.rb b/spec/chewy/index/adapter/active_record_spec.rb similarity index 92% rename from spec/chewy/type/adapter/active_record_spec.rb rename to spec/chewy/index/adapter/active_record_spec.rb index f53953516..699e91e98 100644 --- a/spec/chewy/type/adapter/active_record_spec.rb +++ b/spec/chewy/index/adapter/active_record_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Chewy::Type::Adapter::ActiveRecord, :active_record do +describe Chewy::Index::Adapter::ActiveRecord, :active_record do before do stub_model(:city) stub_model(:country) @@ -509,30 +509,28 @@ def delete_already? let(:city_ids) { cities.map(&:id) } let(:deleted_ids) { deleted.map(&:id) } - let(:type) { double(type_name: 'user') } - subject { described_class.new(City) } - specify { expect(subject.load(city_ids, _type: type)).to eq(cities) } - specify { expect(subject.load(city_ids.reverse, _type: type)).to eq(cities.reverse) } - specify { expect(subject.load(deleted_ids, _type: type)).to eq([nil, nil]) } - specify { expect(subject.load(city_ids + deleted_ids, _type: type)).to eq([*cities, nil, nil]) } + specify { expect(subject.load(city_ids, _index: 'users')).to eq(cities) } + specify { expect(subject.load(city_ids.reverse, _index: 'users')).to eq(cities.reverse) } + specify { expect(subject.load(deleted_ids, _index: 'users')).to eq([nil, nil]) } + specify { expect(subject.load(city_ids + deleted_ids, _index: 'users')).to eq([*cities, nil, nil]) } specify do - expect(subject.load(city_ids, _type: type, scope: -> { where(rating: 0) })) + expect(subject.load(city_ids, _index: 'users', scope: -> { where(rating: 0) })) .to eq(cities.first(2) + [nil]) end specify do expect( - subject.load(city_ids, _type: type, scope: -> { where(rating: 0) }, user: {scope: -> { where(rating: 1) }}) + subject.load(city_ids, _index: 'users', scope: -> { where(rating: 0) }, users: {scope: -> { where(rating: 1) }}) ).to eq([nil, nil] + cities.last(1)) end specify do - expect(subject.load(city_ids, _type: type, scope: City.where(rating: 1))) + expect(subject.load(city_ids, _index: 'users', scope: City.where(rating: 1))) .to eq([nil, nil] + cities.last(1)) end specify do expect( - subject.load(city_ids, _type: type, scope: City.where(rating: 1), user: {scope: -> { where(rating: 0) }}) + subject.load(city_ids, _index: 'users', scope: City.where(rating: 1), users: {scope: -> { where(rating: 0) }}) ).to eq(cities.first(2) + [nil]) end end @@ -544,33 +542,31 @@ def delete_already? let(:city_ids) { cities.map(&:rating) } let(:deleted_ids) { deleted.map(&:rating) } - let(:type) { double(type_name: 'user') } - subject { described_class.new(City) } - specify { expect(subject.load(city_ids, _type: type)).to eq(cities) } - specify { expect(subject.load(city_ids.reverse, _type: type)).to eq(cities.reverse) } - specify { expect(subject.load(deleted_ids, _type: type)).to eq([nil, nil]) } - specify { expect(subject.load(city_ids + deleted_ids, _type: type)).to eq([*cities, nil, nil]) } + specify { expect(subject.load(city_ids, _index: 'users')).to eq(cities) } + specify { expect(subject.load(city_ids.reverse, _index: 'users')).to eq(cities.reverse) } + specify { expect(subject.load(deleted_ids, _index: 'users')).to eq([nil, nil]) } + specify { expect(subject.load(city_ids + deleted_ids, _index: 'users')).to eq([*cities, nil, nil]) } specify do - expect(subject.load(city_ids, _type: type, scope: -> { where(country_id: 0) })) + expect(subject.load(city_ids, _index: 'users', scope: -> { where(country_id: 0) })) .to eq(cities.first(2) + [nil]) end specify do expect( subject.load( - city_ids, _type: type, scope: -> { where(country_id: 0) }, user: {scope: -> { where(country_id: 1) }} + city_ids, _index: 'users', scope: -> { where(country_id: 0) }, users: {scope: -> { where(country_id: 1) }} ) ).to eq([nil, nil] + cities.last(1)) end specify do - expect(subject.load(city_ids, _type: type, scope: City.where(country_id: 1))) + expect(subject.load(city_ids, _index: 'users', scope: City.where(country_id: 1))) .to eq([nil, nil] + cities.last(1)) end specify do expect( subject.load( - city_ids, _type: type, scope: City.where(country_id: 1), user: {scope: -> { where(country_id: 0) }} + city_ids, _index: 'users', scope: City.where(country_id: 1), users: {scope: -> { where(country_id: 0) }} ) ).to eq(cities.first(2) + [nil]) end diff --git a/spec/chewy/type/adapter/object_spec.rb b/spec/chewy/index/adapter/object_spec.rb similarity index 99% rename from spec/chewy/type/adapter/object_spec.rb rename to spec/chewy/index/adapter/object_spec.rb index 6c59140ba..640d96d64 100644 --- a/spec/chewy/type/adapter/object_spec.rb +++ b/spec/chewy/index/adapter/object_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Chewy::Type::Adapter::Object do +describe Chewy::Index::Adapter::Object do before { stub_class(:product) } subject { described_class.new(:product) } diff --git a/spec/chewy/type/import/bulk_builder_spec.rb b/spec/chewy/index/import/bulk_builder_spec.rb similarity index 76% rename from spec/chewy/type/import/bulk_builder_spec.rb rename to spec/chewy/index/import/bulk_builder_spec.rb index 507156845..c793af93f 100644 --- a/spec/chewy/type/import/bulk_builder_spec.rb +++ b/spec/chewy/index/import/bulk_builder_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -describe Chewy::Type::Import::BulkBuilder do +describe Chewy::Index::Import::BulkBuilder do before { Chewy.massacre } - subject { described_class.new(type, index: index, delete: delete, fields: fields) } - let(:type) { CitiesIndex::City } - let(:index) { [] } + subject { described_class.new(index, to_index: to_index, delete: delete, fields: fields) } + let(:index) { CitiesIndex } + let(:to_index) { [] } let(:delete) { [] } let(:fields) { [] } @@ -14,9 +14,8 @@ before do stub_model(:city) stub_index(:cities) do - define_type City do - field :name, :rating - end + index_scope City + field :name, :rating end end let(:cities) { Array.new(3) { |i| City.create!(id: i + 1, name: "City#{i + 17}", rating: 42) } } @@ -24,7 +23,7 @@ specify { expect(subject.bulk_body).to eq([]) } context do - let(:index) { cities } + let(:to_index) { cities } specify do expect(subject.bulk_body).to eq([ {index: {_id: 1, data: {'name' => 'City17', 'rating' => 42}}}, @@ -44,7 +43,7 @@ end context do - let(:index) { cities.first(2) } + let(:to_index) { cities.first(2) } let(:delete) { [cities.last] } specify do expect(subject.bulk_body).to eq([ @@ -74,10 +73,9 @@ before do stub_index(:cities) do - define_type City do - root id: -> { name } do - field :rating - end + index_scope City + root id: -> { name } do + field :rating end end end @@ -90,7 +88,7 @@ end context 'indexing' do - let(:index) { [london] } + let(:to_index) { [london] } specify do expect(subject.bulk_body).to eq([ @@ -113,17 +111,15 @@ context 'crutches' do before do stub_index(:cities) do - define_type :city do - crutch :names do |collection| - collection.map { |item| [item.id, "Name#{item.id}"] }.to_h - end - - field :name, value: ->(o, c) { c.names[o.id] } + crutch :names do |collection| + collection.map { |item| [item.id, "Name#{item.id}"] }.to_h end + + field :name, value: ->(o, c) { c.names[o.id] } end end - let(:index) { [double(id: 42)] } + let(:to_index) { [double(id: 42)] } specify do expect(subject.bulk_body).to eq([ @@ -132,7 +128,7 @@ end context 'witchcraft' do - before { CitiesIndex::City.witchcraft! } + before { CitiesIndex.witchcraft! } specify do expect(subject.bulk_body).to eq([ {index: {_id: 42, data: {'name' => 'Name42'}}} @@ -144,13 +140,11 @@ context 'empty ids' do before do stub_index(:cities) do - define_type :city do - field :name - end + field :name end end - let(:index) { [{id: 1, name: 'Name0'}, double(id: '', name: 'Name1'), double(name: 'Name2')] } + let(:to_index) { [{id: 1, name: 'Name0'}, double(id: '', name: 'Name1'), double(name: 'Name2')] } let(:delete) { [double(id: '', name: 'Name3'), {name: 'Name4'}, '', 2] } specify do @@ -180,15 +174,13 @@ describe '#index_objects_by_id' do before do stub_index(:cities) do - define_type :city do - field :name - end + field :name end end - let(:index) { [double(id: 1), double(id: 2), double(id: ''), double] } + let(:to_index) { [double(id: 1), double(id: 2), double(id: ''), double] } let(:delete) { [double(id: 3)] } - specify { expect(subject.index_objects_by_id).to eq('1' => index.first, '2' => index.second) } + specify { expect(subject.index_objects_by_id).to eq('1' => to_index.first, '2' => to_index.second) } end end diff --git a/spec/chewy/type/import/bulk_request_spec.rb b/spec/chewy/index/import/bulk_request_spec.rb similarity index 91% rename from spec/chewy/type/import/bulk_request_spec.rb rename to spec/chewy/index/import/bulk_request_spec.rb index 3b62fd8b8..0869804a1 100644 --- a/spec/chewy/type/import/bulk_request_spec.rb +++ b/spec/chewy/index/import/bulk_request_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -describe Chewy::Type::Import::BulkRequest do +describe Chewy::Index::Import::BulkRequest do before { Chewy.massacre } - subject { described_class.new(type, suffix: suffix, bulk_size: bulk_size, **bulk_options) } + subject { described_class.new(index, suffix: suffix, bulk_size: bulk_size, **bulk_options) } let(:suffix) {} let(:bulk_size) {} let(:bulk_options) { {} } - let(:type) { PlacesIndex::City } + let(:index) { PlacesIndex } describe '#initialize' do specify { expect { described_class.new(nil, bulk_size: 100) }.to raise_error(ArgumentError) } @@ -18,9 +18,8 @@ before do stub_model(:city) stub_index(:places) do - define_type City do - field :name - end + index_scope City + field :name end end diff --git a/spec/chewy/type/import/journal_builder_spec.rb b/spec/chewy/index/import/journal_builder_spec.rb similarity index 76% rename from spec/chewy/type/import/journal_builder_spec.rb rename to spec/chewy/index/import/journal_builder_spec.rb index 25b36f48c..3b8904467 100644 --- a/spec/chewy/type/import/journal_builder_spec.rb +++ b/spec/chewy/index/import/journal_builder_spec.rb @@ -1,13 +1,11 @@ require 'spec_helper' -describe Chewy::Type::Import::JournalBuilder, :orm do +describe Chewy::Index::Import::JournalBuilder, :orm do before do stub_model(:country) - stub_index 'namespace/cities' do - define_type :city - end + stub_index 'namespace/cities' stub_index 'namespace/countries' do - define_type Country + index_scope Country end Timecop.freeze(time) end @@ -15,23 +13,22 @@ let(:time) { Time.parse('2017-07-14 12:00Z') } - let(:type) { Namespace::CitiesIndex::City } - let(:index) { [] } + let(:index) { Namespace::CitiesIndex } + let(:to_index) { [] } let(:delete) { [] } - subject { described_class.new(type, index: index, delete: delete) } + subject { described_class.new(index, to_index: to_index, delete: delete) } describe '#bulk_body' do specify { expect(subject.bulk_body).to eq([]) } context do - let(:index) { [{id: 1, name: 'City'}] } + let(:to_index) { [{id: 1, name: 'City'}] } specify do expect(subject.bulk_body).to eq([{ index: { _index: 'chewy_journal', data: { 'index_name' => 'namespace/cities', - 'type_name' => 'city', 'action' => 'index', 'references' => [Base64.encode64('{"id":1,"name":"City"}')], 'created_at' => time.as_json @@ -49,7 +46,6 @@ _index: 'chewy_journal', data: { 'index_name' => 'namespace/cities', - 'type_name' => 'city', 'action' => 'delete', 'references' => [Base64.encode64('{"id":1,"name":"City"}')], 'created_at' => time.as_json @@ -60,8 +56,8 @@ end context do - let(:type) { Namespace::CountriesIndex::Country } - let(:index) { [Country.new(id: 1, name: 'City')] } + let(:index) { Namespace::CountriesIndex } + let(:to_index) { [Country.new(id: 1, name: 'City')] } let(:delete) { [Country.new(id: 2, name: 'City')] } specify do expect(subject.bulk_body).to eq([{ @@ -69,7 +65,6 @@ _index: 'chewy_journal', data: { 'index_name' => 'namespace/countries', - 'type_name' => 'country', 'action' => 'index', 'references' => [Base64.encode64('1')], 'created_at' => time.as_json @@ -80,7 +75,6 @@ _index: 'chewy_journal', data: { 'index_name' => 'namespace/countries', - 'type_name' => 'country', 'action' => 'delete', 'references' => [Base64.encode64('2')], 'created_at' => time.as_json diff --git a/spec/chewy/type/import/routine_spec.rb b/spec/chewy/index/import/routine_spec.rb similarity index 69% rename from spec/chewy/type/import/routine_spec.rb rename to spec/chewy/index/import/routine_spec.rb index ba5f4778a..40eb3d7ae 100644 --- a/spec/chewy/type/import/routine_spec.rb +++ b/spec/chewy/index/import/routine_spec.rb @@ -1,14 +1,12 @@ require 'spec_helper' # TODO: add more specs here later -describe Chewy::Type::Import::Routine do +describe Chewy::Index::Import::Routine do before { Chewy.massacre } before do stub_index(:cities) do - define_type :city do - field :name - field :object, type: 'object' - end + field :name + field :object, type: 'object' end CitiesIndex.create! end @@ -18,7 +16,7 @@ describe '#options' do specify do - expect(described_class.new(CitiesIndex::City).options).to eq( + expect(described_class.new(CitiesIndex).options).to eq( journal: nil, refresh: true, update_failover: true, @@ -29,7 +27,7 @@ specify do expect(described_class.new( - CitiesIndex::City, batch_size: 100, bulk_size: 1.megabyte, refresh: false + CitiesIndex, batch_size: 100, bulk_size: 1.megabyte, refresh: false ).options).to eq( journal: nil, refresh: false, @@ -43,7 +41,7 @@ context do before { allow(Chewy).to receive_messages(configuration: Chewy.configuration.merge(journal: true)) } specify do - expect(described_class.new(CitiesIndex::City).options).to eq( + expect(described_class.new(CitiesIndex).options).to eq( journal: true, refresh: true, update_failover: true, @@ -55,26 +53,26 @@ specify do expect(CitiesIndex.client).to receive(:bulk).with(hash_including(refresh: true)) - described_class.new(CitiesIndex::City).process(index: index) + described_class.new(CitiesIndex).process(index: index) end specify do expect(CitiesIndex.client).to receive(:bulk).with(hash_including(refresh: false)) - described_class.new(CitiesIndex::City, refresh: false).process(index: index) + described_class.new(CitiesIndex, refresh: false).process(index: index) end end describe '#parallel_options' do - specify { expect(described_class.new(CitiesIndex::City).parallel_options).to be_nil } - specify { expect(described_class.new(CitiesIndex::City, parallel: true).parallel_options).to eq({}) } - specify { expect(described_class.new(CitiesIndex::City, parallel: 3).parallel_options).to eq(in_processes: 3) } + specify { expect(described_class.new(CitiesIndex).parallel_options).to be_nil } + specify { expect(described_class.new(CitiesIndex, parallel: true).parallel_options).to eq({}) } + specify { expect(described_class.new(CitiesIndex, parallel: 3).parallel_options).to eq(in_processes: 3) } specify do - expect(described_class.new(CitiesIndex::City, parallel: {in_threads: 2}).parallel_options).to eq(in_threads: 2) + expect(described_class.new(CitiesIndex, parallel: {in_threads: 2}).parallel_options).to eq(in_threads: 2) end end describe '#stats' do - subject { described_class.new(CitiesIndex::City) } + subject { described_class.new(CitiesIndex) } specify { expect(subject.stats).to eq({}) } specify do @@ -94,7 +92,7 @@ end describe '#errors' do - subject { described_class.new(CitiesIndex::City) } + subject { described_class.new(CitiesIndex) } let(:index) { [double(id: 1, name: 'Name', object: ''), double(id: 2, name: 'Name', object: {})] } specify { expect(subject.errors).to eq([]) } diff --git a/spec/chewy/type/import_spec.rb b/spec/chewy/index/import_spec.rb similarity index 78% rename from spec/chewy/type/import_spec.rb rename to spec/chewy/index/import_spec.rb index 23dbc99e3..ca7d79e89 100644 --- a/spec/chewy/type/import_spec.rb +++ b/spec/chewy/index/import_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Chewy::Type::Import do +describe Chewy::Index::Import do before { Chewy.massacre } before do @@ -9,14 +9,13 @@ before do stub_index(:cities) do - define_type City do - field :name - end + index_scope City + field :name end end def imported_cities - CitiesIndex::City.all.map do |city| + CitiesIndex.all.map do |city| city.attributes.except('_score', '_explanation') end end @@ -37,13 +36,13 @@ def subscribe_notification specify 'lazy (default)' do expect(CitiesIndex).to receive(:exists?).and_call_original expect(CitiesIndex).to receive(:create!).and_call_original - CitiesIndex::City.import(dummy_city) + CitiesIndex.import(dummy_city) end specify 'lazy without objects' do expect(CitiesIndex).not_to receive(:exists?) expect(CitiesIndex).not_to receive(:create!) - CitiesIndex::City.import([]) + CitiesIndex.import([]) end context 'skip' do @@ -58,7 +57,7 @@ def subscribe_notification specify do expect(CitiesIndex).not_to receive(:exists?) expect(CitiesIndex).not_to receive(:create!) - CitiesIndex::City.import(dummy_city) + CitiesIndex.import(dummy_city) end end end @@ -69,10 +68,10 @@ def subscribe_notification specify { expect(import(dummy_cities)).to eq(true) } specify { expect(import(dummy_cities.map(&:id))).to eq(true) } - specify { expect { import([]) }.not_to update_index(CitiesIndex::City) } - specify { expect { import }.to update_index(CitiesIndex::City).and_reindex(dummy_cities) } - specify { expect { import dummy_cities }.to update_index(CitiesIndex::City).and_reindex(dummy_cities) } - specify { expect { import dummy_cities.map(&:id) }.to update_index(CitiesIndex::City).and_reindex(dummy_cities) } + specify { expect { import([]) }.not_to update_index(CitiesIndex) } + specify { expect { import }.to update_index(CitiesIndex).and_reindex(dummy_cities) } + specify { expect { import dummy_cities }.to update_index(CitiesIndex).and_reindex(dummy_cities) } + specify { expect { import dummy_cities.map(&:id) }.to update_index(CitiesIndex).and_reindex(dummy_cities) } describe 'criteria-driven importing' do let(:names) { %w[name0 name1] } @@ -80,11 +79,11 @@ def subscribe_notification context 'active record', :active_record do specify do expect { import(City.where(name: names)) } - .to update_index(CitiesIndex::City).and_reindex(dummy_cities.first(2)) + .to update_index(CitiesIndex).and_reindex(dummy_cities.first(2)) end specify do expect { import(City.where(name: names).map(&:id)) } - .to update_index(CitiesIndex::City).and_reindex(dummy_cities.first(2)) + .to update_index(CitiesIndex).and_reindex(dummy_cities.first(2)) end end end @@ -92,13 +91,13 @@ def subscribe_notification specify do dummy_cities.first.destroy expect { import dummy_cities } - .to update_index(CitiesIndex::City).and_reindex(dummy_cities.from(1)).and_delete(dummy_cities.first) + .to update_index(CitiesIndex).and_reindex(dummy_cities.from(1)).and_delete(dummy_cities.first) end specify do dummy_cities.first.destroy expect { import dummy_cities.map(&:id) } - .to update_index(CitiesIndex::City).and_reindex(dummy_cities.from(1)).and_delete(dummy_cities.first) + .to update_index(CitiesIndex).and_reindex(dummy_cities.from(1)).and_delete(dummy_cities.first) end specify do @@ -123,7 +122,7 @@ def subscribe_notification specify do expect { import(dummy_cities, bulk_size: 1.2.kilobyte) } - .to update_index(CitiesIndex::City).and_reindex(dummy_cities) + .to update_index(CitiesIndex).and_reindex(dummy_cities) end context do @@ -139,23 +138,22 @@ def subscribe_notification criteria = {name: names} stub_index(:cities) do - define_type City.where(criteria) do - field :name - end + index_scope City.where(criteria) + field :name end end - specify { expect { import }.to update_index(CitiesIndex::City).and_reindex(dummy_cities.first(2)) } + specify { expect { import }.to update_index(CitiesIndex).and_reindex(dummy_cities.first(2)) } context 'active record', :active_record do specify do expect { import City.where(id: dummy_cities.first.id) } - .to update_index(CitiesIndex::City).and_reindex(dummy_cities.first).only + .to update_index(CitiesIndex).and_reindex(dummy_cities.first).only end specify do - allow(CitiesIndex::City).to receive(:import_linear).and_return(double(present?: false)) - allow(CitiesIndex::City).to receive(:import_parallel).and_return(double(present?: false)) + allow(CitiesIndex).to receive(:import_linear).and_return(double(present?: false)) + allow(CitiesIndex).to receive(:import_parallel).and_return(double(present?: false)) expects_no_query(except: /SELECT\s+1\s+AS\s+one\s+FROM/) do import City.where(id: dummy_cities.first.id) @@ -169,28 +167,27 @@ def subscribe_notification payload = subscribe_notification dummy_cities.first.destroy import dummy_cities - expect(payload).to eq(type: CitiesIndex::City, import: {delete: 1, index: 2}) + expect(payload).to eq(index: CitiesIndex, import: {delete: 1, index: 2}) end specify do payload = subscribe_notification dummy_cities.first.destroy import dummy_cities, batch_size: 2 - expect(payload).to eq(type: CitiesIndex::City, import: {delete: 1, index: 2}) + expect(payload).to eq(index: CitiesIndex, import: {delete: 1, index: 2}) end specify do payload = subscribe_notification import dummy_cities, batch_size: 2 - expect(payload).to eq(type: CitiesIndex::City, import: {index: 3}) + expect(payload).to eq(index: CitiesIndex, import: {index: 3}) end context do before do stub_index(:cities) do - define_type City do - field :name, type: 'object' - end + index_scope City + field :name, type: 'object' end end @@ -204,7 +201,7 @@ def subscribe_notification specify do payload = subscribe_notification import dummy_cities, batch_size: 2 - expect(payload).to eq(type: CitiesIndex::City, + expect(payload).to eq(index: CitiesIndex, errors: {index: {mapper_parsing_exception => %w[1 2 3]}}, import: {index: 3}) end @@ -212,7 +209,7 @@ def subscribe_notification end context 'fields' do - before { CitiesIndex::City.import!(dummy_cities.first(2)) } + before { CitiesIndex.import!(dummy_cities.first(2)) } context do before { expect(Chewy.client).to receive(:bulk).twice.and_call_original } @@ -220,7 +217,7 @@ def subscribe_notification end context do - before { CitiesIndex::City.import!(dummy_cities.last) } + before { CitiesIndex.import!(dummy_cities.last) } before { expect(Chewy.client).to receive(:bulk).once.and_call_original } specify { expect(import(dummy_cities, update_fields: [:name])).to eq(true) } end @@ -229,10 +226,8 @@ def subscribe_notification context 'fields integrational' do before do stub_index(:cities) do - define_type :city do - field :name - field :object, type: 'object' - end + field :name + field :object, type: 'object' end end @@ -267,7 +262,7 @@ def subscribe_notification } => %w[2 4]} }, import: {index: 6}, - type: CitiesIndex::City + index: CitiesIndex ) expect(imported_cities).to match_array([ {'id' => '1', 'name' => 'Name11', 'object' => {'foo' => 11}}, @@ -290,7 +285,7 @@ def subscribe_notification } => %w[2 4]} }, import: {index: 6}, - type: CitiesIndex::City + index: CitiesIndex ) expect(imported_cities).to match_array([ {'id' => '1', 'name' => 'Name11', 'object' => {'foo' => 11}}, @@ -300,7 +295,7 @@ def subscribe_notification end context do - before { CitiesIndex::City.import!(objects[4]) } + before { CitiesIndex.import!(objects[4]) } specify do payload = subscribe_notification @@ -316,7 +311,7 @@ def subscribe_notification } => %w[2 4]} }, import: {index: 6}, - type: CitiesIndex::City + index: CitiesIndex ) expect(imported_cities).to match_array([ {'id' => '1', 'name' => 'Name11', 'object' => {'foo' => 11}}, @@ -327,7 +322,7 @@ def subscribe_notification end context do - before { CitiesIndex::City.import!(old_objects[1], old_objects[3], objects[4]) } + before { CitiesIndex.import!(old_objects[1], old_objects[3], objects[4]) } specify do payload = subscribe_notification @@ -337,7 +332,7 @@ def subscribe_notification expect(payload).to eq( import: {index: 6}, - type: CitiesIndex::City + index: CitiesIndex ) expect(imported_cities).to match_array([ {'id' => '1', 'name' => 'Name11', 'object' => {'foo' => 11}}, @@ -356,7 +351,7 @@ def subscribe_notification expect(payload).to eq( import: {index: 6}, - type: CitiesIndex::City + index: CitiesIndex ) expect(imported_cities).to match_array([ {'id' => '1', 'name' => 'Name11', 'object' => {'foo' => 11}}, @@ -388,7 +383,7 @@ def subscribe_notification end context do - before { CitiesIndex::City.import!(old_objects) } + before { CitiesIndex.import!(old_objects) } specify do payload = subscribe_notification @@ -398,7 +393,7 @@ def subscribe_notification expect(payload).to eq( import: {index: 6}, - type: CitiesIndex::City + index: CitiesIndex ) expect(imported_cities).to match_array([ {'id' => '1', 'name' => 'Name11', 'object' => {'foo' => 1}}, @@ -412,7 +407,7 @@ def subscribe_notification end context do - before { CitiesIndex::City.import!(old_objects) } + before { CitiesIndex.import!(old_objects) } specify do payload = subscribe_notification @@ -428,7 +423,7 @@ def subscribe_notification } => %w[2 4]} }, import: {index: 6}, - type: CitiesIndex::City + index: CitiesIndex ) expect(imported_cities).to match_array([ {'id' => '1', 'name' => 'Name1', 'object' => {'foo' => 11}}, @@ -446,9 +441,8 @@ def subscribe_notification context do before do stub_index(:cities) do - define_type City do - field :name, type: 'object' - end + index_scope City + field :name, type: 'object' end end @@ -460,9 +454,8 @@ def subscribe_notification context do before do stub_index(:cities) do - define_type City do - field :name, type: 'object', value: -> { name == 'name1' ? name : {name: name} } - end + index_scope City + field :name, type: 'object', value: -> { name == 'name1' ? name : {name: name} } end end @@ -474,19 +467,19 @@ def subscribe_notification context 'default_import_options are set' do before do - CitiesIndex::City.default_import_options(batch_size: 500) + CitiesIndex.default_import_options(batch_size: 500) end specify do - expect(CitiesIndex::City.adapter).to receive(:import).with(any_args, hash_including(batch_size: 500)) - CitiesIndex::City.import + expect(CitiesIndex.adapter).to receive(:import).with(any_args, hash_including(batch_size: 500)) + CitiesIndex.import end end end describe '.import', :orm do def import(*args) - CitiesIndex::City.import(*args) + CitiesIndex.import(*args) end it_behaves_like 'importing' @@ -495,7 +488,7 @@ def import(*args) def import(*args) options = args.extract_options! options[:parallel] = 0 - CitiesIndex::City.import(*args, options) + CitiesIndex.import(*args, options) end it_behaves_like 'importing' @@ -503,54 +496,51 @@ def import(*args) end describe '.import!', :orm do - specify { expect { CitiesIndex::City.import! }.not_to raise_error } + specify { expect { CitiesIndex.import! }.not_to raise_error } context do before do stub_index(:cities) do - define_type City do - field :name, type: 'object' - end + index_scope City + field :name, type: 'object' end end - specify { expect { CitiesIndex::City.import!(dummy_cities) }.to raise_error Chewy::ImportFailed } + specify { expect { CitiesIndex.import!(dummy_cities) }.to raise_error Chewy::ImportFailed } end end describe '.compose' do before do stub_index(:cities) do - define_type :city do - crutch :names do |collection| - collection.map { |o| [o.name, "#{o.name}42"] }.to_h - end - field :name, value: ->(o, c) { c.names[o.name] } - field :rating + crutch :names do |collection| + collection.map { |o| [o.name, "#{o.name}42"] }.to_h end + field :name, value: ->(o, c) { c.names[o.name] } + field :rating end end specify do - expect(CitiesIndex::City.compose(double(name: 'Name', rating: 42))) + expect(CitiesIndex.compose(double(name: 'Name', rating: 42))) .to eq('name' => 'Name42', 'rating' => 42) end specify do - expect(CitiesIndex::City.compose(double(name: 'Name', rating: 42), fields: %i[name])) + expect(CitiesIndex.compose(double(name: 'Name', rating: 42), fields: %i[name])) .to eq('name' => 'Name42') end context 'witchcraft' do - before { CitiesIndex::City.witchcraft! } + before { CitiesIndex.witchcraft! } specify do - expect(CitiesIndex::City.compose(double(name: 'Name', rating: 42))) + expect(CitiesIndex.compose(double(name: 'Name', rating: 42))) .to eq('name' => 'Name42', 'rating' => 42) end specify do - expect(CitiesIndex::City.compose(double(name: 'Name', rating: 42), fields: %i[name])) + expect(CitiesIndex.compose(double(name: 'Name', rating: 42), fields: %i[name])) .to eq('name' => 'Name42') end end @@ -559,12 +549,12 @@ def import(*args) let(:crutches) { double(names: {'Name' => 'Name43'}) } specify do - expect(CitiesIndex::City.compose(double(name: 'Name', rating: 42), crutches)) + expect(CitiesIndex.compose(double(name: 'Name', rating: 42), crutches)) .to eq('name' => 'Name43', 'rating' => 42) end specify do - expect(CitiesIndex::City.compose(double(name: 'Name', rating: 42), crutches, fields: %i[name])) + expect(CitiesIndex.compose(double(name: 'Name', rating: 42), crutches, fields: %i[name])) .to eq('name' => 'Name43') end end diff --git a/spec/chewy/type/mapping_spec.rb b/spec/chewy/index/mapping_spec.rb similarity index 58% rename from spec/chewy/type/mapping_spec.rb rename to spec/chewy/index/mapping_spec.rb index a6ed5a633..feb1a376a 100644 --- a/spec/chewy/type/mapping_spec.rb +++ b/spec/chewy/index/mapping_spec.rb @@ -1,47 +1,41 @@ require 'spec_helper' -describe Chewy::Type::Mapping do - let(:product) { ProductsIndex::Product } - let(:review) { ReviewsIndex::Review } +describe Chewy::Index::Mapping do + let(:product) { ProductsIndex } + let(:review) { ReviewsIndex } before do stub_index(:products) do - define_type :product do - root do - field :name, 'surname' - field :title, type: 'text' do - field :subfield1 - end - field 'price', type: 'float' do - field :subfield2 - end - agg :named_agg do - {avg: {field: 'title.subfield1'}} - end + root do + field :name, 'surname' + field :title, type: 'text' do + field :subfield1 end - end - end - stub_index(:reviews) do - define_type :review do - field :title, :body - field :comments do - field :message - field :rating, type: 'long' + field 'price', type: 'float' do + field :subfield2 end agg :named_agg do - {avg: {field: 'comments.rating'}} + {avg: {field: 'title.subfield1'}} end end end + stub_index(:reviews) do + field :title, :body + field :comments do + field :message + field :rating, type: 'long' + end + agg :named_agg do + {avg: {field: 'comments.rating'}} + end + end end context 'no root element call' do before do stub_index(:products) do - define_type :product do - field :title, type: 'text' do - field :subfield1 - end + field :title, type: 'text' do + field :subfield1 end end end @@ -59,7 +53,7 @@ Chewy.default_root_options = previous_options end - specify { expect(product.mappings_hash).to include(_all: {enabled: false}) } + specify { expect(product.mappings_hash[:mappings]).to include(_all: {enabled: false}) } end end @@ -83,33 +77,33 @@ end describe '.mappings_hash' do - specify { expect(product.mappings_hash).to eq(product.root.mappings_hash) } + specify { expect(product.mappings_hash[:mappings]).to eq(product.root.mappings_hash) } context 'root merging' do context do before do stub_index(:products) do - define_type :product do - root other_option: 'nothing' do - field :name do - field :last_name # will be redefined in the following root flock - end - end - root other_option: 'option_value' do - field :identifier - field :name, type: 'integer' + root other_option: 'nothing' do + field :name do + field :last_name # will be redefined in the following root flock end end + root other_option: 'option_value' do + field :identifier + field :name, type: 'integer' + end end end specify do expect(product.mappings_hash).to eq( - properties: { - name: {type: 'integer'}, - identifier: {type: Chewy.default_field_type} - }, - other_option: 'option_value' + mappings: { + properties: { + name: {type: 'integer'}, + identifier: {type: Chewy.default_field_type} + }, + other_option: 'option_value' + } ) end end @@ -117,24 +111,22 @@ end describe '.supports_outdated_sync?' do - def type(&block) - stub_index(:cities) do - define_type :city, &block - end - CitiesIndex::City + def index(&block) + stub_index(:cities, &block) + CitiesIndex end - specify { expect(type.supports_outdated_sync?).to eq(false) } - specify { expect(type { field :updated_at }.supports_outdated_sync?).to eq(true) } - specify { expect(type { field :updated_at, value: -> {} }.supports_outdated_sync?).to eq(false) } + specify { expect(index.supports_outdated_sync?).to eq(false) } + specify { expect(index { field :updated_at }.supports_outdated_sync?).to eq(true) } + specify { expect(index { field :updated_at, value: -> {} }.supports_outdated_sync?).to eq(false) } specify do - expect(type do + expect(index do self.outdated_sync_field = :version field :updated_at end.supports_outdated_sync?).to eq(false) end specify do - expect(type do + expect(index do self.outdated_sync_field = :version field :version end.supports_outdated_sync?).to eq(true) diff --git a/spec/chewy/type/observe_spec.rb b/spec/chewy/index/observe_spec.rb similarity index 58% rename from spec/chewy/type/observe_spec.rb rename to spec/chewy/index/observe_spec.rb index 024d9fd0b..7d9671442 100644 --- a/spec/chewy/type/observe_spec.rb +++ b/spec/chewy/index/observe_spec.rb @@ -1,26 +1,24 @@ require 'spec_helper' -describe Chewy::Type::Observe do +describe Chewy::Index::Observe do describe '.update_index' do before do - stub_index(:dummies) do - define_type :dummy - end + stub_index(:dummies) end let(:backreferenced) { Array.new(3) { |i| double(id: i) } } specify do - expect { DummiesIndex::Dummy.update_index(backreferenced) } + expect { DummiesIndex.update_index(backreferenced) } .to raise_error Chewy::UndefinedUpdateStrategy end specify do - expect { DummiesIndex::Dummy.update_index([]) } - .not_to update_index('dummies#dummy') + expect { DummiesIndex.update_index([]) } + .not_to update_index('dummies') end specify do - expect { DummiesIndex::Dummy.update_index(nil) } - .not_to update_index('dummies#dummy') + expect { DummiesIndex.update_index(nil) } + .not_to update_index('dummies') end end @@ -29,13 +27,13 @@ before do stub_model(:city) do - update_index(->(city) { "cities##{city.class.name.underscore}" }) { self } - update_index('countries#country') { changes['country_id'] || previous_changes['country_id'] || country } + update_index(-> { 'cities' }, :self) + update_index('countries') { changes['country_id'] || previous_changes['country_id'] || country } end stub_model(:country) do - update_index('cities#city', if: -> { update_condition }) { cities } - update_index(-> { "countries##{self.class.name.underscore}" }, :self) + update_index('cities', if: -> { update_condition }) { cities } + update_index(-> { 'countries' }, :self) attr_accessor :update_condition end @@ -43,11 +41,11 @@ Country.has_many :cities stub_index(:cities) do - define_type City + index_scope City end stub_index(:countries) do - define_type Country + index_scope Country end end @@ -56,16 +54,16 @@ let!(:country2) { Chewy.strategy(:atomic) { Country.create!(id: 2, update_condition: update_condition) } } let!(:city) { Chewy.strategy(:atomic) { City.create!(id: 1, country: country1) } } - specify { expect { city.save! }.to update_index('cities#city').and_reindex(city).only } - specify { expect { city.save! }.to update_index('countries#country').and_reindex(country1).only } + specify { expect { city.save! }.to update_index('cities').and_reindex(city).only } + specify { expect { city.save! }.to update_index('countries').and_reindex(country1).only } - specify { expect { city.update!(country: nil) }.to update_index('cities#city').and_reindex(city).only } - specify { expect { city.update!(country: nil) }.to update_index('countries#country').and_reindex(country1).only } + specify { expect { city.update!(country: nil) }.to update_index('cities').and_reindex(city).only } + specify { expect { city.update!(country: nil) }.to update_index('countries').and_reindex(country1).only } - specify { expect { city.update!(country: country2) }.to update_index('cities#city').and_reindex(city).only } + specify { expect { city.update!(country: country2) }.to update_index('cities').and_reindex(city).only } specify do expect { city.update!(country: country2) } - .to update_index('countries#country').and_reindex(country1, country2).only + .to update_index('countries').and_reindex(country1, country2).only end end @@ -77,25 +75,25 @@ end end - specify { expect { country.save! }.to update_index('cities#city').and_reindex(country.cities).only } - specify { expect { country.save! }.to update_index('countries#country').and_reindex(country).only } + specify { expect { country.save! }.to update_index('cities').and_reindex(country.cities).only } + specify { expect { country.save! }.to update_index('countries').and_reindex(country).only } context 'conditional update' do let(:update_condition) { false } - specify { expect { country.save! }.not_to update_index('cities#city') } + specify { expect { country.save! }.not_to update_index('cities') } end end end context 'transactions', :active_record do context do - before { stub_model(:city) { update_index 'cities#city', :self } } - before { stub_index(:cities) { define_type City } } + before { stub_model(:city) { update_index 'cities', :self } } + before { stub_index(:cities) { index_scope City } } specify do Chewy.strategy(:urgent) do ActiveRecord::Base.transaction do - expect { City.create! }.not_to update_index('cities#city') + expect { City.create! }.not_to update_index('cities') end end end @@ -103,13 +101,13 @@ context do before { allow(Chewy).to receive_messages(use_after_commit_callbacks: false) } - before { stub_model(:city) { update_index 'cities#city', :self } } - before { stub_index(:cities) { define_type City } } + before { stub_model(:city) { update_index 'cities', :self } } + before { stub_index(:cities) { index_scope City } } specify do Chewy.strategy(:urgent) do ActiveRecord::Base.transaction do - expect { City.create! }.to update_index('cities#city') + expect { City.create! }.to update_index('cities') end end end diff --git a/spec/chewy/index/specification_spec.rb b/spec/chewy/index/specification_spec.rb index 07f997edf..68a34b8d5 100644 --- a/spec/chewy/index/specification_spec.rb +++ b/spec/chewy/index/specification_spec.rb @@ -5,44 +5,34 @@ let(:index1) do stub_index(:places) do - define_type(:city) do - field :founded_on, type: 'date' - end + field :founded_on, type: 'date' end end let(:index2) do stub_index(:places) do settings analyzer: {} - define_type(:city) do - field :founded_on, type: 'date' - end + field :founded_on, type: 'date' end end let(:index3) do stub_index(:places) do - define_type(:city) do - field :founded_on, type: 'date' - field :population, type: 'integer' - end + field :founded_on, type: 'date' + field :population, type: 'integer' end end let(:index4) do stub_index(:places) do - define_type(:city) do - field :population, type: 'integer' - field :founded_on, type: 'date' - end + field :population, type: 'integer' + field :founded_on, type: 'date' end end let(:index5) do stub_index('namespace/cities') do - define_type(:city) do - field :population, type: 'integer' - end + field :population, type: 'integer' end end diff --git a/spec/chewy/type/syncer_spec.rb b/spec/chewy/index/syncer_spec.rb similarity index 81% rename from spec/chewy/type/syncer_spec.rb rename to spec/chewy/index/syncer_spec.rb index d69d6bff9..e71617f04 100644 --- a/spec/chewy/type/syncer_spec.rb +++ b/spec/chewy/index/syncer_spec.rb @@ -1,36 +1,34 @@ require 'spec_helper' -describe Chewy::Type::Syncer, :orm do +describe Chewy::Index::Syncer, :orm do before { Chewy.massacre } before do stub_model(:city) stub_index(:cities) do - define_type City do - field :name - field :updated_at, type: 'date' - end + index_scope City + field :name + field :updated_at, type: 'date' end end shared_examples 'sync' do |options = {}| let!(:cities) { Array.new(3) { |i| City.create!(name: "Name#{i + 1}") } } - subject { described_class.new(CitiesIndex::City, **options) } + subject { described_class.new(CitiesIndex, **options) } describe '#perform' do - before { CitiesIndex::City.import!(cities) } + before { CitiesIndex.import!(cities) } specify { expect(subject.perform).to eq(0) } context do before do cities.first.destroy - sleep(1) if ActiveSupport::VERSION::STRING < '4.1.0' cities.last.update(name: 'Name5') end let!(:additional_city) { City.create!(name: 'Name4') } specify { expect(subject.perform).to eq(3) } specify do - expect { subject.perform }.to update_index(CitiesIndex::City) + expect { subject.perform }.to update_index(CitiesIndex) .and_reindex(additional_city, cities.last) .and_delete(cities.first).only end @@ -39,9 +37,8 @@ context 'does not support outdated sync' do before do stub_index(:cities) do - define_type City do - field :name - end + index_scope City + field :name end end @@ -56,7 +53,7 @@ specify { expect(subject.perform).to eq(2) } specify do - expect { subject.perform }.to update_index(CitiesIndex::City) + expect { subject.perform }.to update_index(CitiesIndex) .and_reindex(additional_city) .and_delete(cities.first).only end @@ -68,7 +65,7 @@ specify { expect(subject.missing_ids).to match_array(cities.map(&:id).map(&:to_s)) } context do - before { CitiesIndex::City.import!(cities) } + before { CitiesIndex.import!(cities) } specify { expect(subject.missing_ids).to eq([]) } context do @@ -83,12 +80,11 @@ specify { expect(subject.outdated_ids).to eq([]) } context do - before { CitiesIndex::City.import!(cities) } + before { CitiesIndex.import!(cities) } specify { expect(subject.outdated_ids).to eq([]) } context do before do - sleep(1) if ActiveSupport::VERSION::STRING < '4.1.0' cities.first.update(name: 'Name4') cities.last.update(name: 'Name5') end @@ -99,9 +95,8 @@ context 'does not support outdated sync' do before do stub_index(:cities) do - define_type City do - field :name - end + index_scope City + field :name end end diff --git a/spec/chewy/type/witchcraft_spec.rb b/spec/chewy/index/witchcraft_spec.rb similarity index 78% rename from spec/chewy/type/witchcraft_spec.rb rename to spec/chewy/index/witchcraft_spec.rb index aa8ac1d5a..0d4a28c4d 100644 --- a/spec/chewy/type/witchcraft_spec.rb +++ b/spec/chewy/index/witchcraft_spec.rb @@ -1,25 +1,23 @@ require 'spec_helper' -describe Chewy::Type::Witchcraft do +describe Chewy::Index::Witchcraft do def self.mapping(&block) before do stub_index(:products) do - define_type :product do - witchcraft! + witchcraft! - instance_exec(&block) - end + instance_exec(&block) end end end describe '#cauldron' do - let(:type) { ProductsIndex::Product } + let(:index) { ProductsIndex } let(:object) {} context 'empty mapping' do mapping {} - specify { expect(type.cauldron.brew(object)).to eq({}) } + specify { expect(index.cauldron.brew(object)).to eq({}) } end context do @@ -32,18 +30,18 @@ def self.mapping(&block) context do let(:object) { double(attributes) } - specify { expect(type.cauldron.brew(object)).to eq(attributes.as_json) } + specify { expect(index.cauldron.brew(object)).to eq(attributes.as_json) } end context do let(:object) { attributes } - specify { expect(type.cauldron.brew(object)).to eq(attributes.as_json) } + specify { expect(index.cauldron.brew(object)).to eq(attributes.as_json) } end context do let(:object) { double(attributes) } specify do - expect(type.cauldron(fields: %i[name tags]).brew(object)) + expect(index.cauldron(fields: %i[name tags]).brew(object)) .to eq('name' => 'Name', 'tags' => %w[Ruby RoR]) end end @@ -51,7 +49,7 @@ def self.mapping(&block) context do let(:object) { attributes } specify do - expect(type.cauldron(fields: %i[name tags]).brew(object)) + expect(index.cauldron(fields: %i[name tags]).brew(object)) .to eq('name' => 'Name', 'tags' => %w[Ruby RoR]) end end @@ -69,7 +67,7 @@ def self.mapping(&block) context do let(:object) { double(attributes) } - specify { expect(type.cauldron.brew(object)).to eq(attributes.merge(tags: %i[Ruby RoR]).as_json) } + specify { expect(index.cauldron.brew(object)).to eq(attributes.merge(tags: %i[Ruby RoR]).as_json) } end end @@ -82,7 +80,7 @@ def self.mapping(&block) context do let(:object) { double(attributes) } let(:crutches) { double(names: ['Other']) } - specify { expect(type.cauldron.brew(object, crutches)).to eq({name: 'Other'}.as_json) } + specify { expect(index.cauldron.brew(object, crutches)).to eq({name: 'Other'}.as_json) } end end @@ -102,7 +100,7 @@ def self.mapping(&block) ]) end specify do - expect(type.cauldron.brew(object)).to eq({queries: [ + expect(index.cauldron.brew(object)).to eq({queries: [ {title: 'Title1', body: 'This Body1'}, {title: 'Title2', body: 'This Body2'} ]}.as_json) @@ -124,7 +122,7 @@ def self.mapping(&block) ]) end specify do - expect(type.cauldron.brew(object)).to eq({queries: [ + expect(index.cauldron.brew(object)).to eq({queries: [ {title: 'Title1', body: 'This Body1'}, {title: 'Title2', body: 'This Body2'} ]}.as_json) @@ -146,7 +144,7 @@ def self.mapping(&block) ]) end specify do - expect(type.cauldron.brew(object)).to eq({queries: [ + expect(index.cauldron.brew(object)).to eq({queries: [ {title: 'Title1', body: 'This Body1'}, {title: 'Title2', body: 'This Body2'} ]}.as_json) @@ -172,7 +170,7 @@ def self.mapping(&block) ]) end specify do - expect(type.cauldron.brew(object, double(second: 'Crutch'))).to eq({queries: [ + expect(index.cauldron.brew(object, double(second: 'Crutch'))).to eq({queries: [ {fields: [ {first: 'First1', second: 'Value1Second1'}, {first: 'First2', second: 'Value1Crutch'} @@ -193,7 +191,7 @@ def self.mapping(&block) double(not_present: nil) end specify do - expect(type.cauldron.brew(object)).to eq({not_present: nil}.as_json) + expect(index.cauldron.brew(object)).to eq({not_present: nil}.as_json) end end end @@ -208,7 +206,7 @@ def self.mapping(&block) context do let(:object) { double(attributes) } - specify { expect(type.cauldron.brew(object)).to eq(attributes.as_json) } + specify { expect(index.cauldron.brew(object)).to eq(attributes.as_json) } end end @@ -224,7 +222,7 @@ def self.custom_value(field) context do let(:object) { double(attributes) } - specify { expect(type.cauldron.brew(object)).to eq(attributes.as_json) } + specify { expect(index.cauldron.brew(object)).to eq(attributes.as_json) } end end @@ -235,12 +233,12 @@ def self.custom_value(field) context do let(:object) { double(last_name: 'Name') } - specify { expect(type.cauldron.brew(object)).to eq({name: 'Name'}.as_json) } + specify { expect(index.cauldron.brew(object)).to eq({name: 'Name'}.as_json) } end context do let(:object) { {'last_name' => 'Name'} } - specify { expect(type.cauldron.brew(object)).to eq({name: 'Name'}.as_json) } + specify { expect(index.cauldron.brew(object)).to eq({name: 'Name'}.as_json) } end end end diff --git a/spec/chewy/index/wrapper_spec.rb b/spec/chewy/index/wrapper_spec.rb new file mode 100644 index 000000000..d8db65896 --- /dev/null +++ b/spec/chewy/index/wrapper_spec.rb @@ -0,0 +1,100 @@ +require 'spec_helper' + +describe Chewy::Index::Wrapper do + before do + stub_class(:city) + stub_index(:cities) do + index_scope City + end + end + + let(:cities_index) { CitiesIndex } + + describe '.build' do + specify do + expect(cities_index.build({}).attributes) + .to eq('id' => nil, '_score' => nil, '_explanation' => nil) + end + specify do + expect(cities_index.build('_source' => {name: 'Martin'}).attributes) + .to eq('id' => nil, '_score' => nil, '_explanation' => nil, 'name' => 'Martin') + end + specify do + expect(cities_index.build('_id' => 42).attributes) + .to eq('id' => 42, '_score' => nil, '_explanation' => nil) + end + specify do + expect(cities_index.build('_id' => 42, '_source' => {'id' => 43}).attributes) + .to eq('id' => 43, '_score' => nil, '_explanation' => nil) + end + specify do + expect(cities_index.build('_score' => 42, '_explanation' => {foo: 'bar'}).attributes) + .to eq('id' => nil, '_score' => 42, '_explanation' => {foo: 'bar'}) + end + specify do + expect(cities_index.build('_score' => 42, 'borogoves' => {foo: 'bar'})._data) + .to eq('_score' => 42, 'borogoves' => {foo: 'bar'}) + end + end + + describe '#initialize' do + subject(:city) { cities_index.new(name: 'Martin', age: 42) } + + it do + is_expected.to respond_to(:name) + .and respond_to(:age) + .and have_attributes( + name: 'Martin', + age: 42 + ) + end + + it { expect { city.population }.to raise_error(NoMethodError) } + + context 'highlight' do + subject(:city) do + cities_index.new(name: 'Martin', age: 42) + .tap do |city| + city._data = { + 'highlight' => {'name' => ['Martin']} + } + end + end + + it do + is_expected.to respond_to(:name_highlight) + .and respond_to(:name_highlights) + .and have_attributes( + name: 'Martin', + name_highlight: 'Martin', + name_highlights: ['Martin'] + ) + end + end + end + + describe '#==' do + specify { expect(cities_index.new(id: 42)).to eq(cities_index.new(id: 42)) } + specify { expect(cities_index.new(id: 42, age: 55)).to eq(cities_index.new(id: 42, age: 54)) } + specify { expect(cities_index.new(id: 42)).not_to eq(cities_index.new(id: 43)) } + specify { expect(cities_index.new(id: 42, age: 55)).not_to eq(cities_index.new(id: 43, age: 55)) } + specify { expect(cities_index.new(age: 55)).to eq(cities_index.new(age: 55)) } + specify { expect(cities_index.new(age: 55)).not_to eq(cities_index.new(age: 54)) } + + specify { expect(cities_index.new(id: '42')).to eq(City.new.tap { |m| allow(m).to receive_messages(id: 42) }) } + specify { expect(cities_index.new(id: 42)).not_to eq(City.new.tap { |m| allow(m).to receive_messages(id: 43) }) } + specify { expect(cities_index.new(id: 42)).not_to eq(Class.new) } + + context 'models', :orm do + before do + stub_model(:city) + stub_index(:cities) do + index_scope City + end + end + specify { expect(cities_index.new(id: '42')).to eq(City.new.tap { |m| allow(m).to receive_messages(id: 42) }) } + specify { expect(cities_index.new(id: 42)).not_to eq(City.new.tap { |m| allow(m).to receive_messages(id: 43) }) } + specify { expect(cities_index.new(id: 42)).not_to eq(Class.new) } + end + end +end diff --git a/spec/chewy/index_spec.rb b/spec/chewy/index_spec.rb index 7b6f7a457..64ce10a12 100644 --- a/spec/chewy/index_spec.rb +++ b/spec/chewy/index_spec.rb @@ -2,9 +2,7 @@ describe Chewy::Index do before do - stub_index(:dummies) do - define_type :dummy - end + stub_index(:dummies) end describe '.import', :orm do @@ -13,11 +11,11 @@ stub_model(:country) stub_index(:cities) do - define_type City + index_scope City end stub_index(:countries) do - define_type Country + index_scope Country end end @@ -30,20 +28,13 @@ end specify do - expect { CitiesIndex.import city: cities.first }.to update_index(CitiesIndex).and_reindex(cities.first).only - expect { CountriesIndex.import city: cities.first }.to update_index(CountriesIndex).and_reindex(countries) - end - - specify do - expect { CitiesIndex.import city: cities.first, country: countries.last } - .to update_index(CitiesIndex).and_reindex(cities.first).only - expect { CountriesIndex.import city: cities.first, country: countries.last } - .to update_index(CountriesIndex).and_reindex(countries.last).only + expect { CitiesIndex.import cities.first }.to update_index(CitiesIndex).and_reindex(cities.first).only + expect { CountriesIndex.import countries.last }.to update_index(CountriesIndex).and_reindex(countries.last).only end specify do expect(CitiesIndex.client).to receive(:bulk).with(hash_including(refresh: false)).once - CitiesIndex.import city: cities.first, refresh: false + CitiesIndex.import cities.first, refresh: false end end @@ -98,19 +89,19 @@ specify { expect(Class.new(Chewy::Index).prefix).to eq('testing') } end - describe '.define_type' do - specify { expect(DummiesIndex.type_hash['dummy']).to eq(DummiesIndex::Dummy) } - - context do - before { stub_index(:dummies) { define_type :dummy, name: :borogoves } } - specify { expect(DummiesIndex.type_hash['borogoves']).to eq(DummiesIndex::Borogoves) } - end - - context do - before { stub_class(:city) } - before { stub_index(:dummies) { define_type City, name: :country } } - specify { expect(DummiesIndex.type_hash['country']).to eq(DummiesIndex::Country) } - end + describe '.index_scope' do + # specify { expect(DummiesIndex.type_hash['dummy']).to eq(DummiesIndex::Dummy) } + # + # context do + # before { stub_index(:dummies) { index_scope :dummy, name: :borogoves } } + # specify { expect(DummiesIndex.type_hash['borogoves']).to eq(DummiesIndex::Borogoves) } + # end + # + # context do + # before { stub_class(:city) } + # before { stub_index(:dummies) { index_scope City, name: :country } } + # specify { expect(DummiesIndex.type_hash['country']).to eq(DummiesIndex::Country) } + # end context do before { stub_class('City') } @@ -120,16 +111,16 @@ expect do Kernel.eval <<-DUMMY_CITY_INDEX class DummyCityIndex2 < Chewy::Index - define_type City - define_type Country + index_scope City + index_scope Country end DUMMY_CITY_INDEX - end.to raise_error(/Multiple types are deprecated/) + end.to raise_error(/Index scope is already defined/) expect do Kernel.eval <<-DUMMY_CITY_INDEX class DummyCityIndex2 < Chewy::Index - define_type City::Nothing + index_scope City::Nothing end DUMMY_CITY_INDEX end.to raise_error(NameError) @@ -137,23 +128,23 @@ class DummyCityIndex2 < Chewy::Index end end - describe '.type_hash' do - specify { expect(DummiesIndex.type_hash['dummy']).to eq(DummiesIndex::Dummy) } - specify { expect(DummiesIndex.type_hash).to have_key 'dummy' } - specify { expect(DummiesIndex.type_hash['dummy']).to be < Chewy::Type } - specify { expect(DummiesIndex.type_hash['dummy'].type_name).to eq('dummy') } - end - - describe '.type' do - specify { expect(DummiesIndex.type('dummy')).to eq(DummiesIndex::Dummy) } - specify { expect { DummiesIndex.type('not-the-dummy') }.to raise_error(Chewy::UndefinedType) } - end - - specify { expect(DummiesIndex.type_names).to eq(DummiesIndex.type_hash.keys) } - - describe '.types' do - specify { expect(DummiesIndex.types).to eq(DummiesIndex.type_hash.values) } - end + # describe '.type_hash' do + # specify { expect(DummiesIndex.type_hash['dummy']).to eq(DummiesIndex::Dummy) } + # specify { expect(DummiesIndex.type_hash).to have_key 'dummy' } + # specify { expect(DummiesIndex.type_hash['dummy']).to be < Chewy::Type } + # specify { expect(DummiesIndex.type_hash['dummy'].type_name).to eq('dummy') } + # end + # + # describe '.type' do + # specify { expect(DummiesIndex.type('dummy')).to eq(DummiesIndex::Dummy) } + # specify { expect { DummiesIndex.type('not-the-dummy') }.to raise_error(Chewy::UndefinedType) } + # end + + # specify { expect(DummiesIndex.type_names).to eq(DummiesIndex.type_hash.keys) } + # + # describe '.types' do + # specify { expect(DummiesIndex.types).to eq(DummiesIndex.type_hash.values) } + # end describe '.settings' do before do @@ -194,20 +185,18 @@ def self.colors(*colors) filter(terms: {colors: colors.flatten(1).map(&:to_s)}) end - define_type :city do - def self.by_id; end - field :colors - end + def self.by_id; end + field :colors end end specify { expect(described_class.scopes).to eq([]) } - specify { expect(PlacesIndex.scopes).to match_array(%i[by_rating colors]) } + specify { expect(PlacesIndex.scopes).to match_array(%i[by_rating colors by_id]) } context do before do Chewy.massacre - PlacesIndex::City.import!( + PlacesIndex.import!( double(colors: ['red']), double(colors: %w[red green]), double(colors: %w[green yellow]) @@ -215,16 +204,12 @@ def self.by_id; end end specify do - # This `blank?`` call is for the messed scopes bug reproduction. See #573 - PlacesIndex::City.blank? expect(PlacesIndex.colors(:green).map(&:colors)) .to contain_exactly(%w[red green], %w[green yellow]) end specify do - # This `blank?` call is for the messed scopes bug reproduction. See #573 - PlacesIndex::City.blank? - expect(PlacesIndex::City.colors(:green).map(&:colors)) + expect(PlacesIndex.colors(:green).map(&:colors)) .to contain_exactly(%w[red green], %w[green yellow]) end end @@ -243,12 +228,10 @@ def self.by_id; end describe '.mappings_hash' do specify { expect(stub_index(:documents).mappings_hash).to eq({}) } - specify { expect(stub_index(:documents) { define_type :document }.mappings_hash).to eq({}) } + specify { expect(stub_index(:documents) { index_scope :document }.mappings_hash).to eq({}) } specify do expect(stub_index(:documents) do - define_type :document do - field :date, type: 'date' - end + field :date, type: 'date' end.mappings_hash).to eq(mappings: {properties: {date: {type: 'date'}}}) end end @@ -264,17 +247,13 @@ def self.by_id; end end specify do expect(stub_index(:documents) do - define_type :document do - field :name - end + field :name end.specification_hash.keys).to eq([:mappings]) end specify do expect(stub_index(:documents) do settings number_of_shards: 1 - define_type :document do - field :name - end + field :name end.specification_hash.keys).to match_array(%i[mappings settings]) end end @@ -288,25 +267,21 @@ def self.by_id; end context 'index call inside index', :orm do before do stub_index(:cities) do - define_type :city do - field :country_name, value: (lambda do |city| - CountriesIndex::Country.filter(term: {_id: city.country_id}).first.name - end) - end + field :country_name, value: (lambda do |city| + CountriesIndex.filter(term: {_id: city.country_id}).first.name + end) end stub_index(:countries) do - define_type :country do - field :name - end + field :name end - CountriesIndex::Country.import!(double(id: 1, name: 'Country')) + CountriesIndex.import!(double(id: 1, name: 'Country')) end specify do - expect { CitiesIndex::City.import!(double(country_id: 1)) } - .to update_index(CitiesIndex::City).and_reindex(country_name: 'Country') + expect { CitiesIndex.import!(double(country_id: 1)) } + .to update_index(CitiesIndex).and_reindex(country_name: 'Country') end end end diff --git a/spec/chewy/journal_spec.rb b/spec/chewy/journal_spec.rb index abae9fa6b..95b618cc7 100644 --- a/spec/chewy/journal_spec.rb +++ b/spec/chewy/journal_spec.rb @@ -13,14 +13,12 @@ end stub_index("#{namespace}cities") do - define_type City do - default_import_options journal: true - end + index_scope City + default_import_options journal: true end stub_index("#{namespace}countries") do - define_type Country do - default_import_options journal: true - end + index_scope Country + default_import_options journal: true end Chewy.massacre @@ -67,63 +65,54 @@ def timestamp(time) expected_journal = [ { 'index_name' => "#{namespace}cities", - 'type_name' => 'city', 'action' => 'index', 'references' => ['1'].map(&Base64.method(:encode64)), 'created_at' => time.utc.as_json }, { 'index_name' => "#{namespace}cities", - 'type_name' => 'city', 'action' => 'index', 'references' => ['2'].map(&Base64.method(:encode64)), 'created_at' => time.utc.as_json }, { 'index_name' => "#{namespace}countries", - 'type_name' => 'country', 'action' => 'index', 'references' => ['1'].map(&Base64.method(:encode64)), 'created_at' => time.utc.as_json }, { 'index_name' => "#{namespace}countries", - 'type_name' => 'country', 'action' => 'index', 'references' => ['2'].map(&Base64.method(:encode64)), 'created_at' => time.utc.as_json }, { 'index_name' => "#{namespace}countries", - 'type_name' => 'country', 'action' => 'index', 'references' => ['3'].map(&Base64.method(:encode64)), 'created_at' => time.utc.as_json }, { 'index_name' => "#{namespace}cities", - 'type_name' => 'city', 'action' => 'index', 'references' => %w[1 2].map(&Base64.method(:encode64)), 'created_at' => import_time.utc.as_json }, { 'index_name' => "#{namespace}countries", - 'type_name' => 'country', 'action' => 'index', 'references' => %w[1 2 3].map(&Base64.method(:encode64)), 'created_at' => import_time.utc.as_json }, { 'index_name' => "#{namespace}cities", - 'type_name' => 'city', 'action' => 'index', 'references' => ['1'].map(&Base64.method(:encode64)), 'created_at' => update_time.utc.as_json }, { 'index_name' => "#{namespace}countries", - 'type_name' => 'country', 'action' => 'delete', 'references' => ['2'].map(&Base64.method(:encode64)), 'created_at' => destroy_time.utc.as_json @@ -166,14 +155,12 @@ def timestamp(time) end stub_index(:cities) do - define_type City do - default_import_options journal: true - end + index_scope City + default_import_options journal: true end stub_index(:countries) do - define_type Country do - default_import_options journal: true - end + index_scope Country + default_import_options journal: true end end @@ -235,7 +222,7 @@ def timestamp(time) let!(:journal_entries) do record = Chewy::Stash::Journal.entries(time).first Array.new(count_of_checks) do |i| - Chewy::Stash::Journal::Journal.new( + Chewy::Stash::Journal.new( record.attributes.merge( 'created_at' => time.to_i + i, 'references' => [i.to_s] diff --git a/spec/chewy/minitest/helpers_spec.rb b/spec/chewy/minitest/helpers_spec.rb index 6a65d56c8..59bc2b90f 100644 --- a/spec/chewy/minitest/helpers_spec.rb +++ b/spec/chewy/minitest/helpers_spec.rb @@ -18,54 +18,52 @@ def assert_includes(haystack, needle, _comment) before do stub_index(:dummies) do - define_type :dummy do - root value: ->(_o) { {} } - end + root value: ->(_o) { {} } end end context 'assert_indexes' do specify 'doesn\'t fail when index updates correctly' do expect do - assert_indexes DummiesIndex::Dummy do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] + assert_indexes DummiesIndex do + DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] end end.to_not raise_error end specify 'fails when index doesn\'t update' do expect do - assert_indexes DummiesIndex::Dummy do + assert_indexes DummiesIndex do end end.to raise_error(RSpec::Expectations::ExpectationNotMetError) end specify 'SearchIndexReceiver catches the indexes' do - receiver = assert_indexes DummiesIndex::Dummy do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] + receiver = assert_indexes DummiesIndex do + DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] end expect(receiver).to be_a(SearchIndexReceiver) expect( - receiver.indexes_for(DummiesIndex::Dummy) + receiver.indexes_for(DummiesIndex) .map { |index| index[:_id] } ).to match_array([41, 42]) end specify 'Real index is bypassed when asserting' do - expect(DummiesIndex::Dummy).not_to receive(:bulk) + expect(DummiesIndex).not_to receive(:bulk) - assert_indexes DummiesIndex::Dummy do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] + assert_indexes DummiesIndex do + DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] end end specify 'Real index is allowed when asserting' do - expect(DummiesIndex::Dummy).to receive(:bulk) + expect(DummiesIndex).to receive(:bulk) - assert_indexes DummiesIndex::Dummy, bypass_actual_index: false do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] + assert_indexes DummiesIndex, bypass_actual_index: false do + DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] end end end diff --git a/spec/chewy/minitest/search_index_receiver_spec.rb b/spec/chewy/minitest/search_index_receiver_spec.rb index 180f109a4..213d46de8 100644 --- a/spec/chewy/minitest/search_index_receiver_spec.rb +++ b/spec/chewy/minitest/search_index_receiver_spec.rb @@ -26,97 +26,93 @@ def parse_request(request) before do stub_index(:dummies) do - define_type :fizz do - root value: ->(_o) { {} } - end + root value: ->(_o) { {} } end stub_index(:dummies2) do - define_type :buzz do - root value: ->(_o) { {} } - end + root value: ->(_o) { {} } end end context 'catch' do specify 'archives more than one type' do - receiver.catch search_request(2), DummiesIndex::Fizz - receiver.catch search_request(3), Dummies2Index::Buzz - expect(receiver.indexes.keys).to match_array([DummiesIndex::Fizz, Dummies2Index::Buzz]) + receiver.catch search_request(2), DummiesIndex + receiver.catch search_request(3), Dummies2Index + expect(receiver.indexes.keys).to match_array([DummiesIndex, Dummies2Index]) end end context 'indexes_for' do before do - receiver.catch search_request(2), DummiesIndex::Fizz - receiver.catch search_request(3), Dummies2Index::Buzz + receiver.catch search_request(2), DummiesIndex + receiver.catch search_request(3), Dummies2Index end specify 'returns indexes for a specific type' do - expect(parse_request(receiver.indexes_for(DummiesIndex::Fizz))).to match_array([1, 2]) + expect(parse_request(receiver.indexes_for(DummiesIndex))).to match_array([1, 2]) end specify 'returns only indexes for all types' do index_responses = receiver.indexes - expect(index_responses.keys).to match_array([DummiesIndex::Fizz, Dummies2Index::Buzz]) + expect(index_responses.keys).to match_array([DummiesIndex, Dummies2Index]) expect(parse_request(index_responses.values.flatten)).to match_array([1, 2, 1, 2, 3]) end end context 'deletes_for' do before do - receiver.catch search_request(2, verb: :delete), DummiesIndex::Fizz - receiver.catch search_request(3, verb: :delete), Dummies2Index::Buzz + receiver.catch search_request(2, verb: :delete), DummiesIndex + receiver.catch search_request(3, verb: :delete), Dummies2Index end specify 'returns deletes for a specific type' do - expect(receiver.deletes_for(Dummies2Index::Buzz)).to match_array([1, 2, 3]) + expect(receiver.deletes_for(Dummies2Index)).to match_array([1, 2, 3]) end specify 'returns only deletes for all types' do deletes = receiver.deletes - expect(deletes.keys).to match_array([DummiesIndex::Fizz, Dummies2Index::Buzz]) + expect(deletes.keys).to match_array([DummiesIndex, Dummies2Index]) expect(deletes.values.flatten).to match_array([1, 2, 1, 2, 3]) end end context 'indexed?' do before do - receiver.catch search_request(1), DummiesIndex::Fizz + receiver.catch search_request(1), DummiesIndex end specify 'validates that an object was indexed' do dummy = OpenStruct.new(id: 1) - expect(receiver.indexed?(dummy, DummiesIndex::Fizz)).to be(true) + expect(receiver.indexed?(dummy, DummiesIndex)).to be(true) end specify 'doesn\'t validate than unindexed objects were indexed' do dummy = OpenStruct.new(id: 2) - expect(receiver.indexed?(dummy, DummiesIndex::Fizz)).to be(false) + expect(receiver.indexed?(dummy, DummiesIndex)).to be(false) end end context 'deleted?' do before do - receiver.catch search_request(1, verb: :delete), DummiesIndex::Fizz + receiver.catch search_request(1, verb: :delete), DummiesIndex end specify 'validates than an object was deleted' do dummy = OpenStruct.new(id: 1) - expect(receiver.deleted?(dummy, DummiesIndex::Fizz)).to be(true) + expect(receiver.deleted?(dummy, DummiesIndex)).to be(true) end specify 'doesn\'t validate than undeleted objects were deleted' do dummy = OpenStruct.new(id: 2) - expect(receiver.deleted?(dummy, DummiesIndex::Fizz)).to be(false) + expect(receiver.deleted?(dummy, DummiesIndex)).to be(false) end end context 'updated_indexes' do specify 'provides a list of indices updated' do - receiver.catch search_request(2, verb: :delete), DummiesIndex::Fizz - receiver.catch search_request(3, verb: :delete), Dummies2Index::Buzz - expect(receiver.updated_indexes).to match_array([DummiesIndex::Fizz, Dummies2Index::Buzz]) + receiver.catch search_request(2, verb: :delete), DummiesIndex + receiver.catch search_request(3, verb: :delete), Dummies2Index + expect(receiver.updated_indexes).to match_array([DummiesIndex, Dummies2Index]) end end end diff --git a/spec/chewy/multi_search_spec.rb b/spec/chewy/multi_search_spec.rb index ea82eb601..8ca1e2cd2 100644 --- a/spec/chewy/multi_search_spec.rb +++ b/spec/chewy/multi_search_spec.rb @@ -13,10 +13,9 @@ def self.aggregate_by_country aggs(country: {terms: {field: :country_id}}) end - define_type City do - field :name, type: 'keyword' - field :country_id, type: 'keyword' - end + index_scope City + field :name, type: 'keyword' + field :country_id, type: 'keyword' end end @@ -78,7 +77,7 @@ def self.aggregate_by_country is_expected.to have(2).responses expect(responses[0]).to be_a(Chewy::Search::Response) expect(responses[1]).to be_a(Chewy::Search::Response) - expect(responses[1].wrappers).to all(be_a CitiesIndex::City) + expect(responses[1].wrappers).to all(be_a CitiesIndex) end end end diff --git a/spec/chewy/rake_helper_spec.rb b/spec/chewy/rake_helper_spec.rb index 19b471557..97b5c9c25 100644 --- a/spec/chewy/rake_helper_spec.rb +++ b/spec/chewy/rake_helper_spec.rb @@ -8,13 +8,12 @@ stub_model(:country) stub_index(:cities) do - define_type City do - field :name - field :updated_at, type: 'date' - end + index_scope City + field :name + field :updated_at, type: 'date' end stub_index(:countries) do - define_type Country + index_scope Country end stub_index(:users) @@ -52,17 +51,18 @@ .to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\AResetting CitiesIndex - Imported CitiesIndex::City in \\d+s, stats: index 3 - Applying journal to \\[CitiesIndex::City\\], 2 entries, stage 1 - Imported CitiesIndex::City in \\d+s, stats: index 2 - Imported Chewy::Stash::Specification::Specification in \\d+s, stats: index 1 + Imported CitiesIndex in \\d+s, stats: index 3 + Applying journal to \\[CitiesIndex\\], 2 entries, stage 1 + Imported CitiesIndex in \\d+s, stats: index 2 + Imported Chewy::Stash::Specification in \\d+s, stats: index 1 Resetting CountriesIndex - Imported CountriesIndex::Country in \\d+s, stats: index 2 - Applying journal to \\[CountriesIndex::Country\\], 1 entries, stage 1 - Imported CountriesIndex::Country in \\d+s, stats: index 1 - Imported Chewy::Stash::Specification::Specification in \\d+s, stats: index 1 + Imported CountriesIndex in \\d+s, stats: index 2 + Applying journal to \\[CountriesIndex\\], 1 entries, stage 1 + Imported CountriesIndex in \\d+s, stats: index 1 + Imported Chewy::Stash::Specification in \\d+s, stats: index 1 Resetting UsersIndex - Imported Chewy::Stash::Specification::Specification in \\d+s, stats: index 1 + Imported UsersIndex in 1s, stats:\s + Imported Chewy::Stash::Specification in \\d+s, stats: index 1 Total: \\d+s\\Z OUTPUT end @@ -73,10 +73,10 @@ .to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\AResetting CitiesIndex - Imported CitiesIndex::City in \\d+s, stats: index 3 - Applying journal to \\[CitiesIndex::City\\], 2 entries, stage 1 - Imported CitiesIndex::City in \\d+s, stats: index 2 - Imported Chewy::Stash::Specification::Specification in \\d+s, stats: index 1 + Imported CitiesIndex in \\d+s, stats: index 3 + Applying journal to \\[CitiesIndex\\], 2 entries, stage 1 + Imported CitiesIndex in \\d+s, stats: index 2 + Imported Chewy::Stash::Specification in \\d+s, stats: index 1 Total: \\d+s\\Z OUTPUT end @@ -87,7 +87,8 @@ .not_to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\AResetting UsersIndex - Imported Chewy::Stash::Specification::Specification in \\d+s, stats: index 1 + Imported UsersIndex in 1s, stats:\s + Imported Chewy::Stash::Specification in \\d+s, stats: index 1 Total: \\d+s\\Z OUTPUT end @@ -100,13 +101,14 @@ .to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\AResetting CitiesIndex - Imported CitiesIndex::City in \\d+s, stats: index 3 - Imported Chewy::Stash::Specification::Specification in \\d+s, stats: index 1 + Imported CitiesIndex in \\d+s, stats: index 3 + Imported Chewy::Stash::Specification in \\d+s, stats: index 1 Resetting CountriesIndex - Imported CountriesIndex::Country in \\d+s, stats: index 2 - Imported Chewy::Stash::Specification::Specification in \\d+s, stats: index 1 + Imported CountriesIndex in \\d+s, stats: index 2 + Imported Chewy::Stash::Specification in \\d+s, stats: index 1 Resetting UsersIndex - Imported Chewy::Stash::Specification::Specification in \\d+s, stats: index 1 + Imported UsersIndex in 1s, stats:\s + Imported Chewy::Stash::Specification in \\d+s, stats: index 1 Total: \\d+s\\Z OUTPUT end @@ -125,7 +127,8 @@ \\ASkipping CitiesIndex, the specification didn't change Skipping CountriesIndex, the specification didn't change Resetting UsersIndex - Imported Chewy::Stash::Specification::Specification in \\d+s, stats: index 1 + Imported UsersIndex in 1s, stats:\s + Imported Chewy::Stash::Specification in \\d+s, stats: index 1 Total: \\d+s\\Z OUTPUT end @@ -136,7 +139,8 @@ .not_to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\AResetting UsersIndex - Imported Chewy::Stash::Specification::Specification in \\d+s, stats: index 1 + Imported UsersIndex in 1s, stats:\s + Imported Chewy::Stash::Specification in \\d+s, stats: index 1 Total: \\d+s\\Z OUTPUT end @@ -165,6 +169,7 @@ expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\ASkipping CitiesIndex, it does not exists \\(use rake chewy:reset\\[cities\\] to create and update it\\) Skipping CountriesIndex, it does not exists \\(use rake chewy:reset\\[countries\\] to create and update it\\) +Skipping UsersIndex, it does not exists \\(use rake chewy:reset\\[users\\] to create and update it\\) Total: \\d+s\\Z OUTPUT end @@ -181,9 +186,10 @@ .to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\AUpdating CitiesIndex - Imported CitiesIndex::City in \\d+s, stats: index 3 + Imported CitiesIndex in \\d+s, stats: index 3 Updating CountriesIndex - Imported CountriesIndex::Country in \\d+s, stats: index 2 + Imported CountriesIndex in \\d+s, stats: index 2 +Skipping UsersIndex, it does not exists \\(use rake chewy:reset\\[users\\] to create and update it\\) Total: \\d+s\\Z OUTPUT end @@ -194,7 +200,7 @@ .not_to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\AUpdating CountriesIndex - Imported CountriesIndex::Country in \\d+s, stats: index 2 + Imported CountriesIndex in \\d+s, stats: index 2 Total: \\d+s\\Z OUTPUT end @@ -205,7 +211,8 @@ .to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\AUpdating CitiesIndex - Imported CitiesIndex::City in \\d+s, stats: index 3 + Imported CitiesIndex in \\d+s, stats: index 3 +Skipping UsersIndex, it does not exists \\(use rake chewy:reset\\[users\\] to create and update it\\) Total: \\d+s\\Z OUTPUT end @@ -218,15 +225,19 @@ expect { described_class.sync(output: output) } .to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) -\\ASynchronizing CitiesIndex::City - Imported CitiesIndex::City in \\d+s, stats: index 3 +\\ASynchronizing CitiesIndex + Imported CitiesIndex in \\d+s, stats: index 3 Missing documents: \\[[^\\]]+\\] Took \\d+s -Synchronizing CountriesIndex::Country - CountriesIndex::Country doesn't support outdated synchronization - Imported CountriesIndex::Country in \\d+s, stats: index 2 +Synchronizing CountriesIndex + CountriesIndex doesn't support outdated synchronization + Imported CountriesIndex in \\d+s, stats: index 2 Missing documents: \\[[^\\]]+\\] Took \\d+s +Synchronizing UsersIndex + UsersIndex doesn't support outdated synchronization + Skipping UsersIndex, up to date + Took \\d+s Total: \\d+s\\Z OUTPUT end @@ -236,7 +247,6 @@ CitiesIndex.import(cities.first(2)) CountriesIndex.import - sleep(1) if ActiveSupport::VERSION::STRING < '4.1.0' cities.first.update(name: 'Name5') end @@ -245,14 +255,18 @@ expect { described_class.sync(output: output) } .to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) -\\ASynchronizing CitiesIndex::City - Imported CitiesIndex::City in \\d+s, stats: index 2 +\\ASynchronizing CitiesIndex + Imported CitiesIndex in \\d+s, stats: index 2 Missing documents: \\["#{cities.last.id}"\\] Outdated documents: \\["#{cities.first.id}"\\] Took \\d+s -Synchronizing CountriesIndex::Country - CountriesIndex::Country doesn't support outdated synchronization - Skipping CountriesIndex::Country, up to date +Synchronizing CountriesIndex + CountriesIndex doesn't support outdated synchronization + Skipping CountriesIndex, up to date + Took \\d+s +Synchronizing UsersIndex + UsersIndex doesn't support outdated synchronization + Skipping UsersIndex, up to date Took \\d+s Total: \\d+s\\Z OUTPUT @@ -263,8 +277,8 @@ expect { described_class.sync(only: CitiesIndex, output: output) } .to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) -\\ASynchronizing CitiesIndex::City - Imported CitiesIndex::City in \\d+s, stats: index 2 +\\ASynchronizing CitiesIndex + Imported CitiesIndex in \\d+s, stats: index 2 Missing documents: \\["#{cities.last.id}"\\] Outdated documents: \\["#{cities.first.id}"\\] Took \\d+s @@ -277,9 +291,13 @@ expect { described_class.sync(except: ['cities'], output: output) } .not_to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) -\\ASynchronizing CountriesIndex::Country - CountriesIndex::Country doesn't support outdated synchronization - Skipping CountriesIndex::Country, up to date +\\ASynchronizing CountriesIndex + CountriesIndex doesn't support outdated synchronization + Skipping CountriesIndex, up to date + Took \\d+s +Synchronizing UsersIndex + UsersIndex doesn't support outdated synchronization + Skipping UsersIndex, up to date Took \\d+s Total: \\d+s\\Z OUTPUT @@ -308,9 +326,9 @@ .to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\AApplying journal entries created after [+-:\\d\\s]+ - Applying journal to \\[CitiesIndex::City, CountriesIndex::Country\\], 3 entries, stage 1 - Imported CitiesIndex::City in \\d+s, stats: index 2 - Imported CountriesIndex::Country in \\d+s, stats: index 1 + Applying journal to \\[CitiesIndex, CountriesIndex\\], 3 entries, stage 1 + Imported CitiesIndex in \\d+s, stats: index 2 + Imported CountriesIndex in \\d+s, stats: index 1 Total: \\d+s\\Z OUTPUT end @@ -321,8 +339,8 @@ .not_to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\AApplying journal entries created after [+-:\\d\\s]+ - Applying journal to \\[CountriesIndex::Country\\], 1 entries, stage 1 - Imported CountriesIndex::Country in \\d+s, stats: index 1 + Applying journal to \\[CountriesIndex\\], 1 entries, stage 1 + Imported CountriesIndex in \\d+s, stats: index 1 Total: \\d+s\\Z OUTPUT end @@ -333,8 +351,8 @@ .to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\AApplying journal entries created after [+-:\\d\\s]+ - Applying journal to \\[CitiesIndex::City\\], 2 entries, stage 1 - Imported CitiesIndex::City in \\d+s, stats: index 2 + Applying journal to \\[CitiesIndex\\], 2 entries, stage 1 + Imported CitiesIndex in \\d+s, stats: index 2 Total: \\d+s\\Z OUTPUT end @@ -345,8 +363,8 @@ .not_to update_index(CitiesIndex) expect(output.string).to match(Regexp.new(<<-OUTPUT, Regexp::MULTILINE)) \\AApplying journal entries created after [+-:\\d\\s]+ - Applying journal to \\[CountriesIndex::Country\\], 1 entries, stage 1 - Imported CountriesIndex::Country in \\d+s, stats: index 1 + Applying journal to \\[CountriesIndex\\], 1 entries, stage 1 + Imported CountriesIndex in \\d+s, stats: index 1 Total: \\d+s\\Z OUTPUT end @@ -443,7 +461,7 @@ end let(:index_name) { CitiesIndex.index_name } - let(:unexisting_index) { 'wrong_index' } + let(:nonexistent_index) { 'wrong_index' } context 'with existing index' do specify do @@ -457,11 +475,11 @@ end end - context 'with unexisting index name' do + context 'with non-existent index name' do specify do output = StringIO.new - expect { described_class.update_mapping(name: unexisting_index, output: output) } - .to raise_error Elasticsearch::Transport::Transport::Errors::NotFound + expect { described_class.update_mapping(name: nonexistent_index, output: output) } + .to raise_error NameError end end end diff --git a/spec/chewy/rspec/update_index_spec.rb b/spec/chewy/rspec/update_index_spec.rb index b1cea443f..5982f4c51 100644 --- a/spec/chewy/rspec/update_index_spec.rb +++ b/spec/chewy/rspec/update_index_spec.rb @@ -3,10 +3,8 @@ describe :update_index do before do stub_index(:dummies) do - define_type :dummy end stub_index(:dummies2) do - define_type :dummy end end @@ -16,16 +14,16 @@ end specify { expect {}.not_to update_index(DummiesIndex) } - specify { expect { DummiesIndex::Dummy.bulk body: [] }.not_to update_index(DummiesIndex) } + specify { expect { DummiesIndex.bulk body: [] }.not_to update_index(DummiesIndex) } specify do - expect { expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42}}] }.not_to update_index(DummiesIndex) } + expect { expect { DummiesIndex.bulk body: [{index: {_id: 42}}] }.not_to update_index(DummiesIndex) } .to fail_with(/Expected index .* not to be updated, but it was with/) end specify do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] + DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] end.to update_index(DummiesIndex).and_reindex(41, 42).only end @@ -33,7 +31,7 @@ let(:expectation) do expect do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42}}, {index: {_id: 41}}, {index: {_id: 42}}] + DummiesIndex.bulk body: [{index: {_id: 42}}, {index: {_id: 41}}, {index: {_id: 42}}] end.not_to update_index(DummiesIndex) end end @@ -45,8 +43,8 @@ context 'compound matchers' do specify do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] - Dummies2Index::Dummy.bulk body: [{index: {_id: 43, data: {}}}] + DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] + Dummies2Index.bulk body: [{index: {_id: 43, data: {}}}] end.to update_index(DummiesIndex).and_reindex(41, 42).only .and update_index(Dummies2Index).and_reindex(43).only end @@ -55,7 +53,7 @@ let(:expectation) do expect do expect do - Dummies2Index::Dummy.bulk body: [{index: {_id: 43, data: {}}}] + Dummies2Index.bulk body: [{index: {_id: 43, data: {}}}] end.to update_index(DummiesIndex).and_reindex(41, 42).only .and update_index(Dummies2Index).and_reindex(43).only end @@ -67,91 +65,91 @@ context '#only' do specify do - expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] } + expect { DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] } .to update_index(DummiesIndex).and_reindex(41, 42).only end specify do expect do - expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] } + expect { DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] } .to update_index(DummiesIndex).and_reindex(41).only end.to fail_matching 'to update documents ["41"] only, but ["42"] was updated also' end specify do expect do - expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] } + expect { DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}] } .to update_index(DummiesIndex).and_reindex(41, times: 2).only end.to fail_matching 'to update documents ["41"] only, but ["42"] was updated also' end specify do - expect { DummiesIndex::Dummy.bulk body: [{delete: {_id: 42}}, {delete: {_id: 41}}] } + expect { DummiesIndex.bulk body: [{delete: {_id: 42}}, {delete: {_id: 41}}] } .to update_index(DummiesIndex).and_delete(41, 42).only end specify do expect do - expect { DummiesIndex::Dummy.bulk body: [{delete: {_id: 42}}, {delete: {_id: 41}}] } + expect { DummiesIndex.bulk body: [{delete: {_id: 42}}, {delete: {_id: 41}}] } .to update_index(DummiesIndex).and_delete(41).only end.to fail_matching 'to delete documents ["41"] only, but ["42"] was deleted also' end specify do expect do - expect { DummiesIndex::Dummy.bulk body: [{delete: {_id: 42}}, {delete: {_id: 41}}] } + expect { DummiesIndex.bulk body: [{delete: {_id: 42}}, {delete: {_id: 41}}] } .to update_index(DummiesIndex).and_delete(41, times: 2).only end.to fail_matching 'to delete documents ["41"] only, but ["42"] was deleted also' end specify do expect do - expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {delete: {_id: 41}}] } + expect { DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {delete: {_id: 41}}] } .to update_index(DummiesIndex).and_reindex(42).only end.to fail_matching 'to update documents ["42"] only, but ["41"] was deleted also' end specify do expect do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}, - {delete: {_id: 41}}] + DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}, + {delete: {_id: 41}}] end.to update_index(DummiesIndex).and_reindex(42).only end.to fail_matching 'to update documents ["42"] only, but ["43"] was updated and ["41"] was deleted also' end specify do expect do - expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {delete: {_id: 41}}] } + expect { DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {delete: {_id: 41}}] } .to update_index(DummiesIndex).and_delete(41).only end.to fail_matching 'to delete documents ["41"] only, but ["42"] was updated also' end specify do expect do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {delete: {_id: 41}}, {delete: {_id: 43}}] + DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {delete: {_id: 41}}, {delete: {_id: 43}}] end.to update_index(DummiesIndex).and_delete(41).only end.to fail_matching 'to delete documents ["41"] only, but ["42"] was updated and ["43"] was deleted also' end end context '#and_reindex' do - specify { expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42}}] }.to update_index(DummiesIndex) } + specify { expect { DummiesIndex.bulk body: [{index: {_id: 42}}] }.to update_index(DummiesIndex) } specify do - expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}] } + expect { DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}] } .to update_index(DummiesIndex).and_reindex(42) end specify do - expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] } + expect { DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] } .to update_index(DummiesIndex).and_reindex(double(id: 42)) end specify do - expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] } + expect { DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] } .to update_index(DummiesIndex).and_reindex(double(id: 42), double(id: 43)) end specify do - expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] } + expect { DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] } .to update_index(DummiesIndex).and_reindex([double(id: 42), 43]) end specify do expect do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] + DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] end.to update_index(DummiesIndex).and_reindex([44, 43]) end.to fail_matching 'Expected document with id `44` to be reindexed, but it was not' end @@ -160,7 +158,7 @@ let(:expectation) do expect do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] + DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] end.to update_index(DummiesIndex).and_reindex(44, double(id: 47)) end end @@ -172,15 +170,15 @@ context ':times' do specify do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] - DummiesIndex::Dummy.bulk body: [{index: {_id: 43, data: {}}}, {index: {_id: 44, data: {}}}] + DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] + DummiesIndex.bulk body: [{index: {_id: 43, data: {}}}, {index: {_id: 44, data: {}}}] end.to update_index(DummiesIndex).and_reindex(42, 44, times: 1).and_reindex(43, times: 2) end specify do expect do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 43, data: {a: '1'}}}] + DummiesIndex.bulk body: [{index: {_id: 43, data: {a: '1'}}}] end.to update_index(DummiesIndex).and_reindex(42, times: 3) end.to fail_matching('Expected document with id `42` to be reindexed, but it was not') end @@ -189,8 +187,8 @@ let(:expectation) do expect do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] - DummiesIndex::Dummy.bulk body: [{index: {_id: 43, data: {}}}, {index: {_id: 44, data: {}}}] + DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 43, data: {}}}] + DummiesIndex.bulk body: [{index: {_id: 43, data: {}}}, {index: {_id: 44, data: {}}}] end.to update_index(DummiesIndex).and_reindex(42, times: 3).and_reindex(44, 43, times: 4) end end @@ -205,20 +203,20 @@ context ':with' do specify do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {a: '1'}}}, {index: {_id: 42, data: {'a' => 2}}}] + DummiesIndex.bulk body: [{index: {_id: 42, data: {a: '1'}}}, {index: {_id: 42, data: {'a' => 2}}}] end.to update_index(DummiesIndex).and_reindex(42, with: {a: 2}) end specify do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {a: '1'}}}, {index: {_id: 42, data: {'b' => 2}}}] + DummiesIndex.bulk body: [{index: {_id: 42, data: {a: '1'}}}, {index: {_id: 42, data: {'b' => 2}}}] end.to update_index(DummiesIndex).and_reindex(42, with: {a: '1', b: 2}) end specify do expect do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 43, data: {a: '1'}}}] + DummiesIndex.bulk body: [{index: {_id: 43, data: {a: '1'}}}] end.to update_index(DummiesIndex).and_reindex(42, with: {a: 1}) end.to fail_matching('Expected document with id `42` to be reindexed, but it was not') end @@ -232,7 +230,7 @@ ].each do |(data, with)| specify do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: data}}] + DummiesIndex.bulk body: [{index: {_id: 42, data: data}}] end.to update_index(DummiesIndex).and_reindex(42, with: with) end end @@ -247,7 +245,7 @@ specify do expect do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: data}}] + DummiesIndex.bulk body: [{index: {_id: 42, data: data}}] end.to update_index(DummiesIndex).and_reindex(42, with: with) end.to fail_matching('Expected document with id `42` to be reindexed') end @@ -257,7 +255,7 @@ let(:expectation) do expect do expect do - DummiesIndex::Dummy.bulk body: [{index: {_id: 43, data: {a: '1'}}}, {index: {_id: 42, data: {'a' => 2}}}] + DummiesIndex.bulk body: [{index: {_id: 43, data: {a: '1'}}}, {index: {_id: 42, data: {'a' => 2}}}] end.to update_index(DummiesIndex).and_reindex(43, times: 2, with: {a: 2}) end end @@ -271,26 +269,26 @@ context '#and_delete' do specify do - expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {delete: {_id: 43}}] } + expect { DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {delete: {_id: 43}}] } .to update_index(DummiesIndex).and_reindex(42).and_delete(double(id: 43)) end specify do - expect { DummiesIndex::Dummy.bulk body: [{delete: {_id: 42}}, {delete: {_id: 43}}] } + expect { DummiesIndex.bulk body: [{delete: {_id: 42}}, {delete: {_id: 43}}] } .to update_index(DummiesIndex).and_delete(42).and_delete(double(id: 43)) end specify do - expect { DummiesIndex::Dummy.bulk body: [{delete: {_id: 42}}, {delete: {_id: 43}}] } + expect { DummiesIndex.bulk body: [{delete: {_id: 42}}, {delete: {_id: 43}}] } .to update_index(DummiesIndex).and_delete(42, double(id: 43)) end specify do - expect { DummiesIndex::Dummy.bulk body: [{delete: {_id: 42}}, {delete: {_id: 43}}] } + expect { DummiesIndex.bulk body: [{delete: {_id: 42}}, {delete: {_id: 43}}] } .to update_index(DummiesIndex).and_delete([43, double(id: 42)]) end context do let(:expectation) do expect do - expect { DummiesIndex::Dummy.bulk body: [{index: {_id: 42, data: {}}}, {delete: {_id: 43}}] } + expect { DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {delete: {_id: 43}}] } .to update_index(DummiesIndex).and_reindex(43).and_delete(double(id: 42)) end end @@ -302,7 +300,7 @@ context do let(:expectation) do expect do - expect { DummiesIndex::Dummy.bulk body: [{delete: {_id: 42, data: {}}}, {delete: {_id: 42}}] } + expect { DummiesIndex.bulk body: [{delete: {_id: 42, data: {}}}, {delete: {_id: 42}}] } .to update_index(DummiesIndex).and_delete(44, times: 2).and_delete(double(id: 42), times: 3) end end diff --git a/spec/chewy/search/loader_spec.rb b/spec/chewy/search/loader_spec.rb index 4cf04b07f..1bfde065a 100644 --- a/spec/chewy/search/loader_spec.rb +++ b/spec/chewy/search/loader_spec.rb @@ -8,17 +8,15 @@ stub_model(:country) stub_index(:cities) do - define_type City do - field :name - field :rating, type: 'integer' - end + index_scope City + field :name + field :rating, type: 'integer' end stub_index(:countries) do - define_type Country do - field :name - field :rating, type: 'integer' - end + index_scope Country + field :name + field :rating, type: 'integer' end end @@ -33,18 +31,18 @@ let(:options) { {} } subject { described_class.new(indexes: [CitiesIndex, CountriesIndex], **options) } - describe '#derive_type' do - specify { expect(subject.derive_type('cities', 'city')).to eq(CitiesIndex::City) } - specify { expect(subject.derive_type('cities_suffix', 'city')).to eq(CitiesIndex::City) } + describe '#derive_index' do + specify { expect(subject.derive_index('cities')).to eq(CitiesIndex) } + specify { expect(subject.derive_index('cities_suffix')).to eq(CitiesIndex) } - specify { expect { subject.derive_type('whatever', 'city') }.to raise_error(Chewy::UnderivableType) } - specify { expect { subject.derive_type('citiessuffix', 'city') }.to raise_error(Chewy::UnderivableType) } + specify { expect { subject.derive_index('whatever') }.to raise_error(Chewy::UndefinedIndex) } + specify { expect { subject.derive_index('citiessuffix') }.to raise_error(Chewy::UndefinedIndex) } context do before { CitiesIndex.index_name :boro_goves } - specify { expect(subject.derive_type('boro_goves', 'city')).to eq(CitiesIndex::City) } - specify { expect(subject.derive_type('boro_goves_suffix', 'city')).to eq(CitiesIndex::City) } + specify { expect(subject.derive_index('boro_goves')).to eq(CitiesIndex) } + specify { expect(subject.derive_index('boro_goves_suffix')).to eq(CitiesIndex) } end end @@ -60,7 +58,7 @@ end context do - let(:options) { {country: {scope: -> { where('rating > 2') }}} } + let(:options) { {countries: {scope: -> { where('rating > 2') }}} } specify { expect(subject.load(hits)).to eq([*cities, nil, countries.last]) } end end @@ -68,21 +66,17 @@ context 'objects' do before do stub_index(:cities) do - define_type :city do - field :name - field :rating, type: 'integer' - end + field :name + field :rating, type: 'integer' end stub_index(:countries) do - define_type :country do - field :name - field :rating, type: 'integer' - end + field :name + field :rating, type: 'integer' end end - specify { expect(subject.load(hits).map(&:class).uniq).to eq([CitiesIndex::City, CountriesIndex::Country]) } + specify { expect(subject.load(hits).map(&:class).uniq).to eq([CitiesIndex, CountriesIndex]) } specify { expect(subject.load(hits).map(&:rating)).to eq([*cities, *countries].map(&:rating)) } end end diff --git a/spec/chewy/search/pagination/kaminari_examples.rb b/spec/chewy/search/pagination/kaminari_examples.rb index f60f132df..ccb033bfd 100644 --- a/spec/chewy/search/pagination/kaminari_examples.rb +++ b/spec/chewy/search/pagination/kaminari_examples.rb @@ -5,10 +5,8 @@ before do stub_index(:products) do - define_type(:product) do - field :name - field :age, type: 'integer' - end + field :name + field :age, type: 'integer' end end @@ -25,7 +23,7 @@ context do let(:data) { Array.new(10) { |i| {id: i.next.to_s, name: "Name#{i.next}", age: 10 * i.next}.stringify_keys! } } - before { ProductsIndex::Product.import!(data.map { |h| double(h) }) } + before { ProductsIndex.import!(data.map { |h| double(h) }) } before { allow(::Kaminari.config).to receive_messages(default_per_page: 3) } describe '#per, #page' do diff --git a/spec/chewy/search/pagination/kaminari_spec.rb b/spec/chewy/search/pagination/kaminari_spec.rb index 30ac7effc..c75eacaa8 100644 --- a/spec/chewy/search/pagination/kaminari_spec.rb +++ b/spec/chewy/search/pagination/kaminari_spec.rb @@ -5,7 +5,7 @@ describe '#objects' do let(:data) { Array.new(12) { |i| {id: i.next.to_s, name: "Name#{i.next}", age: 10 * i.next}.stringify_keys! } } - before { ProductsIndex::Product.import!(data.map { |h| double(h) }) } + before { ProductsIndex.import!(data.map { |h| double(h) }) } before { allow(::Kaminari.config).to receive_messages(default_per_page: 17) } specify { expect(search.objects.class).to eq(Kaminari::PaginatableArray) } diff --git a/spec/chewy/search/parameters/indices_spec.rb b/spec/chewy/search/parameters/indices_spec.rb index 649e7d3a5..a58276b38 100644 --- a/spec/chewy/search/parameters/indices_spec.rb +++ b/spec/chewy/search/parameters/indices_spec.rb @@ -2,14 +2,8 @@ describe Chewy::Search::Parameters::Indices do before do - stub_index(:first) do - define_type :one - end - - stub_index(:second) do - define_type :three - end - + stub_index(:first) + stub_index(:second) stub_index(:third) end diff --git a/spec/chewy/search/request_spec.rb b/spec/chewy/search/request_spec.rb index d46dc9759..e077716e4 100644 --- a/spec/chewy/search/request_spec.rb +++ b/spec/chewy/search/request_spec.rb @@ -5,23 +5,17 @@ before do stub_index(:products) do - define_type :product do - field :id, type: :integer - field :name - field :age, type: :integer - end + field :id, type: :integer + field :name + field :age, type: :integer end stub_index(:cities) do - define_type :city do - field :id, type: :integer - end + field :id, type: :integer end stub_index(:countries) do - define_type :country do - field :id, type: :integer - end + field :id, type: :integer end end @@ -383,15 +377,13 @@ stub_model(:country) stub_index(:places) do - define_type City do - field :rating, type: 'integer' - end + index_scope City + field :rating, type: 'integer' end stub_index(:countries) do - define_type Country do - field :rating, type: 'integer' - end + index_scope Country + field :rating, type: 'integer' end end @@ -409,7 +401,7 @@ describe '#load' do specify { expect(subject.load(only: 'city')).to eq([*cities]) } - specify { expect(subject.load(only: 'city').map(&:class).uniq).to eq([PlacesIndex::City]) } + specify { expect(subject.load(only: 'city').map(&:class).uniq).to eq([PlacesIndex]) } specify { expect(subject.load(only: 'city').objects).to eq([*cities]) } end end @@ -508,9 +500,9 @@ let(:cities) { Array.new(3) { |i| {id: (i.next + 9).to_i}.stringify_keys! } } let(:countries) { Array.new(3) { |i| {id: (i.next + 12).to_i}.stringify_keys! } } before do - ProductsIndex::Product.import!(products.map { |h| double(h) }) - CountriesIndex::Country.import!(countries.map { |h| double(h) }) - CitiesIndex::City.import!(cities.map { |h| double(h) }) + ProductsIndex.import!(products.map { |h| double(h) }) + CountriesIndex.import!(countries.map { |h| double(h) }) + CitiesIndex.import!(cities.map { |h| double(h) }) end specify { expect(subject[0]._data).to be_a Hash } @@ -647,7 +639,7 @@ context do before { expect(Chewy.client).to receive(:search).once.and_call_original } - specify { expect(subject.first).to be_a(ProductsIndex::Product).and have_attributes(id: 9) } + specify { expect(subject.first).to be_a(ProductsIndex).and have_attributes(id: 9) } specify { expect(subject.first(3).map(&:id)).to eq([9, 8, 7]) } specify { expect(subject.first(10).map(&:id)).to have(9).items } specify { expect(subject.limit(5).first(10).map(&:id)).to have(9).items } @@ -660,7 +652,7 @@ expect(Chewy.client).not_to receive(:search) end - specify { expect(subject.first).to be_a(ProductsIndex::Product).and have_attributes(id: 9) } + specify { expect(subject.first).to be_a(ProductsIndex).and have_attributes(id: 9) } specify { expect(subject.first(3).map(&:id)).to eq([9, 8, 7]) } specify { expect(subject.first(10).map(&:id)).to have(9).items } @@ -681,8 +673,8 @@ end describe '#find' do - specify { expect(subject.find('1')).to be_a(ProductsIndex::Product).and have_attributes(id: 1) } - specify { expect(subject.find { |w| w.id == 2 }).to be_a(ProductsIndex::Product).and have_attributes(id: 2) } + specify { expect(subject.find('1')).to be_a(ProductsIndex).and have_attributes(id: 1) } + specify { expect(subject.find { |w| w.id == 2 }).to be_a(ProductsIndex).and have_attributes(id: 2) } specify { expect(subject.limit(2).find('1', '3', '7').map(&:id)).to contain_exactly(1, 3, 7) } specify { expect(subject.find(1, 3, 7).map(&:id)).to contain_exactly(1, 3, 7) } specify do @@ -722,7 +714,7 @@ before { expect(Chewy.client).to receive(:scroll).once.and_call_original } specify { expect(subject.find((1..9).to_a)).to have(9).items } - specify { expect(subject.find((1..9).to_a)).to all be_a(Chewy::Type) } + specify { expect(subject.find((1..9).to_a)).to all be_a(Chewy::Index) } end end diff --git a/spec/chewy/search/response_spec.rb b/spec/chewy/search/response_spec.rb index ae5721c2f..7b291288d 100644 --- a/spec/chewy/search/response_spec.rb +++ b/spec/chewy/search/response_spec.rb @@ -8,16 +8,14 @@ stub_model(:country) stub_index(:cities) do - define_type City do - field :name - field :rating, type: 'integer' - end + index_scope City + field :name + field :rating, type: 'integer' end stub_index(:countries) do - define_type Country do - field :name - field :rating, type: 'integer' - end + index_scope Country + field :name + field :rating, type: 'integer' end end @@ -139,7 +137,7 @@ specify { expect(subject.wrappers).to have(4).items } specify do expect(subject.wrappers.map(&:class).uniq) - .to contain_exactly(CitiesIndex::City, CountriesIndex::Country) + .to contain_exactly(CitiesIndex, CountriesIndex) end specify { expect(subject.wrappers.map(&:_data)).to eq(subject.hits) } @@ -168,7 +166,7 @@ '_source' => {'id' => 2, 'rating' => 0}} ]}} end - specify { expect(subject.wrappers.first).to be_a(CitiesIndex::City) } + specify { expect(subject.wrappers.first).to be_a(CitiesIndex) } specify { expect(subject.wrappers.first.id).to eq(2) } specify { expect(subject.wrappers.first.rating).to eq(0) } specify { expect(subject.wrappers.first._score).to eq(1.3) } @@ -185,7 +183,7 @@ '_explanation' => {foo: 'bar'}} ]}} end - specify { expect(subject.wrappers.first).to be_a(CountriesIndex::Country) } + specify { expect(subject.wrappers.first).to be_a(CountriesIndex) } specify { expect(subject.wrappers.first.id).to eq('2') } specify { expect(subject.wrappers.first.rating).to be_nil } specify { expect(subject.wrappers.first._score).to eq(1.2) } diff --git a/spec/chewy/search/scrolling_spec.rb b/spec/chewy/search/scrolling_spec.rb index aa0b64174..db714a43d 100644 --- a/spec/chewy/search/scrolling_spec.rb +++ b/spec/chewy/search/scrolling_spec.rb @@ -8,16 +8,14 @@ stub_model(:country) stub_index(:cities) do - define_type City do - field :name - field :rating, type: 'integer' - end + index_scope City + field :name + field :rating, type: 'integer' end stub_index(:countries) do - define_type Country do - field :name - field :rating, type: 'integer' - end + index_scope Country + field :name + field :rating, type: 'integer' end end @@ -153,7 +151,7 @@ end specify do expect(request.scroll_wrappers(batch_size: 2).map(&:class).uniq) - .to eq([CitiesIndex::City, CountriesIndex::Country]) + .to eq([CitiesIndex, CountriesIndex]) end end diff --git a/spec/chewy/search_spec.rb b/spec/chewy/search_spec.rb index de87a7b67..3abf43326 100644 --- a/spec/chewy/search_spec.rb +++ b/spec/chewy/search_spec.rb @@ -4,47 +4,34 @@ before { Chewy.massacre } before do - stub_index(:products) do - define_type :product - end + stub_index(:products) end - let(:product) { ProductsIndex::Product } - describe '.all' do specify { expect(ProductsIndex.all).to be_a(Chewy::Search::Request) } - specify { expect(product.all).to be_a(Chewy::Search::Request) } context do before { allow(Chewy).to receive_messages(search_class: Chewy::Search::Request) } specify { expect(ProductsIndex.all).to be_a(Chewy::Search::Request) } - specify { expect(product.all).to be_a(Chewy::Search::Request) } end end describe '.search_string' do specify do - expect(ProductsIndex.client).to receive(:search).with(hash_including(q: 'hello')).twice + expect(ProductsIndex.client).to receive(:search).with(hash_including(q: 'hello')).once ProductsIndex.search_string('hello') - product.search_string('hello') end specify do - expect(ProductsIndex.client).to receive(:search).with(hash_including(explain: true)).twice + expect(ProductsIndex.client).to receive(:search).with(hash_including(explain: true)).once ProductsIndex.search_string('hello', explain: true) - product.search_string('hello', explain: true) end specify do - expect(ProductsIndex.client).to receive(:search).with(hash_including(index: ['products'])) + expect(ProductsIndex.client).to receive(:search).with(hash_including(index: ['products'])).once ProductsIndex.search_string('hello') end - - specify do - expect(ProductsIndex.client).to receive(:search).with(hash_including(index: ['products'])) - product.search_string('hello') - end end context 'named scopes' do @@ -61,10 +48,9 @@ def self.by_name(index) filter { match name: "Name#{index}" } end - define_type City do - field :name, type: 'keyword' - field :rating, type: :integer - end + index_scope City + field :name, type: 'keyword' + field :rating, type: :integer end stub_index(:countries) do @@ -76,10 +62,9 @@ def self.by_name(index) filter { match name: "Name#{index}" } end - define_type Country do - field :name, type: 'keyword' - field :rating, type: :integer - end + index_scope Country + field :name, type: 'keyword' + field :rating, type: :integer end end @@ -94,40 +79,40 @@ def self.by_name(index) specify { expect(CitiesIndex.indices(CountriesIndex).by_rating(1).map(&:rating)).to eq([1, 1]) } specify do expect(CitiesIndex.indices(CountriesIndex).by_rating(1).map(&:class)) - .to match_array([CitiesIndex::City, CountriesIndex::Country]) + .to match_array([CitiesIndex, CountriesIndex]) end specify { expect(CitiesIndex.indices(CountriesIndex).by_rating(1).by_name(2).map(&:rating)).to eq([1]) } specify do expect(CitiesIndex.indices(CountriesIndex).by_rating(1).by_name(2).map(&:class)) - .to eq([CitiesIndex::City]) + .to eq([CitiesIndex]) end specify { expect(CitiesIndex.indices(CountriesIndex).by_name(3).map(&:rating)).to eq([2, 1]) } specify do expect(CitiesIndex.indices(CountriesIndex).by_name(3).map(&:class)) - .to eq([CitiesIndex::City, CountriesIndex::Country]) + .to eq([CitiesIndex, CountriesIndex]) end specify { expect(CitiesIndex.indices(CountriesIndex).order(:name).by_rating(1).map(&:rating)).to eq([1, 1]) } specify do expect(CitiesIndex.indices(CountriesIndex).order(:name).by_rating(1).map(&:class)) - .to match_array([CitiesIndex::City, CountriesIndex::Country]) + .to match_array([CitiesIndex, CountriesIndex]) end specify { expect(CitiesIndex.by_rating(2).map(&:rating)).to eq([2]) } - specify { expect(CitiesIndex.by_rating(2).map(&:class)).to eq([CitiesIndex::City]) } + specify { expect(CitiesIndex.by_rating(2).map(&:class)).to eq([CitiesIndex]) } specify { expect(CitiesIndex.by_rating(2).by_name(3).map(&:rating)).to eq([2]) } - specify { expect(CitiesIndex.by_rating(2).by_name(3).map(&:class)).to eq([CitiesIndex::City]) } + specify { expect(CitiesIndex.by_rating(2).by_name(3).map(&:class)).to eq([CitiesIndex]) } specify { expect(CitiesIndex.by_name(3).map(&:rating)).to eq([2]) } specify { expect(CitiesIndex.by_name(3).map(&:rating)).to eq([2]) } specify { expect(CitiesIndex.order(:name).by_name(3).map(&:rating)).to eq([2]) } specify { expect(CitiesIndex.order(:name).by_name(3).map(&:rating)).to eq([2]) } specify { expect(CitiesIndex.order(:name).by_rating(2).map(&:rating)).to eq([2]) } - specify { expect(CitiesIndex.order(:name).by_rating(2).map(&:class)).to eq([CitiesIndex::City]) } + specify { expect(CitiesIndex.order(:name).by_rating(2).map(&:class)).to eq([CitiesIndex]) } specify { expect(CountriesIndex.by_rating(3).map(&:rating)).to eq([3]) } - specify { expect(CountriesIndex.by_rating(3).map(&:class)).to eq([CountriesIndex::Country]) } + specify { expect(CountriesIndex.by_rating(3).map(&:class)).to eq([CountriesIndex]) } specify { expect(CountriesIndex.by_rating(3).by_name(5).map(&:rating)).to eq([3]) } - specify { expect(CountriesIndex.by_rating(3).by_name(5).map(&:class)).to eq([CountriesIndex::Country]) } + specify { expect(CountriesIndex.by_rating(3).by_name(5).map(&:class)).to eq([CountriesIndex]) } specify { expect(CountriesIndex.order(:name).by_rating(3).map(&:rating)).to eq([3]) } - specify { expect(CountriesIndex.order(:name).by_rating(3).map(&:class)).to eq([CountriesIndex::Country]) } + specify { expect(CountriesIndex.order(:name).by_rating(3).map(&:class)).to eq([CountriesIndex]) } end end diff --git a/spec/chewy/stash_spec.rb b/spec/chewy/stash_spec.rb index e1198a5c4..2d2774ff5 100644 --- a/spec/chewy/stash_spec.rb +++ b/spec/chewy/stash_spec.rb @@ -10,12 +10,10 @@ def fetch_deleted_number(response) before do stub_model(:city) stub_index(:cities) do - define_type City + index_scope City end - stub_index(:countries) do - define_type :country - end - stub_index(:users) { define_type :user } + stub_index(:countries) + stub_index(:users) stub_index(:borogoves) end @@ -28,7 +26,7 @@ def fetch_deleted_number(response) CountriesIndex.import!([id: 2, name: 'Country'], journal: true) end Timecop.travel(Time.now + 2.minutes) do - UsersIndex::User.import!([id: 3, name: 'User'], journal: true) + UsersIndex.import!([id: 3, name: 'User'], journal: true) end end @@ -80,24 +78,8 @@ def fetch_deleted_number(response) describe '.for' do specify { expect(described_class.for(UsersIndex).map(&:index_name)).to eq(['users']) } - specify do - expect(described_class.for(CitiesIndex, CountriesIndex).map(&:type_name)).to contain_exactly('city', 'country') - end specify do expect(described_class.for(CitiesIndex, UsersIndex).map(&:index_name)).to contain_exactly('cities', 'users') end end - - describe '#type' do - let(:index_name) { 'users' } - let(:type_name) { 'city' } - subject { described_class::Journal.new('index_name' => index_name, 'type_name' => type_name).type } - - specify { expect { subject }.to raise_error(Chewy::UnderivableType) } - - context do - let(:index_name) { 'cities' } - it { is_expected.to eq(CitiesIndex::City) } - end - end end diff --git a/spec/chewy/strategy/active_job_spec.rb b/spec/chewy/strategy/active_job_spec.rb index 1782cdeb9..71d9563d1 100644 --- a/spec/chewy/strategy/active_job_spec.rb +++ b/spec/chewy/strategy/active_job_spec.rb @@ -19,11 +19,11 @@ before do stub_model(:city) do - update_index('cities#city') { self } + update_index('cities') { self } end stub_index(:cities) do - define_type City + index_scope City end end @@ -32,7 +32,7 @@ specify do expect { [city, other_city].map(&:save!) } - .not_to update_index(CitiesIndex::City, strategy: :active_job) + .not_to update_index(CitiesIndex, strategy: :active_job) end specify do @@ -55,19 +55,19 @@ specify do ::ActiveJob::Base.queue_adapter = :inline expect { [city, other_city].map(&:save!) } - .to update_index(CitiesIndex::City, strategy: :active_job) + .to update_index(CitiesIndex, strategy: :active_job) .and_reindex(city, other_city).only end specify do - expect(CitiesIndex::City).to receive(:import!).with([city.id, other_city.id], suffix: '201601') - Chewy::Strategy::ActiveJob::Worker.new.perform('CitiesIndex::City', [city.id, other_city.id], suffix: '201601') + expect(CitiesIndex).to receive(:import!).with([city.id, other_city.id], suffix: '201601') + Chewy::Strategy::ActiveJob::Worker.new.perform('CitiesIndex', [city.id, other_city.id], suffix: '201601') end specify do allow(Chewy).to receive(:disable_refresh_async).and_return(true) - expect(CitiesIndex::City).to receive(:import!).with([city.id, other_city.id], suffix: '201601', refresh: false) - Chewy::Strategy::ActiveJob::Worker.new.perform('CitiesIndex::City', [city.id, other_city.id], suffix: '201601') + expect(CitiesIndex).to receive(:import!).with([city.id, other_city.id], suffix: '201601', refresh: false) + Chewy::Strategy::ActiveJob::Worker.new.perform('CitiesIndex', [city.id, other_city.id], suffix: '201601') end end end diff --git a/spec/chewy/strategy/atomic_spec.rb b/spec/chewy/strategy/atomic_spec.rb index d479be6bc..adca4dd4d 100644 --- a/spec/chewy/strategy/atomic_spec.rb +++ b/spec/chewy/strategy/atomic_spec.rb @@ -5,11 +5,11 @@ before do stub_model(:country) do - update_index('countries#country') { self } + update_index('countries') { self } end stub_index(:countries) do - define_type Country + index_scope Country end end @@ -18,35 +18,34 @@ specify do expect { [country, other_country].map(&:save!) } - .to update_index(CountriesIndex::Country, strategy: :atomic) + .to update_index(CountriesIndex, strategy: :atomic) .and_reindex(country, other_country).only end specify do expect { [country, other_country].map(&:destroy) } - .to update_index(CountriesIndex::Country, strategy: :atomic) + .to update_index(CountriesIndex, strategy: :atomic) .and_delete(country, other_country).only end context do before do stub_index(:countries) do - define_type Country do - root id: -> { country_code } do - end + index_scope Country + root id: -> { country_code } do end end end specify do expect { [country, other_country].map(&:save!) } - .to update_index(CountriesIndex::Country, strategy: :atomic) + .to update_index(CountriesIndex, strategy: :atomic) .and_reindex('HL', 'WD').only end specify do expect { [country, other_country].map(&:destroy) } - .to update_index(CountriesIndex::Country, strategy: :atomic) + .to update_index(CountriesIndex, strategy: :atomic) .and_delete('HL', 'WD').only end @@ -55,7 +54,7 @@ country.save! other_country.destroy end - .to update_index(CountriesIndex::Country, strategy: :atomic) + .to update_index(CountriesIndex, strategy: :atomic) .and_reindex('HL').and_delete('WD').only end end diff --git a/spec/chewy/strategy/sidekiq_spec.rb b/spec/chewy/strategy/sidekiq_spec.rb index 8fe94e143..943ac6f7e 100644 --- a/spec/chewy/strategy/sidekiq_spec.rb +++ b/spec/chewy/strategy/sidekiq_spec.rb @@ -13,11 +13,11 @@ before { ::Sidekiq::Worker.clear_all } before do stub_model(:city) do - update_index('cities#city') { self } + update_index('cities') { self } end stub_index(:cities) do - define_type City + index_scope City end end @@ -26,27 +26,27 @@ specify do expect { [city, other_city].map(&:save!) } - .not_to update_index(CitiesIndex::City, strategy: :sidekiq) + .not_to update_index(CitiesIndex, strategy: :sidekiq) end specify do expect(::Sidekiq::Client).to receive(:push).with(hash_including('queue' => 'low')).and_call_original ::Sidekiq::Testing.inline! do expect { [city, other_city].map(&:save!) } - .to update_index(CitiesIndex::City, strategy: :sidekiq) + .to update_index(CitiesIndex, strategy: :sidekiq) .and_reindex(city, other_city).only end end specify do - expect(CitiesIndex::City).to receive(:import!).with([city.id, other_city.id], suffix: '201601') - Chewy::Strategy::Sidekiq::Worker.new.perform('CitiesIndex::City', [city.id, other_city.id], suffix: '201601') + expect(CitiesIndex).to receive(:import!).with([city.id, other_city.id], suffix: '201601') + Chewy::Strategy::Sidekiq::Worker.new.perform('CitiesIndex', [city.id, other_city.id], suffix: '201601') end specify do allow(Chewy).to receive(:disable_refresh_async).and_return(true) - expect(CitiesIndex::City).to receive(:import!).with([city.id, other_city.id], suffix: '201601', refresh: false) - Chewy::Strategy::Sidekiq::Worker.new.perform('CitiesIndex::City', [city.id, other_city.id], suffix: '201601') + expect(CitiesIndex).to receive(:import!).with([city.id, other_city.id], suffix: '201601', refresh: false) + Chewy::Strategy::Sidekiq::Worker.new.perform('CitiesIndex', [city.id, other_city.id], suffix: '201601') end end end diff --git a/spec/chewy/strategy_spec.rb b/spec/chewy/strategy_spec.rb index 64c5c3399..25a2344bd 100644 --- a/spec/chewy/strategy_spec.rb +++ b/spec/chewy/strategy_spec.rb @@ -55,11 +55,11 @@ context 'nesting', :orm do before do stub_model(:city) do - update_index('cities#city') { self } + update_index('cities') { self } end stub_index(:cities) do - define_type City + index_scope City end end @@ -70,12 +70,12 @@ around { |example| Chewy.strategy(:bypass) { example.run } } specify do - expect(CitiesIndex::City).not_to receive(:import!) + expect(CitiesIndex).not_to receive(:import!) [city, other_city].map(&:save!) end specify do - expect(CitiesIndex::City).to receive(:import!).with([city.id, other_city.id]).once + expect(CitiesIndex).to receive(:import!).with([city.id, other_city.id]).once Chewy.strategy(:atomic) { [city, other_city].map(&:save!) } end end @@ -84,41 +84,39 @@ around { |example| Chewy.strategy(:urgent) { example.run } } specify do - expect(CitiesIndex::City).to receive(:import!).at_least(2).times + expect(CitiesIndex).to receive(:import!).at_least(2).times [city, other_city].map(&:save!) end specify do - expect(CitiesIndex::City).to receive(:import!).with([city.id, other_city.id]).once + expect(CitiesIndex).to receive(:import!).with([city.id, other_city.id]).once Chewy.strategy(:atomic) { [city, other_city].map(&:save!) } end context 'hash passed to urgent' do before do - stub_index(:cities) do - define_type :city - end + stub_index(:cities) stub_model(:city) do - update_index('cities#city') { {name: name} } + update_index('cities') { {name: name} } end end specify do [city, other_city].map(&:save!) - expect(CitiesIndex::City.total_count).to eq(4) + expect(CitiesIndex.total_count).to eq(4) end context do before do stub_model(:city) do - update_index('cities#city') { {id: id.to_s, name: name} } + update_index('cities') { {id: id.to_s, name: name} } end end specify do [city, other_city].map(&:save!) - expect(CitiesIndex::City.total_count).to eq(2) + expect(CitiesIndex.total_count).to eq(2) end end end diff --git a/spec/chewy/type/actions_spec.rb b/spec/chewy/type/actions_spec.rb deleted file mode 100644 index 853027cb7..000000000 --- a/spec/chewy/type/actions_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -require 'spec_helper' - -describe Chewy::Type::Actions, :orm do - before { Chewy.massacre } - - before do - stub_model(:city) - stub_index(:cities) do - define_type City do - field :name - field :updated_at, type: 'date' - end - end - end - - let!(:cities) { Array.new(3) { |i| City.create!(name: "Name#{i + 1}") } } - before { CitiesIndex::City.import } - - describe '.reset' do - specify do - expect { CitiesIndex::City.reset }.to update_index(CitiesIndex::City) - end - end - - describe '.sync' do - before do - cities.first.destroy - sleep(1) if ActiveSupport::VERSION::STRING < '4.1.0' - cities.last.update(name: 'Name5') - end - let!(:additional_city) { City.create!(name: 'Name4') } - - specify do - expect(CitiesIndex::City.sync).to match( - count: 3, - missing: contain_exactly(cities.first.id.to_s, additional_city.id.to_s), - outdated: [cities.last.id.to_s] - ) - end - specify do - expect { CitiesIndex::City.sync }.to update_index(CitiesIndex::City) - .and_reindex(additional_city, cities.last) - .and_delete(cities.first).only - end - end - - describe '.journal' do - specify { expect(CitiesIndex::City.journal).to be_a(Chewy::Journal) } - end -end diff --git a/spec/chewy/type/wrapper_spec.rb b/spec/chewy/type/wrapper_spec.rb deleted file mode 100644 index 434aaa1f1..000000000 --- a/spec/chewy/type/wrapper_spec.rb +++ /dev/null @@ -1,100 +0,0 @@ -require 'spec_helper' - -describe Chewy::Type::Wrapper do - before do - stub_class(:city) - stub_index(:cities) do - define_type City - end - end - - let(:city_type) { CitiesIndex::City } - - describe '.build' do - specify do - expect(city_type.build({}).attributes) - .to eq('id' => nil, '_score' => nil, '_explanation' => nil) - end - specify do - expect(city_type.build('_source' => {name: 'Martin'}).attributes) - .to eq('id' => nil, '_score' => nil, '_explanation' => nil, 'name' => 'Martin') - end - specify do - expect(city_type.build('_id' => 42).attributes) - .to eq('id' => 42, '_score' => nil, '_explanation' => nil) - end - specify do - expect(city_type.build('_id' => 42, '_source' => {'id' => 43}).attributes) - .to eq('id' => 43, '_score' => nil, '_explanation' => nil) - end - specify do - expect(city_type.build('_score' => 42, '_explanation' => {foo: 'bar'}).attributes) - .to eq('id' => nil, '_score' => 42, '_explanation' => {foo: 'bar'}) - end - specify do - expect(city_type.build('_score' => 42, 'borogoves' => {foo: 'bar'})._data) - .to eq('_score' => 42, 'borogoves' => {foo: 'bar'}) - end - end - - describe '#initialize' do - subject(:city) { city_type.new(name: 'Martin', age: 42) } - - it do - is_expected.to respond_to(:name) - .and respond_to(:age) - .and have_attributes( - name: 'Martin', - age: 42 - ) - end - - it { expect { city.population }.to raise_error(NoMethodError) } - - context 'highlight' do - subject(:city) do - city_type.new(name: 'Martin', age: 42) - .tap do |city| - city._data = { - 'highlight' => {'name' => ['Martin']} - } - end - end - - it do - is_expected.to respond_to(:name_highlight) - .and respond_to(:name_highlights) - .and have_attributes( - name: 'Martin', - name_highlight: 'Martin', - name_highlights: ['Martin'] - ) - end - end - end - - describe '#==' do - specify { expect(city_type.new(id: 42)).to eq(city_type.new(id: 42)) } - specify { expect(city_type.new(id: 42, age: 55)).to eq(city_type.new(id: 42, age: 54)) } - specify { expect(city_type.new(id: 42)).not_to eq(city_type.new(id: 43)) } - specify { expect(city_type.new(id: 42, age: 55)).not_to eq(city_type.new(id: 43, age: 55)) } - specify { expect(city_type.new(age: 55)).to eq(city_type.new(age: 55)) } - specify { expect(city_type.new(age: 55)).not_to eq(city_type.new(age: 54)) } - - specify { expect(city_type.new(id: '42')).to eq(City.new.tap { |m| allow(m).to receive_messages(id: 42) }) } - specify { expect(city_type.new(id: 42)).not_to eq(City.new.tap { |m| allow(m).to receive_messages(id: 43) }) } - specify { expect(city_type.new(id: 42)).not_to eq(Class.new) } - - context 'models', :orm do - before do - stub_model(:city) - stub_index(:cities) do - define_type City - end - end - specify { expect(city_type.new(id: '42')).to eq(City.new.tap { |m| allow(m).to receive_messages(id: 42) }) } - specify { expect(city_type.new(id: 42)).not_to eq(City.new.tap { |m| allow(m).to receive_messages(id: 43) }) } - specify { expect(city_type.new(id: 42)).not_to eq(Class.new) } - end - end -end diff --git a/spec/chewy/type_spec.rb b/spec/chewy/type_spec.rb deleted file mode 100644 index b51831d68..000000000 --- a/spec/chewy/type_spec.rb +++ /dev/null @@ -1,58 +0,0 @@ -require 'spec_helper' - -describe Chewy::Type do - describe '.derivable_name' do - specify { expect { Class.new(Chewy::Type).derivable_name }.to raise_error NotImplementedError } - - specify do - index = Class.new(Chewy::Index) { define_type :city } - expect(index::City.derivable_name).to be_nil - end - - specify do - stub_index(:places) { define_type :city } - expect(PlacesIndex::City.derivable_name).to eq('places#city') - end - - specify do - stub_index('namespace/places') { define_type :city } - expect(Namespace::PlacesIndex::City.derivable_name).to eq('namespace/places#city') - end - end - - describe '.types' do - subject { Class.new(Chewy::Type) } - specify { expect(subject.types).to eq([subject]) } - end - - describe '.scopes' do - before do - stub_index(:places) do - def self.by_id; end - - define_type :city do - def self.by_rating; end - - def self.by_name; end - end - end - end - - specify { expect(described_class.scopes).to eq([]) } - specify { expect(PlacesIndex::City.scopes).to match_array(%i[by_rating by_name]) } - specify { expect { PlacesIndex::City.non_existing_method_call }.to raise_error(NoMethodError) } - - specify { expect(PlacesIndex::City._default_import_options).to eq({}) } - specify do - expect { PlacesIndex::City.default_import_options(invalid_option: 'Yeah!') } - .to raise_error(ArgumentError) - end - - context 'default_import_options is set' do - let(:converter) { -> {} } - before { PlacesIndex::City.default_import_options(batch_size: 500, raw_import: converter) } - - specify { expect(PlacesIndex::City._default_import_options).to eq(batch_size: 500, raw_import: converter) } - end - end -end diff --git a/spec/chewy_spec.rb b/spec/chewy_spec.rb index 1f9637535..cf1c6d037 100644 --- a/spec/chewy_spec.rb +++ b/spec/chewy_spec.rb @@ -5,144 +5,29 @@ expect(Chewy::VERSION).not_to be nil end - describe '.derive_type' do + describe '.derive_name' do before do stub_const('SomeIndex', Class.new) - stub_index(:developers) do - define_type :developer - end - - stub_index('namespace/autocomplete') do - define_type :developer - end - end - - specify do - expect { described_class.derive_type('some#developers') } - .to raise_error(Chewy::UnderivableType, /SomeIndex/) - end - specify do - expect { described_class.derive_type('borogoves#developers') } - .to raise_error(Chewy::UnderivableType, /Borogoves/) - end - specify do - expect { described_class.derive_type('developers#borogoves') } - .to raise_error(Chewy::UnderivableType, /DevelopersIndex.*borogoves/) - end - - specify { expect(described_class.derive_type(DevelopersIndex::Developer)).to eq(DevelopersIndex::Developer) } - specify { expect(described_class.derive_type('developers_index')).to eq(DevelopersIndex::Developer) } - specify { expect(described_class.derive_type('developers')).to eq(DevelopersIndex::Developer) } - specify { expect(described_class.derive_type('developers#developer')).to eq(DevelopersIndex::Developer) } - specify do - expect(described_class.derive_type('namespace/autocomplete#developer')) - .to eq(Namespace::AutocompleteIndex::Developer) - end - end - - describe '.derive_types' do - before do - stub_const('SomeIndex', Class.new) + stub_index(:developers) - stub_index(:developers) do - define_type :developer - end - - stub_index('namespace/autocomplete') do - define_type :developer - end + stub_index('namespace/autocomplete') end specify do - expect { described_class.derive_types('some#developers') } - .to raise_error(Chewy::UnderivableType, /SomeIndex/) + expect { described_class.derive_name('some') } + .to raise_error(Chewy::UndefinedIndex, /SomeIndex/) end specify do - expect { described_class.derive_types('borogoves#developers') } - .to raise_error(Chewy::UnderivableType, /Borogoves/) - end - specify do - expect { described_class.derive_types('developers#borogoves') } - .to raise_error(Chewy::UnderivableType, /DevelopersIndex.*borogoves/) + expect { described_class.derive_name('borogoves') } + .to raise_error(Chewy::UndefinedIndex, /Borogoves/) end + specify { expect(described_class.derive_name(DevelopersIndex)).to eq(DevelopersIndex) } + specify { expect(described_class.derive_name('developers_index')).to eq(DevelopersIndex) } + specify { expect(described_class.derive_name('developers')).to eq(DevelopersIndex) } specify do - expect(described_class.derive_types(Namespace::AutocompleteIndex)) - .to match_array(Namespace::AutocompleteIndex.types) - end - specify { expect(described_class.derive_types(DevelopersIndex::Developer)).to eq([DevelopersIndex::Developer]) } - - specify { expect(described_class.derive_types('developers_index')).to eq([DevelopersIndex::Developer]) } - specify { expect(described_class.derive_types('developers')).to eq([DevelopersIndex::Developer]) } - specify { expect(described_class.derive_types('developers#developer')).to eq([DevelopersIndex::Developer]) } - specify do - expect(described_class.derive_types('namespace/autocomplete')).to match_array(Namespace::AutocompleteIndex.types) - end - specify do - expect(described_class.derive_types('namespace/autocomplete#developer')) - .to eq([Namespace::AutocompleteIndex::Developer]) - end - end - - describe '.create_type' do - before { stub_index(:cities) } - - context 'Symbol' do - subject { described_class.create_type(CitiesIndex, :city) } - - it { is_expected.to be_a Class } - it { is_expected.to be < Chewy::Type } - its(:name) { should == 'CitiesIndex::City' } - its(:index) { should == CitiesIndex } - its(:type_name) { should == 'city' } - end - - context 'simple model' do - before { stub_class(:city) } - subject { described_class.create_type(CitiesIndex, City) } - - it { is_expected.to be_a Class } - it { is_expected.to be < Chewy::Type } - its(:name) { should == 'CitiesIndex::City' } - its(:index) { should == CitiesIndex } - its(:type_name) { should == 'city' } - end - - context 'model scope', :orm do - before { stub_model(:city) } - subject { described_class.create_type(CitiesIndex, City.where(rating: 1)) } - - it { is_expected.to be_a Class } - it { is_expected.to be < Chewy::Type } - its(:name) { should == 'CitiesIndex::City' } - its(:index) { should == CitiesIndex } - its(:type_name) { should == 'city' } - end - - context 'Namespaced index' do - before { stub_class(:city) } - before { stub_index('namespace/cities') } - - subject { described_class.create_type(Namespace::CitiesIndex, City) } - - it { is_expected.to be_a Class } - it { is_expected.to be < Chewy::Type } - its(:name) { should == 'Namespace::CitiesIndex::City' } - its(:index) { should == Namespace::CitiesIndex } - its(:type_name) { should == 'city' } - end - - context 'Namespaced model' do - before { stub_class('namespace/city') } - - subject { described_class.create_type(CitiesIndex, Namespace::City) } - - it { is_expected.to be_a Class } - it { is_expected.to be < Chewy::Type } - its(:name) { should == 'CitiesIndex::City' } - its(:index) { should == CitiesIndex } - its(:type_name) { should == 'city' } + expect(described_class.derive_name('namespace/autocomplete')).to eq(Namespace::AutocompleteIndex) end end