chewy 7.1.0 → 7.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|