chewy 7.1.0 → 7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +58 -0
- data/.rubocop.yml +13 -8
- data/.rubocop_todo.yml +110 -22
- data/CHANGELOG.md +53 -0
- data/Gemfile +0 -7
- data/Guardfile +3 -1
- data/README.md +282 -245
- data/chewy.gemspec +3 -5
- data/gemfiles/rails.5.2.activerecord.gemfile +8 -14
- data/gemfiles/rails.6.0.activerecord.gemfile +8 -14
- data/gemfiles/rails.6.1.activerecord.gemfile +8 -14
- data/lib/chewy.rb +21 -75
- data/lib/chewy/config.rb +40 -40
- data/lib/chewy/errors.rb +0 -12
- data/lib/chewy/fields/base.rb +11 -1
- data/lib/chewy/fields/root.rb +3 -4
- data/lib/chewy/index.rb +46 -87
- data/lib/chewy/index/actions.rb +51 -32
- data/lib/chewy/{type → index}/adapter/active_record.rb +12 -3
- data/lib/chewy/{type → index}/adapter/base.rb +2 -3
- data/lib/chewy/{type → index}/adapter/object.rb +27 -31
- data/lib/chewy/{type → index}/adapter/orm.rb +11 -14
- data/lib/chewy/{type → index}/crutch.rb +5 -5
- data/lib/chewy/{type → index}/import.rb +36 -27
- data/lib/chewy/{type → index}/import/bulk_builder.rb +15 -13
- data/lib/chewy/{type → index}/import/bulk_request.rb +6 -6
- data/lib/chewy/{type → index}/import/journal_builder.rb +10 -10
- data/lib/chewy/{type → index}/import/routine.rb +15 -14
- data/lib/chewy/{type → index}/mapping.rb +26 -31
- data/lib/chewy/{type → index}/observe.rb +9 -19
- data/lib/chewy/index/specification.rb +1 -0
- data/lib/chewy/{type → index}/syncer.rb +60 -57
- data/lib/chewy/{type → index}/witchcraft.rb +11 -7
- data/lib/chewy/{type → index}/wrapper.rb +2 -2
- data/lib/chewy/journal.rb +8 -8
- data/lib/chewy/minitest/helpers.rb +9 -13
- data/lib/chewy/minitest/search_index_receiver.rb +22 -26
- data/lib/chewy/railtie.rb +4 -2
- data/lib/chewy/rake_helper.rb +82 -107
- data/lib/chewy/rspec/update_index.rb +47 -43
- data/lib/chewy/search.rb +4 -17
- data/lib/chewy/search/loader.rb +18 -30
- data/lib/chewy/search/parameters.rb +4 -2
- data/lib/chewy/search/parameters/concerns/query_storage.rb +2 -2
- data/lib/chewy/search/parameters/source.rb +5 -1
- data/lib/chewy/search/query_proxy.rb +9 -2
- data/lib/chewy/search/request.rb +82 -86
- data/lib/chewy/search/response.rb +4 -4
- data/lib/chewy/search/scoping.rb +6 -7
- data/lib/chewy/search/scrolling.rb +11 -11
- data/lib/chewy/stash.rb +14 -22
- data/lib/chewy/strategy.rb +3 -19
- data/lib/chewy/strategy/sidekiq.rb +1 -0
- data/lib/chewy/version.rb +1 -1
- data/lib/generators/chewy/install_generator.rb +1 -1
- data/lib/tasks/chewy.rake +10 -22
- data/migration_guide.md +14 -0
- data/spec/chewy/config_spec.rb +14 -39
- data/spec/chewy/fields/base_spec.rb +412 -148
- data/spec/chewy/fields/root_spec.rb +16 -24
- data/spec/chewy/fields/time_fields_spec.rb +5 -5
- data/spec/chewy/index/actions_spec.rb +270 -24
- data/spec/chewy/{type → index}/adapter/active_record_spec.rb +68 -40
- data/spec/chewy/{type → index}/adapter/object_spec.rb +21 -6
- data/spec/chewy/{type → index}/import/bulk_builder_spec.rb +23 -31
- data/spec/chewy/{type → index}/import/bulk_request_spec.rb +5 -6
- data/spec/chewy/{type → index}/import/journal_builder_spec.rb +9 -15
- data/spec/chewy/{type → index}/import/routine_spec.rb +16 -16
- data/spec/chewy/{type → index}/import_spec.rb +102 -98
- data/spec/chewy/{type → index}/mapping_spec.rb +46 -54
- data/spec/chewy/index/observe_spec.rb +116 -0
- data/spec/chewy/index/settings_spec.rb +3 -1
- data/spec/chewy/index/specification_spec.rb +7 -17
- data/spec/chewy/{type → index}/syncer_spec.rb +14 -19
- data/spec/chewy/{type → index}/witchcraft_spec.rb +20 -22
- data/spec/chewy/index/wrapper_spec.rb +100 -0
- data/spec/chewy/index_spec.rb +59 -102
- data/spec/chewy/journal_spec.rb +9 -22
- data/spec/chewy/minitest/helpers_spec.rb +13 -15
- data/spec/chewy/minitest/search_index_receiver_spec.rb +22 -26
- data/spec/chewy/multi_search_spec.rb +4 -5
- data/spec/chewy/rake_helper_spec.rb +145 -55
- data/spec/chewy/rspec/update_index_spec.rb +74 -71
- data/spec/chewy/search/loader_spec.rb +19 -37
- data/spec/chewy/search/pagination/kaminari_examples.rb +3 -5
- data/spec/chewy/search/pagination/kaminari_spec.rb +1 -1
- data/spec/chewy/search/parameters/indices_spec.rb +2 -8
- data/spec/chewy/search/parameters/order_spec.rb +1 -1
- data/spec/chewy/search/parameters/query_storage_examples.rb +67 -21
- data/spec/chewy/search/parameters/search_after_spec.rb +4 -1
- data/spec/chewy/search/parameters/source_spec.rb +8 -2
- data/spec/chewy/search/parameters_spec.rb +12 -3
- data/spec/chewy/search/query_proxy_spec.rb +68 -17
- data/spec/chewy/search/request_spec.rb +222 -74
- data/spec/chewy/search/response_spec.rb +12 -12
- data/spec/chewy/search/scrolling_spec.rb +7 -9
- data/spec/chewy/search_spec.rb +32 -35
- data/spec/chewy/stash_spec.rb +9 -21
- data/spec/chewy/strategy/active_job_spec.rb +8 -8
- data/spec/chewy/strategy/atomic_spec.rb +9 -10
- data/spec/chewy/strategy/sidekiq_spec.rb +8 -8
- data/spec/chewy/strategy_spec.rb +19 -15
- data/spec/chewy_spec.rb +14 -100
- data/spec/spec_helper.rb +2 -21
- data/spec/support/active_record.rb +15 -5
- metadata +44 -103
- data/.circleci/config.yml +0 -214
- data/Appraisals +0 -81
- data/gemfiles/rails.5.2.mongoid.6.4.gemfile +0 -17
- data/gemfiles/sequel.4.45.gemfile +0 -11
- data/lib/chewy/search/pagination/will_paginate.rb +0 -43
- data/lib/chewy/strategy/resque.rb +0 -27
- data/lib/chewy/strategy/shoryuken.rb +0 -40
- data/lib/chewy/type.rb +0 -120
- data/lib/chewy/type/actions.rb +0 -43
- data/lib/chewy/type/adapter/mongoid.rb +0 -67
- data/lib/chewy/type/adapter/sequel.rb +0 -93
- data/lib/sequel/plugins/chewy_observe.rb +0 -63
- data/spec/chewy/search/pagination/will_paginate_examples.rb +0 -63
- data/spec/chewy/search/pagination/will_paginate_spec.rb +0 -23
- data/spec/chewy/strategy/resque_spec.rb +0 -46
- data/spec/chewy/strategy/shoryuken_spec.rb +0 -70
- data/spec/chewy/type/actions_spec.rb +0 -50
- data/spec/chewy/type/adapter/mongoid_spec.rb +0 -372
- data/spec/chewy/type/adapter/sequel_spec.rb +0 -472
- data/spec/chewy/type/observe_spec.rb +0 -137
- data/spec/chewy/type/wrapper_spec.rb +0 -100
- data/spec/chewy/type_spec.rb +0 -55
- data/spec/support/mongoid.rb +0 -93
- data/spec/support/sequel.rb +0 -80
|
@@ -64,12 +64,12 @@ module Chewy
|
|
|
64
64
|
end
|
|
65
65
|
alias_method :aggregations, :aggs
|
|
66
66
|
|
|
67
|
-
# {Chewy::
|
|
67
|
+
# {Chewy::Index} wrappers collection instantiated on top of hits.
|
|
68
68
|
#
|
|
69
|
-
# @return [Array<Chewy::
|
|
69
|
+
# @return [Array<Chewy::Index>]
|
|
70
70
|
def wrappers
|
|
71
71
|
@wrappers ||= hits.map do |hit|
|
|
72
|
-
@loader.
|
|
72
|
+
@loader.derive_index(hit['_index']).build(hit)
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
|
|
@@ -102,7 +102,7 @@ module Chewy
|
|
|
102
102
|
# end
|
|
103
103
|
# @see #wrappers
|
|
104
104
|
# @see #objects
|
|
105
|
-
# @return [{Chewy::
|
|
105
|
+
# @return [{Chewy::Index => Object}] a hash with wrappers as keys and ORM/ODM objects as values
|
|
106
106
|
def object_hash
|
|
107
107
|
@object_hash ||= wrappers.zip(objects).to_h
|
|
108
108
|
end
|
data/lib/chewy/search/scoping.rb
CHANGED
|
@@ -9,17 +9,16 @@ module Chewy
|
|
|
9
9
|
# query(match: {name: name})
|
|
10
10
|
# end
|
|
11
11
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# end
|
|
12
|
+
#
|
|
13
|
+
# def self.by_age(age)
|
|
14
|
+
# filter(term: {age: age})
|
|
16
15
|
# end
|
|
17
16
|
# end
|
|
18
17
|
#
|
|
19
18
|
# UsersIndex.limit(10).by_name('Martin')
|
|
20
19
|
# # => <UsersIndex::Query {..., :body=>{:size=>10, :query=>{:match=>{:name=>"Martin"}}}}>
|
|
21
|
-
# UsersIndex
|
|
22
|
-
# # => <UsersIndex::
|
|
20
|
+
# UsersIndex.limit(10).by_name('Martin').by_age(42)
|
|
21
|
+
# # => <UsersIndex::Query {..., :body=>{:size=>10, :query=>{:bool=>{
|
|
23
22
|
# # :must=>{:match=>{:name=>"Martin"}},
|
|
24
23
|
# # :filter=>{:term=>{:age=>42}}}}}}>
|
|
25
24
|
module Scoping
|
|
@@ -28,7 +27,7 @@ module Chewy
|
|
|
28
27
|
module ClassMethods
|
|
29
28
|
# The scopes stack.
|
|
30
29
|
#
|
|
31
|
-
# @return [Array<Chewy::Search::
|
|
30
|
+
# @return [Array<Chewy::Search::Request>] array of scopes
|
|
32
31
|
def scopes
|
|
33
32
|
Thread.current[:chewy_scopes] ||= []
|
|
34
33
|
end
|
|
@@ -40,6 +40,7 @@ module Chewy
|
|
|
40
40
|
yield(hits) if hits.present?
|
|
41
41
|
scroll_id = result['_scroll_id']
|
|
42
42
|
break if fetched >= total
|
|
43
|
+
|
|
43
44
|
result = perform_scroll(scroll: scroll, scroll_id: scroll_id)
|
|
44
45
|
end
|
|
45
46
|
ensure
|
|
@@ -61,17 +62,17 @@ module Chewy
|
|
|
61
62
|
# @example
|
|
62
63
|
# PlaceIndex.scroll_hits.map { |hit| hit['_id'] }
|
|
63
64
|
# @return [Enumerator] a standard ruby Enumerator
|
|
64
|
-
def scroll_hits(**options)
|
|
65
|
+
def scroll_hits(**options, &block)
|
|
65
66
|
return enum_for(:scroll_hits, **options) unless block_given?
|
|
66
67
|
|
|
67
68
|
scroll_batches(**options).each do |batch|
|
|
68
|
-
batch.each
|
|
69
|
+
batch.each(&block)
|
|
69
70
|
end
|
|
70
71
|
end
|
|
71
72
|
|
|
72
73
|
# @!method scroll_wrappers(batch_size: 1000, scroll: '1m')
|
|
73
74
|
# Iterates through the documents of the scope in batches. Yields
|
|
74
|
-
# each hit wrapped with {Chewy::
|
|
75
|
+
# each hit wrapped with {Chewy::Index}.
|
|
75
76
|
#
|
|
76
77
|
# @param batch_size [Integer] batch size obviously, replaces `size` query parameter
|
|
77
78
|
# @param scroll [String] cursor expiration time
|
|
@@ -79,7 +80,7 @@ module Chewy
|
|
|
79
80
|
# @overload scroll_wrappers(batch_size: 1000, scroll: '1m')
|
|
80
81
|
# @example
|
|
81
82
|
# PlaceIndex.scroll_wrappers { |object| p object.id }
|
|
82
|
-
# @yieldparam object [Chewy::
|
|
83
|
+
# @yieldparam object [Chewy::Index] block is executed for each hit object
|
|
83
84
|
#
|
|
84
85
|
# @overload scroll_wrappers(batch_size: 1000, scroll: '1m')
|
|
85
86
|
# @example
|
|
@@ -89,7 +90,7 @@ module Chewy
|
|
|
89
90
|
return enum_for(:scroll_wrappers, **options) unless block_given?
|
|
90
91
|
|
|
91
92
|
scroll_hits(**options).each do |hit|
|
|
92
|
-
yield loader.
|
|
93
|
+
yield loader.derive_index(hit['_index']).build(hit)
|
|
93
94
|
end
|
|
94
95
|
end
|
|
95
96
|
|
|
@@ -113,12 +114,12 @@ module Chewy
|
|
|
113
114
|
# @example
|
|
114
115
|
# PlaceIndex.scroll_objects.map { |record| record.id }
|
|
115
116
|
# @return [Enumerator] a standard ruby Enumerator
|
|
116
|
-
def scroll_objects(**options)
|
|
117
|
+
def scroll_objects(**options, &block)
|
|
117
118
|
return enum_for(:scroll_objects, **options) unless block_given?
|
|
118
119
|
|
|
119
120
|
except(:source, :stored_fields, :script_fields, :docvalue_fields)
|
|
120
121
|
.source(false).scroll_batches(**options).each do |batch|
|
|
121
|
-
loader.load(batch).each
|
|
122
|
+
loader.load(batch).each(&block)
|
|
122
123
|
end
|
|
123
124
|
end
|
|
124
125
|
alias_method :scroll_records, :scroll_objects
|
|
@@ -127,10 +128,9 @@ module Chewy
|
|
|
127
128
|
private
|
|
128
129
|
|
|
129
130
|
def perform_scroll(body)
|
|
130
|
-
ActiveSupport::Notifications.instrument 'search_query.chewy',
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
end
|
|
131
|
+
ActiveSupport::Notifications.instrument 'search_query.chewy', notification_payload(request: body) do
|
|
132
|
+
Chewy.client.scroll(body)
|
|
133
|
+
end
|
|
134
134
|
end
|
|
135
135
|
end
|
|
136
136
|
end
|
data/lib/chewy/stash.rb
CHANGED
|
@@ -9,11 +9,9 @@ module Chewy
|
|
|
9
9
|
class Specification < Chewy::Index
|
|
10
10
|
index_name 'chewy_specifications'
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
default_import_options journal: false
|
|
12
|
+
default_import_options journal: false
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
end
|
|
14
|
+
field :specification, type: 'binary'
|
|
17
15
|
end
|
|
18
16
|
|
|
19
17
|
class Journal < Chewy::Index
|
|
@@ -43,32 +41,26 @@ module Chewy
|
|
|
43
41
|
# @param indices [Chewy::Index, Array<Chewy::Index>]
|
|
44
42
|
def self.for(*something)
|
|
45
43
|
something = something.flatten.compact
|
|
46
|
-
|
|
47
|
-
return none if something.present? &&
|
|
44
|
+
indexes = something.flat_map { |s| Chewy.derive_name(s) }
|
|
45
|
+
return none if something.present? && indexes.blank?
|
|
46
|
+
|
|
48
47
|
scope = all
|
|
49
|
-
|
|
48
|
+
indexes.each do |index|
|
|
50
49
|
scope = scope.or(filter(term: {index_name: index.derivable_name}))
|
|
51
50
|
end
|
|
52
51
|
scope
|
|
53
52
|
end
|
|
54
53
|
|
|
55
|
-
|
|
56
|
-
default_import_options journal: false
|
|
54
|
+
default_import_options journal: false
|
|
57
55
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
field :created_at, type: 'date'
|
|
63
|
-
|
|
64
|
-
def type
|
|
65
|
-
@type ||= Chewy.derive_type("#{index_name}##{type_name}")
|
|
66
|
-
end
|
|
56
|
+
field :index_name, type: 'keyword'
|
|
57
|
+
field :action, type: 'keyword'
|
|
58
|
+
field :references, type: 'binary'
|
|
59
|
+
field :created_at, type: 'date'
|
|
67
60
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
end
|
|
61
|
+
def references
|
|
62
|
+
@references ||= Array.wrap(@attributes['references']).map do |item|
|
|
63
|
+
JSON.load(Base64.decode64(item)) # rubocop:disable Security/JSONLoad
|
|
72
64
|
end
|
|
73
65
|
end
|
|
74
66
|
end
|
data/lib/chewy/strategy.rb
CHANGED
|
@@ -3,13 +3,6 @@ require 'chewy/strategy/bypass'
|
|
|
3
3
|
require 'chewy/strategy/urgent'
|
|
4
4
|
require 'chewy/strategy/atomic'
|
|
5
5
|
|
|
6
|
-
begin
|
|
7
|
-
require 'resque'
|
|
8
|
-
require 'chewy/strategy/resque'
|
|
9
|
-
rescue LoadError
|
|
10
|
-
nil
|
|
11
|
-
end
|
|
12
|
-
|
|
13
6
|
begin
|
|
14
7
|
require 'sidekiq'
|
|
15
8
|
require 'chewy/strategy/sidekiq'
|
|
@@ -17,13 +10,6 @@ rescue LoadError
|
|
|
17
10
|
nil
|
|
18
11
|
end
|
|
19
12
|
|
|
20
|
-
begin
|
|
21
|
-
require 'shoryuken'
|
|
22
|
-
require 'chewy/strategy/shoryuken'
|
|
23
|
-
rescue LoadError
|
|
24
|
-
nil
|
|
25
|
-
end
|
|
26
|
-
|
|
27
13
|
begin
|
|
28
14
|
require 'active_job'
|
|
29
15
|
require 'chewy/strategy/active_job'
|
|
@@ -60,6 +46,7 @@ module Chewy
|
|
|
60
46
|
|
|
61
47
|
def pop
|
|
62
48
|
raise "Can't pop root strategy" if @stack.one?
|
|
49
|
+
|
|
63
50
|
result = @stack.pop.tap(&:leave)
|
|
64
51
|
debug "[#{@stack.size}] -> #{result.name}, now #{current.name}" if @stack.size > 1
|
|
65
52
|
result
|
|
@@ -75,17 +62,14 @@ module Chewy
|
|
|
75
62
|
private
|
|
76
63
|
|
|
77
64
|
def debug(string)
|
|
78
|
-
return unless Chewy.logger
|
|
65
|
+
return unless Chewy.logger&.debug?
|
|
66
|
+
|
|
79
67
|
line = caller.detect { |l| l !~ %r{lib/chewy/strategy.rb:|lib/chewy.rb:} }
|
|
80
68
|
Chewy.logger.debug(["Chewy strategies stack: #{string}", line.sub(/:in\s.+$/, '')].join(' @ '))
|
|
81
69
|
end
|
|
82
70
|
|
|
83
71
|
def resolve(name)
|
|
84
72
|
"Chewy::Strategy::#{name.to_s.camelize}".safe_constantize or raise "Can't find update strategy `#{name}`"
|
|
85
|
-
rescue NameError => ex
|
|
86
|
-
# WORKAROUND: Strange behavior of `safe_constantize` with mongoid gem
|
|
87
|
-
raise "Can't find update strategy `#{name}`" if ex.name.to_s.demodulize == name.to_s.camelize
|
|
88
|
-
raise
|
|
89
73
|
end
|
|
90
74
|
end
|
|
91
75
|
end
|
data/lib/chewy/version.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Chewy
|
|
2
2
|
module Generators
|
|
3
3
|
class InstallGenerator < Rails::Generators::Base
|
|
4
|
-
source_root File.expand_path('
|
|
4
|
+
source_root File.expand_path('../templates', __dir__)
|
|
5
5
|
|
|
6
6
|
def copy_configuration
|
|
7
7
|
template 'chewy.yml', 'config/chewy.yml'
|
data/lib/tasks/chewy.rake
CHANGED
|
@@ -47,6 +47,16 @@ namespace :chewy do
|
|
|
47
47
|
Chewy::RakeHelper.sync(except: processed)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
desc 'Reindex data from source index to destination index'
|
|
51
|
+
task :reindex, %i[source dest] => :environment do |_task, args|
|
|
52
|
+
Chewy::RakeHelper.reindex(source: args[:source], dest: args[:dest])
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
desc 'Update mapping of exising index with body hash'
|
|
56
|
+
task :update_mapping, %i[index_name] => :environment do |_task, args|
|
|
57
|
+
Chewy::RakeHelper.update_mapping(name: args[:name])
|
|
58
|
+
end
|
|
59
|
+
|
|
50
60
|
namespace :parallel do
|
|
51
61
|
desc 'Parallel version of `rake chewy:reset`'
|
|
52
62
|
task reset: :environment do |_task, args|
|
|
@@ -87,26 +97,4 @@ namespace :chewy do
|
|
|
87
97
|
Chewy::RakeHelper.journal_clean(**parse_journal_args(args.extras))
|
|
88
98
|
end
|
|
89
99
|
end
|
|
90
|
-
|
|
91
|
-
task apply_changes_from: :environment do |_task, args|
|
|
92
|
-
ActiveSupport::Deprecation.warn '`rake chewy:apply_changes_from` is deprecated and will be removed soon, use `rake chewy:journal:apply` instead'
|
|
93
|
-
|
|
94
|
-
Chewy::RakeHelper.subscribed_task_stats do
|
|
95
|
-
params = args.extras
|
|
96
|
-
|
|
97
|
-
if params.empty?
|
|
98
|
-
puts 'Please specify a timestamp like chewy:apply_changes_from[1469528705]'
|
|
99
|
-
else
|
|
100
|
-
timestamp, retries = params
|
|
101
|
-
time = Time.at(timestamp.to_i)
|
|
102
|
-
Chewy::Journal.new.apply(time, retries: (retries.to_i if retries))
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
task clean_journal: :environment do |_task, args|
|
|
108
|
-
ActiveSupport::Deprecation.warn '`rake chewy:clean_journal` is deprecated and will be removed soon, use `rake chewy:journal:clean` instead'
|
|
109
|
-
|
|
110
|
-
Chewy::Journal.new.clean(args.extras.first)
|
|
111
|
-
end
|
|
112
100
|
end
|
data/migration_guide.md
CHANGED
|
@@ -17,6 +17,20 @@ In order to upgrade Chewy 6/Elasticsearch 6 to Chewy 7/Elasticsearch 7 in the mo
|
|
|
17
17
|
* Run your test suite on Chewy 7.1 / Elasticsearch 7
|
|
18
18
|
* Run manual tests on Chewy 7.1 / Elasticsearch 7
|
|
19
19
|
* Upgrade to Chewy 7.1
|
|
20
|
+
* Upgrade to Chewy 7.2:
|
|
21
|
+
* Remove all the the `Chewy::Type` class usages, e.g. remove `CitiesIndex::City` / `CitiesIndex.city`
|
|
22
|
+
* `CitiesIndex::City.import! ...` becomes `CitiesIndex.import! ...`
|
|
23
|
+
* Update indexes with simplified DSL:
|
|
24
|
+
* `define_type` block -> `index_scope` clause
|
|
25
|
+
* it can be omitted completely, if you don't need to specify the scope or options, e.g. `name`
|
|
26
|
+
* Remove type names from string representations:
|
|
27
|
+
* in `update_index` ActiveRecord helper and RSpec matcher, e.g.
|
|
28
|
+
* `update_index('cities#city')` -> `update_index('cities')`
|
|
29
|
+
* `update_index(UsersIndex::User)` -> `update_index(UsersIndex)`
|
|
30
|
+
* in rake tasks (e.g. `rake chewy:update[cities#city]` -> `rake chewy:update[cities]`)
|
|
31
|
+
* rake tasks output is also changed (e.g. `Imported CitiesIndex::City in 1s, stats: index 3` -> `Imported CitiesIndex in 1s, stats: index 3`)
|
|
32
|
+
* Use index name instead of type name in loader additional scope
|
|
33
|
+
* e.g. `CitiesIndex.filter(...).load(city: {scope: City.where(...)})` -> `CitiesIndex.filter(...).load(cities: {scope: City.where(...)})`
|
|
20
34
|
|
|
21
35
|
## Chewy 5/Elasticsearch 5 to Chewy 6/Elasticsearch 6
|
|
22
36
|
|
data/spec/chewy/config_spec.rb
CHANGED
|
@@ -8,6 +8,7 @@ describe Chewy::Config do
|
|
|
8
8
|
its(:transport_logger) { should be_nil }
|
|
9
9
|
its(:root_strategy) { should == :base }
|
|
10
10
|
its(:request_strategy) { should == :atomic }
|
|
11
|
+
its(:console_strategy) { should == :urgent }
|
|
11
12
|
its(:use_after_commit_callbacks) { should == true }
|
|
12
13
|
its(:indices_path) { should == 'app/chewy' }
|
|
13
14
|
its(:reset_disable_refresh_interval) { should == false }
|
|
@@ -55,58 +56,19 @@ describe Chewy::Config do
|
|
|
55
56
|
context 'nothing is defined' do
|
|
56
57
|
before do
|
|
57
58
|
hide_const('Kaminari')
|
|
58
|
-
hide_const('WillPaginate')
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
specify do
|
|
62
62
|
expect(subject.search_class.included_modules)
|
|
63
63
|
.not_to include(Chewy::Search::Pagination::Kaminari)
|
|
64
64
|
end
|
|
65
|
-
|
|
66
|
-
specify do
|
|
67
|
-
expect(subject.search_class.included_modules)
|
|
68
|
-
.not_to include(Chewy::Search::Pagination::WillPaginate)
|
|
69
|
-
end
|
|
70
65
|
end
|
|
71
66
|
|
|
72
67
|
context 'kaminari' do
|
|
73
|
-
before { hide_const('WillPaginate') }
|
|
74
|
-
|
|
75
|
-
specify do
|
|
76
|
-
expect(subject.search_class.included_modules)
|
|
77
|
-
.to include(Chewy::Search::Pagination::Kaminari)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
specify do
|
|
81
|
-
expect(subject.search_class.included_modules)
|
|
82
|
-
.not_to include(Chewy::Search::Pagination::WillPaginate)
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
context 'will_paginate' do
|
|
87
|
-
before { hide_const('Kaminari') }
|
|
88
|
-
|
|
89
|
-
specify do
|
|
90
|
-
expect(subject.search_class.included_modules)
|
|
91
|
-
.not_to include(Chewy::Search::Pagination::Kaminari)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
specify do
|
|
95
|
-
expect(subject.search_class.included_modules)
|
|
96
|
-
.to include(Chewy::Search::Pagination::WillPaginate)
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
context 'both are defined' do
|
|
101
68
|
specify do
|
|
102
69
|
expect(subject.search_class.included_modules)
|
|
103
70
|
.to include(Chewy::Search::Pagination::Kaminari)
|
|
104
71
|
end
|
|
105
|
-
|
|
106
|
-
specify do
|
|
107
|
-
expect(subject.search_class.included_modules)
|
|
108
|
-
.not_to include(Chewy::Search::Pagination::WillPaginate)
|
|
109
|
-
end
|
|
110
72
|
end
|
|
111
73
|
end
|
|
112
74
|
|
|
@@ -133,4 +95,17 @@ describe Chewy::Config do
|
|
|
133
95
|
end
|
|
134
96
|
end
|
|
135
97
|
end
|
|
98
|
+
|
|
99
|
+
describe '.console_strategy' do
|
|
100
|
+
context 'sets .console_strategy' do
|
|
101
|
+
let(:default_strategy) { subject.console_strategy }
|
|
102
|
+
let(:new_strategy) { :atomic }
|
|
103
|
+
after { subject.console_strategy = default_strategy }
|
|
104
|
+
|
|
105
|
+
specify do
|
|
106
|
+
expect { subject.console_strategy = new_strategy }
|
|
107
|
+
.to change { subject.console_strategy }.to(new_strategy)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
136
111
|
end
|
|
@@ -10,8 +10,12 @@ describe Chewy::Fields::Base do
|
|
|
10
10
|
specify { expect(field.compose(double(value: 'hello'))).to eq(name: 'hello') }
|
|
11
11
|
specify { expect(field.compose(double(value: %w[hello world]))).to eq(name: %w[hello world]) }
|
|
12
12
|
|
|
13
|
-
specify
|
|
14
|
-
|
|
13
|
+
specify do
|
|
14
|
+
expect(described_class.new(:name, value: :last_name).compose(double(last_name: 'hello'))).to eq(name: 'hello')
|
|
15
|
+
end
|
|
16
|
+
specify do
|
|
17
|
+
expect(described_class.new(:name, value: :last_name).compose('last_name' => 'hello')).to eq(name: 'hello')
|
|
18
|
+
end
|
|
15
19
|
specify { expect(described_class.new(:name).compose(double(name: 'hello'))).to eq(name: 'hello') }
|
|
16
20
|
specify { expect(described_class.new(:false_value).compose(false_value: false)).to eq(false_value: false) }
|
|
17
21
|
specify { expect(described_class.new(:true_value).compose(true_value: true)).to eq(true_value: true) }
|
|
@@ -40,9 +44,24 @@ describe Chewy::Fields::Base do
|
|
|
40
44
|
end
|
|
41
45
|
|
|
42
46
|
context 'parent objects' do
|
|
43
|
-
let!(:country)
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
let!(:country) do
|
|
48
|
+
described_class.new(:name, value: lambda { |country, crutches|
|
|
49
|
+
country.cities.map do |city|
|
|
50
|
+
double(districts: city.districts, name: crutches.city_name)
|
|
51
|
+
end
|
|
52
|
+
})
|
|
53
|
+
end
|
|
54
|
+
let!(:city) do
|
|
55
|
+
described_class.new(:name, value: lambda { |city, country, crutches|
|
|
56
|
+
city.districts.map do |district|
|
|
57
|
+
[district, country.name, crutches.suffix]
|
|
58
|
+
end
|
|
59
|
+
})
|
|
60
|
+
end
|
|
61
|
+
let(:district_value) { ->(district, city, country, crutches) { [district, city.name, country.name, crutches] } }
|
|
62
|
+
let!(:district) do
|
|
63
|
+
described_class.new(:name, value: district_value)
|
|
64
|
+
end
|
|
46
65
|
let(:crutches) { double(suffix: 'suffix', city_name: 'Bangkok') }
|
|
47
66
|
|
|
48
67
|
before do
|
|
@@ -122,14 +141,12 @@ describe Chewy::Fields::Base do
|
|
|
122
141
|
context 'default field type' do
|
|
123
142
|
before do
|
|
124
143
|
stub_index(:events) do
|
|
125
|
-
|
|
144
|
+
field :id
|
|
145
|
+
field :category do
|
|
126
146
|
field :id
|
|
127
|
-
field :
|
|
147
|
+
field :licenses do
|
|
128
148
|
field :id
|
|
129
|
-
field :
|
|
130
|
-
field :id
|
|
131
|
-
field :created_at, type: 'time'
|
|
132
|
-
end
|
|
149
|
+
field :created_at, type: 'time'
|
|
133
150
|
end
|
|
134
151
|
end
|
|
135
152
|
end
|
|
@@ -143,18 +160,20 @@ describe Chewy::Fields::Base do
|
|
|
143
160
|
end
|
|
144
161
|
|
|
145
162
|
specify do
|
|
146
|
-
expect(EventsIndex
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
163
|
+
expect(EventsIndex.mappings_hash).to eq(
|
|
164
|
+
mappings: {
|
|
165
|
+
properties: {
|
|
166
|
+
id: {type: 'integer'},
|
|
167
|
+
category: {
|
|
168
|
+
type: 'object',
|
|
169
|
+
properties: {
|
|
170
|
+
id: {type: 'integer'},
|
|
171
|
+
licenses: {
|
|
172
|
+
type: 'object',
|
|
173
|
+
properties: {
|
|
174
|
+
id: {type: 'integer'},
|
|
175
|
+
created_at: {type: 'time'}
|
|
176
|
+
}
|
|
158
177
|
}
|
|
159
178
|
}
|
|
160
179
|
}
|
|
@@ -167,153 +186,191 @@ describe Chewy::Fields::Base do
|
|
|
167
186
|
context 'objects, hashes and arrays' do
|
|
168
187
|
before do
|
|
169
188
|
stub_index(:events) do
|
|
170
|
-
|
|
189
|
+
field :id
|
|
190
|
+
field :category do
|
|
171
191
|
field :id
|
|
172
|
-
field :
|
|
192
|
+
field :licenses do
|
|
173
193
|
field :id
|
|
174
|
-
field :
|
|
175
|
-
field :id
|
|
176
|
-
field :name
|
|
177
|
-
end
|
|
194
|
+
field :name
|
|
178
195
|
end
|
|
179
196
|
end
|
|
180
197
|
end
|
|
181
198
|
end
|
|
182
199
|
|
|
183
|
-
# rubocop:disable Style/BracesAroundHashParameters
|
|
184
200
|
specify do
|
|
185
|
-
expect(
|
|
186
|
-
id: 1, category: {id: 2, licenses: {id: 3, name: 'Name'}}
|
|
187
|
-
|
|
201
|
+
expect(
|
|
202
|
+
EventsIndex.root.compose({id: 1, category: {id: 2, licenses: {id: 3, name: 'Name'}}})
|
|
203
|
+
).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}})
|
|
188
204
|
end
|
|
189
205
|
|
|
190
206
|
specify do
|
|
191
|
-
expect(
|
|
192
|
-
{id:
|
|
193
|
-
|
|
194
|
-
|
|
207
|
+
expect(
|
|
208
|
+
EventsIndex.root.compose({id: 1, category: [
|
|
209
|
+
{id: 2, 'licenses' => {id: 3, name: 'Name1'}},
|
|
210
|
+
{id: 4, licenses: nil}
|
|
211
|
+
]})
|
|
212
|
+
).to eq('id' => 1, 'category' => [
|
|
195
213
|
{'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name1'}},
|
|
196
214
|
{'id' => 4, 'licenses' => nil.as_json}
|
|
197
215
|
])
|
|
198
216
|
end
|
|
199
217
|
|
|
200
218
|
specify do
|
|
201
|
-
expect(
|
|
202
|
-
{
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
219
|
+
expect(
|
|
220
|
+
EventsIndex.root.compose({
|
|
221
|
+
'id' => 1,
|
|
222
|
+
category: {
|
|
223
|
+
id: 2, licenses: [
|
|
224
|
+
{id: 3, name: 'Name1'},
|
|
225
|
+
{id: 4, name: 'Name2'}
|
|
226
|
+
]
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
).to eq(
|
|
230
|
+
'id' => 1,
|
|
231
|
+
'category' => {
|
|
232
|
+
'id' => 2,
|
|
233
|
+
'licenses' => [
|
|
234
|
+
{'id' => 3, 'name' => 'Name1'},
|
|
235
|
+
{'id' => 4, 'name' => 'Name2'}
|
|
236
|
+
]
|
|
237
|
+
}
|
|
238
|
+
)
|
|
206
239
|
end
|
|
207
240
|
|
|
208
241
|
specify do
|
|
209
|
-
expect(
|
|
210
|
-
{id:
|
|
211
|
-
{id:
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
242
|
+
expect(
|
|
243
|
+
EventsIndex.root.compose({id: 1, category: [
|
|
244
|
+
{id: 2, licenses: [
|
|
245
|
+
{id: 3, 'name' => 'Name1'}, {id: 4, name: 'Name2'}
|
|
246
|
+
]},
|
|
247
|
+
{id: 5, licenses: []}
|
|
248
|
+
]})
|
|
249
|
+
).to eq(
|
|
250
|
+
'id' => 1,
|
|
251
|
+
'category' => [
|
|
252
|
+
{'id' => 2, 'licenses' => [
|
|
253
|
+
{'id' => 3, 'name' => 'Name1'},
|
|
254
|
+
{'id' => 4, 'name' => 'Name2'}
|
|
255
|
+
]},
|
|
256
|
+
{'id' => 5, 'licenses' => []}
|
|
257
|
+
]
|
|
258
|
+
)
|
|
220
259
|
end
|
|
221
|
-
# rubocop:enable Style/BracesAroundHashParameters
|
|
222
|
-
|
|
223
260
|
specify do
|
|
224
|
-
expect(
|
|
225
|
-
|
|
226
|
-
)
|
|
261
|
+
expect(
|
|
262
|
+
EventsIndex.root.compose(double(id: 1, category: double(id: 2, licenses: double(id: 3, name: 'Name'))))
|
|
263
|
+
).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}})
|
|
227
264
|
end
|
|
228
265
|
|
|
229
266
|
specify do
|
|
230
|
-
expect(
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
267
|
+
expect(
|
|
268
|
+
EventsIndex.root.compose(double(id: 1, category: [
|
|
269
|
+
double(id: 2, licenses: double(id: 3, name: 'Name1')),
|
|
270
|
+
double(id: 4, licenses: nil)
|
|
271
|
+
]))
|
|
272
|
+
).to eq('id' => 1, 'category' => [
|
|
234
273
|
{'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name1'}},
|
|
235
274
|
{'id' => 4, 'licenses' => nil.as_json}
|
|
236
275
|
])
|
|
237
276
|
end
|
|
238
277
|
|
|
239
278
|
specify do
|
|
240
|
-
expect(
|
|
241
|
-
double(id:
|
|
242
|
-
|
|
279
|
+
expect(
|
|
280
|
+
EventsIndex.root.compose(double(id: 1, category: double(id: 2, licenses: [
|
|
281
|
+
double(id: 3, name: 'Name1'), double(id: 4, name: 'Name2')
|
|
282
|
+
])))
|
|
283
|
+
).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => [
|
|
243
284
|
{'id' => 3, 'name' => 'Name1'}, {'id' => 4, 'name' => 'Name2'}
|
|
244
285
|
]})
|
|
245
286
|
end
|
|
246
287
|
|
|
247
288
|
specify do
|
|
248
|
-
expect(
|
|
249
|
-
double(id:
|
|
250
|
-
double(id:
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
289
|
+
expect(
|
|
290
|
+
EventsIndex.root.compose(double(id: 1, category: [
|
|
291
|
+
double(id: 2, licenses: [
|
|
292
|
+
double(id: 3, name: 'Name1'), double(id: 4, name: 'Name2')
|
|
293
|
+
]),
|
|
294
|
+
double(id: 5, licenses: [])
|
|
295
|
+
]))
|
|
296
|
+
).to eq(
|
|
297
|
+
'id' => 1, 'category' => [
|
|
298
|
+
{'id' => 2, 'licenses' => [
|
|
299
|
+
{'id' => 3, 'name' => 'Name1'}, {'id' => 4, 'name' => 'Name2'}
|
|
300
|
+
]},
|
|
301
|
+
{'id' => 5, 'licenses' => []}
|
|
302
|
+
]
|
|
303
|
+
)
|
|
259
304
|
end
|
|
260
305
|
end
|
|
261
306
|
|
|
262
307
|
context 'custom methods' do
|
|
263
308
|
before do
|
|
264
309
|
stub_index(:events) do
|
|
265
|
-
|
|
310
|
+
field :id, type: 'integer'
|
|
311
|
+
field :category, value: -> { categories } do
|
|
266
312
|
field :id, type: 'integer'
|
|
267
|
-
field :
|
|
313
|
+
field :licenses, value: -> { license } do
|
|
268
314
|
field :id, type: 'integer'
|
|
269
|
-
field :
|
|
270
|
-
field :id, type: 'integer'
|
|
271
|
-
field :name
|
|
272
|
-
end
|
|
315
|
+
field :name
|
|
273
316
|
end
|
|
274
317
|
end
|
|
275
318
|
end
|
|
276
319
|
end
|
|
277
320
|
|
|
278
321
|
specify do
|
|
279
|
-
expect(
|
|
280
|
-
|
|
281
|
-
|
|
322
|
+
expect(
|
|
323
|
+
EventsIndex.root.compose(
|
|
324
|
+
double(
|
|
325
|
+
id: 1, categories: double(
|
|
326
|
+
id: 2, license: double(
|
|
327
|
+
id: 3, name: 'Name'
|
|
328
|
+
)
|
|
329
|
+
)
|
|
330
|
+
)
|
|
331
|
+
)
|
|
332
|
+
).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}})
|
|
282
333
|
end
|
|
283
334
|
end
|
|
284
335
|
|
|
285
336
|
context 'objects and multi_fields' do
|
|
286
337
|
before do
|
|
287
338
|
stub_index(:events) do
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
field :
|
|
291
|
-
field :raw, analyzer: 'my_own'
|
|
292
|
-
end
|
|
293
|
-
field :category, type: 'object'
|
|
339
|
+
field :id, type: 'integer'
|
|
340
|
+
field :name, type: 'integer' do
|
|
341
|
+
field :raw, analyzer: 'my_own'
|
|
294
342
|
end
|
|
343
|
+
field :category, type: 'object'
|
|
295
344
|
end
|
|
296
345
|
end
|
|
297
346
|
|
|
298
347
|
specify do
|
|
299
|
-
expect(EventsIndex
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
348
|
+
expect(EventsIndex.mappings_hash).to eq(
|
|
349
|
+
mappings: {
|
|
350
|
+
properties: {
|
|
351
|
+
id: {type: 'integer'},
|
|
352
|
+
name: {
|
|
353
|
+
type: 'integer',
|
|
354
|
+
fields: {
|
|
355
|
+
raw: {analyzer: 'my_own', type: Chewy.default_field_type}
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
category: {type: 'object'}
|
|
359
|
+
}
|
|
309
360
|
}
|
|
310
361
|
)
|
|
311
362
|
end
|
|
312
363
|
|
|
313
364
|
specify do
|
|
314
|
-
expect(
|
|
315
|
-
|
|
316
|
-
|
|
365
|
+
expect(
|
|
366
|
+
EventsIndex.root.compose(
|
|
367
|
+
double(
|
|
368
|
+
id: 1, name: 'Jonny', category: double(
|
|
369
|
+
id: 2, as_json: {'name' => 'Borogoves'}
|
|
370
|
+
)
|
|
371
|
+
)
|
|
372
|
+
)
|
|
373
|
+
).to eq(
|
|
317
374
|
'id' => 1,
|
|
318
375
|
'name' => 'Jonny',
|
|
319
376
|
'category' => {'name' => 'Borogoves'}
|
|
@@ -321,12 +378,14 @@ describe Chewy::Fields::Base do
|
|
|
321
378
|
end
|
|
322
379
|
|
|
323
380
|
specify do
|
|
324
|
-
expect(
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
381
|
+
expect(
|
|
382
|
+
EventsIndex.root.compose(
|
|
383
|
+
double(id: 1, name: 'Jonny', category: [
|
|
384
|
+
double(id: 2, as_json: {'name' => 'Borogoves1'}),
|
|
385
|
+
double(id: 3, as_json: {'name' => 'Borogoves2'})
|
|
386
|
+
])
|
|
387
|
+
)
|
|
388
|
+
).to eq(
|
|
330
389
|
'id' => 1,
|
|
331
390
|
'name' => 'Jonny',
|
|
332
391
|
'category' => [
|
|
@@ -337,56 +396,262 @@ describe Chewy::Fields::Base do
|
|
|
337
396
|
end
|
|
338
397
|
end
|
|
339
398
|
|
|
340
|
-
context '
|
|
399
|
+
context 'ignore_blank option for field method', :orm do
|
|
341
400
|
before do
|
|
401
|
+
stub_model(:location)
|
|
342
402
|
stub_model(:city)
|
|
343
403
|
stub_model(:country)
|
|
344
404
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
else
|
|
351
|
-
Country.has_many :cities, order: :id
|
|
352
|
-
end
|
|
353
|
-
when :mongoid
|
|
354
|
-
if Mongoid::VERSION.start_with?('6')
|
|
355
|
-
City.belongs_to :country, optional: true
|
|
356
|
-
else
|
|
357
|
-
City.belongs_to :country
|
|
358
|
-
end
|
|
359
|
-
Country.has_many :cities, order: :id.asc
|
|
360
|
-
when :sequel
|
|
361
|
-
City.many_to_one :country
|
|
362
|
-
Country.one_to_many :cities, order: :id
|
|
363
|
-
end
|
|
405
|
+
City.belongs_to :country
|
|
406
|
+
Location.belongs_to :city
|
|
407
|
+
City.has_one :location, -> { order :id }
|
|
408
|
+
Country.has_many :cities, -> { order :id }
|
|
409
|
+
end
|
|
364
410
|
|
|
365
|
-
|
|
366
|
-
|
|
411
|
+
context 'text fields with and without ignore_blank option' do
|
|
412
|
+
before do
|
|
413
|
+
stub_index(:countries) do
|
|
414
|
+
index_scope Country
|
|
367
415
|
field :id
|
|
368
416
|
field :cities do
|
|
369
417
|
field :id
|
|
370
418
|
field :name
|
|
419
|
+
field :historical_name, ignore_blank: false
|
|
420
|
+
field :description, ignore_blank: true
|
|
371
421
|
end
|
|
372
422
|
end
|
|
373
423
|
end
|
|
424
|
+
|
|
425
|
+
let(:country_with_cities) do
|
|
426
|
+
cities = [
|
|
427
|
+
City.create!(id: 1, name: '', historical_name: '', description: ''),
|
|
428
|
+
City.create!(id: 2, name: '', historical_name: '', description: '')
|
|
429
|
+
]
|
|
430
|
+
|
|
431
|
+
Country.create!(id: 1, cities: cities)
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
specify do
|
|
435
|
+
expect(CountriesIndex.root.compose(country_with_cities)).to eq(
|
|
436
|
+
'id' => 1, 'cities' => [
|
|
437
|
+
{'id' => 1, 'name' => '', 'historical_name' => ''},
|
|
438
|
+
{'id' => 2, 'name' => '', 'historical_name' => ''}
|
|
439
|
+
]
|
|
440
|
+
)
|
|
441
|
+
end
|
|
374
442
|
end
|
|
375
443
|
|
|
376
|
-
|
|
377
|
-
|
|
444
|
+
context 'nested fields' do
|
|
445
|
+
context 'with ignore_blank: true option' do
|
|
446
|
+
before do
|
|
447
|
+
stub_index(:countries) do
|
|
448
|
+
index_scope Country
|
|
449
|
+
field :id
|
|
450
|
+
field :cities, ignore_blank: true do
|
|
451
|
+
field :id
|
|
452
|
+
field :name
|
|
453
|
+
field :historical_name, ignore_blank: true
|
|
454
|
+
field :description
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
end
|
|
378
458
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
cities
|
|
459
|
+
let(:country) { Country.create!(id: 1, cities: cities) }
|
|
460
|
+
context('without cities') do
|
|
461
|
+
let(:cities) { [] }
|
|
462
|
+
specify do
|
|
463
|
+
expect(CountriesIndex.root.compose(country))
|
|
464
|
+
.to eq('id' => 1)
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
context('with cities') do
|
|
468
|
+
let(:cities) { [City.create!(id: 1, name: '', historical_name: '')] }
|
|
469
|
+
specify do
|
|
470
|
+
expect(CountriesIndex.root.compose(country)).to eq(
|
|
471
|
+
'id' => 1, 'cities' => [
|
|
472
|
+
{'id' => 1, 'name' => '', 'description' => nil}
|
|
473
|
+
]
|
|
474
|
+
)
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
context 'with ignore_blank: false option' do
|
|
480
|
+
before do
|
|
481
|
+
stub_index(:countries) do
|
|
482
|
+
index_scope Country
|
|
483
|
+
field :id
|
|
484
|
+
field :cities, ignore_blank: false do
|
|
485
|
+
field :id
|
|
486
|
+
field :name
|
|
487
|
+
field :historical_name
|
|
488
|
+
field :description
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
let(:country_with_cities) { Country.create!(id: 1) }
|
|
494
|
+
|
|
495
|
+
specify do
|
|
496
|
+
expect(CountriesIndex.root.compose(country_with_cities))
|
|
497
|
+
.to eq('id' => 1, 'cities' => [])
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
context 'without ignore_blank: true option' do
|
|
502
|
+
before do
|
|
503
|
+
stub_index(:countries) do
|
|
504
|
+
index_scope Country
|
|
505
|
+
field :id
|
|
506
|
+
field :cities do
|
|
507
|
+
field :id
|
|
508
|
+
field :name
|
|
509
|
+
field :historical_name
|
|
510
|
+
field :description
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
let(:country_with_cities) { Country.create!(id: 1) }
|
|
516
|
+
|
|
517
|
+
specify do
|
|
518
|
+
expect(CountriesIndex.root.compose(country_with_cities))
|
|
519
|
+
.to eq('id' => 1, 'cities' => [])
|
|
382
520
|
end
|
|
383
|
-
else
|
|
384
|
-
Country.create!(id: 1, cities: cities)
|
|
385
521
|
end
|
|
386
522
|
end
|
|
387
523
|
|
|
524
|
+
context 'geo_point field type' do
|
|
525
|
+
context 'with ignore_blank: true option' do
|
|
526
|
+
before do
|
|
527
|
+
stub_index(:countries) do
|
|
528
|
+
index_scope Country
|
|
529
|
+
field :id
|
|
530
|
+
field :cities do
|
|
531
|
+
field :id
|
|
532
|
+
field :name
|
|
533
|
+
field :location, type: :geo_point, ignore_blank: true do
|
|
534
|
+
field :lat
|
|
535
|
+
field :lon
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
specify do
|
|
542
|
+
expect(
|
|
543
|
+
CountriesIndex.root.compose({
|
|
544
|
+
'id' => 1,
|
|
545
|
+
'cities' => [
|
|
546
|
+
{'id' => 1, 'name' => 'City1', 'location' => {}},
|
|
547
|
+
{'id' => 2, 'name' => 'City2', 'location' => {}}
|
|
548
|
+
]
|
|
549
|
+
})
|
|
550
|
+
).to eq(
|
|
551
|
+
'id' => 1, 'cities' => [
|
|
552
|
+
{'id' => 1, 'name' => 'City1'},
|
|
553
|
+
{'id' => 2, 'name' => 'City2'}
|
|
554
|
+
]
|
|
555
|
+
)
|
|
556
|
+
end
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
context 'without ignore_blank option' do
|
|
560
|
+
before do
|
|
561
|
+
stub_index(:countries) do
|
|
562
|
+
index_scope Country
|
|
563
|
+
field :id
|
|
564
|
+
field :cities do
|
|
565
|
+
field :id
|
|
566
|
+
field :name
|
|
567
|
+
field :location, type: :geo_point do
|
|
568
|
+
field :lat
|
|
569
|
+
field :lon
|
|
570
|
+
end
|
|
571
|
+
end
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
specify do
|
|
576
|
+
expect(
|
|
577
|
+
CountriesIndex.root.compose({
|
|
578
|
+
'id' => 1,
|
|
579
|
+
'cities' => [
|
|
580
|
+
{'id' => 1, 'name' => 'City1', 'location' => {}},
|
|
581
|
+
{'id' => 2, 'name' => 'City2', 'location' => {}}
|
|
582
|
+
]
|
|
583
|
+
})
|
|
584
|
+
).to eq(
|
|
585
|
+
'id' => 1, 'cities' => [
|
|
586
|
+
{'id' => 1, 'name' => 'City1'},
|
|
587
|
+
{'id' => 2, 'name' => 'City2'}
|
|
588
|
+
]
|
|
589
|
+
)
|
|
590
|
+
end
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
context 'with ignore_blank: false flag' do
|
|
594
|
+
before do
|
|
595
|
+
stub_index(:countries) do
|
|
596
|
+
index_scope Country
|
|
597
|
+
field :id
|
|
598
|
+
field :cities do
|
|
599
|
+
field :id
|
|
600
|
+
field :name
|
|
601
|
+
field :location, type: :geo_point, ignore_blank: false do
|
|
602
|
+
field :lat
|
|
603
|
+
field :lon
|
|
604
|
+
end
|
|
605
|
+
end
|
|
606
|
+
end
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
specify do
|
|
610
|
+
expect(
|
|
611
|
+
CountriesIndex.root.compose({
|
|
612
|
+
'id' => 1,
|
|
613
|
+
'cities' => [
|
|
614
|
+
{'id' => 1, 'location' => {}, 'name' => 'City1'},
|
|
615
|
+
{'id' => 2, 'location' => '', 'name' => 'City2'}
|
|
616
|
+
]
|
|
617
|
+
})
|
|
618
|
+
).to eq(
|
|
619
|
+
'id' => 1, 'cities' => [
|
|
620
|
+
{'id' => 1, 'location' => {}, 'name' => 'City1'},
|
|
621
|
+
{'id' => 2, 'location' => '', 'name' => 'City2'}
|
|
622
|
+
]
|
|
623
|
+
)
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
end
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
context 'objects and scopes', :orm do
|
|
630
|
+
before do
|
|
631
|
+
stub_model(:city)
|
|
632
|
+
stub_model(:country)
|
|
633
|
+
|
|
634
|
+
City.belongs_to :country
|
|
635
|
+
Country.has_many :cities, -> { order :id }
|
|
636
|
+
|
|
637
|
+
stub_index(:countries) do
|
|
638
|
+
index_scope Country
|
|
639
|
+
field :id
|
|
640
|
+
field :cities do
|
|
641
|
+
field :id
|
|
642
|
+
field :name
|
|
643
|
+
end
|
|
644
|
+
end
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
let(:country_with_cities) do
|
|
648
|
+
cities = [City.create!(id: 1, name: 'City1'), City.create!(id: 2, name: 'City2')]
|
|
649
|
+
|
|
650
|
+
Country.create!(id: 1, cities: cities)
|
|
651
|
+
end
|
|
652
|
+
|
|
388
653
|
specify do
|
|
389
|
-
expect(CountriesIndex
|
|
654
|
+
expect(CountriesIndex.root.compose(country_with_cities)).to eq('id' => 1, 'cities' => [
|
|
390
655
|
{'id' => 1, 'name' => 'City1'}, {'id' => 2, 'name' => 'City2'}
|
|
391
656
|
])
|
|
392
657
|
end
|
|
@@ -394,20 +659,19 @@ describe Chewy::Fields::Base do
|
|
|
394
659
|
context 'nested object' do
|
|
395
660
|
before do
|
|
396
661
|
stub_index(:cities) do
|
|
397
|
-
|
|
662
|
+
index_scope City
|
|
663
|
+
field :id
|
|
664
|
+
field :country do
|
|
398
665
|
field :id
|
|
399
|
-
field :
|
|
400
|
-
field :id
|
|
401
|
-
field :name
|
|
402
|
-
end
|
|
666
|
+
field :name
|
|
403
667
|
end
|
|
404
668
|
end
|
|
405
669
|
end
|
|
406
670
|
|
|
407
671
|
specify do
|
|
408
|
-
expect(
|
|
409
|
-
|
|
410
|
-
)
|
|
672
|
+
expect(
|
|
673
|
+
CitiesIndex.root.compose(City.create!(id: 1, country: Country.create!(id: 1, name: 'Country')))
|
|
674
|
+
).to eq('id' => 1, 'country' => {'id' => 1, 'name' => 'Country'})
|
|
411
675
|
end
|
|
412
676
|
end
|
|
413
677
|
end
|