chewy 6.0.0 → 7.5.1

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.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. data/.github/PULL_REQUEST_TEMPLATE.md +16 -0
  6. data/.github/dependabot.yml +42 -0
  7. data/.github/workflows/ruby.yml +48 -0
  8. data/.rubocop.yml +16 -8
  9. data/.rubocop_todo.yml +110 -22
  10. data/CHANGELOG.md +385 -105
  11. data/CODE_OF_CONDUCT.md +14 -0
  12. data/CONTRIBUTING.md +63 -0
  13. data/Gemfile +4 -10
  14. data/Guardfile +3 -1
  15. data/README.md +494 -275
  16. data/chewy.gemspec +5 -20
  17. data/gemfiles/base.gemfile +12 -0
  18. data/gemfiles/rails.6.1.activerecord.gemfile +10 -15
  19. data/gemfiles/rails.7.0.activerecord.gemfile +14 -0
  20. data/gemfiles/rails.7.1.activerecord.gemfile +14 -0
  21. data/lib/chewy/config.rb +58 -50
  22. data/lib/chewy/elastic_client.rb +31 -0
  23. data/lib/chewy/errors.rb +7 -10
  24. data/lib/chewy/fields/base.rb +79 -13
  25. data/lib/chewy/fields/root.rb +4 -14
  26. data/lib/chewy/index/actions.rb +54 -37
  27. data/lib/chewy/{type → index}/adapter/active_record.rb +30 -6
  28. data/lib/chewy/{type → index}/adapter/base.rb +2 -3
  29. data/lib/chewy/{type → index}/adapter/object.rb +27 -31
  30. data/lib/chewy/{type → index}/adapter/orm.rb +17 -18
  31. data/lib/chewy/index/aliases.rb +14 -5
  32. data/lib/chewy/index/crutch.rb +40 -0
  33. data/lib/chewy/index/import/bulk_builder.rb +311 -0
  34. data/lib/chewy/{type → index}/import/bulk_request.rb +6 -7
  35. data/lib/chewy/{type → index}/import/journal_builder.rb +11 -12
  36. data/lib/chewy/{type → index}/import/routine.rb +18 -17
  37. data/lib/chewy/{type → index}/import.rb +76 -32
  38. data/lib/chewy/{type → index}/mapping.rb +29 -34
  39. data/lib/chewy/index/observe/active_record_methods.rb +87 -0
  40. data/lib/chewy/index/observe/callback.rb +34 -0
  41. data/lib/chewy/index/observe.rb +17 -0
  42. data/lib/chewy/index/specification.rb +1 -0
  43. data/lib/chewy/{type → index}/syncer.rb +59 -59
  44. data/lib/chewy/{type → index}/witchcraft.rb +11 -7
  45. data/lib/chewy/{type → index}/wrapper.rb +2 -2
  46. data/lib/chewy/index.rb +67 -94
  47. data/lib/chewy/journal.rb +25 -14
  48. data/lib/chewy/log_subscriber.rb +5 -1
  49. data/lib/chewy/minitest/helpers.rb +86 -13
  50. data/lib/chewy/minitest/search_index_receiver.rb +24 -26
  51. data/lib/chewy/railtie.rb +6 -20
  52. data/lib/chewy/rake_helper.rb +169 -113
  53. data/lib/chewy/rspec/build_query.rb +12 -0
  54. data/lib/chewy/rspec/helpers.rb +55 -0
  55. data/lib/chewy/rspec/update_index.rb +55 -44
  56. data/lib/chewy/rspec.rb +2 -0
  57. data/lib/chewy/runtime/version.rb +1 -1
  58. data/lib/chewy/runtime.rb +1 -1
  59. data/lib/chewy/search/loader.rb +19 -41
  60. data/lib/chewy/search/parameters/collapse.rb +16 -0
  61. data/lib/chewy/search/parameters/concerns/query_storage.rb +2 -2
  62. data/lib/chewy/search/parameters/ignore_unavailable.rb +27 -0
  63. data/lib/chewy/search/parameters/indices.rb +13 -58
  64. data/lib/chewy/search/parameters/knn.rb +16 -0
  65. data/lib/chewy/search/parameters/order.rb +6 -19
  66. data/lib/chewy/search/parameters/source.rb +5 -1
  67. data/lib/chewy/search/parameters/storage.rb +1 -1
  68. data/lib/chewy/search/parameters/track_total_hits.rb +16 -0
  69. data/lib/chewy/search/parameters.rb +6 -4
  70. data/lib/chewy/search/query_proxy.rb +9 -2
  71. data/lib/chewy/search/request.rb +169 -134
  72. data/lib/chewy/search/response.rb +5 -5
  73. data/lib/chewy/search/scoping.rb +7 -8
  74. data/lib/chewy/search/scrolling.rb +13 -13
  75. data/lib/chewy/search.rb +9 -19
  76. data/lib/chewy/stash.rb +19 -30
  77. data/lib/chewy/strategy/active_job.rb +1 -1
  78. data/lib/chewy/strategy/atomic_no_refresh.rb +18 -0
  79. data/lib/chewy/strategy/base.rb +10 -0
  80. data/lib/chewy/strategy/delayed_sidekiq/scheduler.rb +151 -0
  81. data/lib/chewy/strategy/delayed_sidekiq/worker.rb +52 -0
  82. data/lib/chewy/strategy/delayed_sidekiq.rb +30 -0
  83. data/lib/chewy/strategy/lazy_sidekiq.rb +64 -0
  84. data/lib/chewy/strategy/sidekiq.rb +2 -1
  85. data/lib/chewy/strategy.rb +6 -19
  86. data/lib/chewy/version.rb +1 -1
  87. data/lib/chewy.rb +39 -86
  88. data/lib/generators/chewy/install_generator.rb +1 -1
  89. data/lib/tasks/chewy.rake +36 -32
  90. data/migration_guide.md +46 -8
  91. data/spec/chewy/config_spec.rb +14 -39
  92. data/spec/chewy/elastic_client_spec.rb +26 -0
  93. data/spec/chewy/fields/base_spec.rb +432 -147
  94. data/spec/chewy/fields/root_spec.rb +20 -28
  95. data/spec/chewy/fields/time_fields_spec.rb +5 -5
  96. data/spec/chewy/index/actions_spec.rb +368 -59
  97. data/spec/chewy/{type → index}/adapter/active_record_spec.rb +156 -40
  98. data/spec/chewy/{type → index}/adapter/object_spec.rb +21 -6
  99. data/spec/chewy/index/aliases_spec.rb +3 -3
  100. data/spec/chewy/index/import/bulk_builder_spec.rb +494 -0
  101. data/spec/chewy/{type → index}/import/bulk_request_spec.rb +5 -12
  102. data/spec/chewy/{type → index}/import/journal_builder_spec.rb +9 -19
  103. data/spec/chewy/{type → index}/import/routine_spec.rb +19 -19
  104. data/spec/chewy/{type → index}/import_spec.rb +164 -98
  105. data/spec/chewy/index/mapping_spec.rb +135 -0
  106. data/spec/chewy/index/observe/active_record_methods_spec.rb +68 -0
  107. data/spec/chewy/index/observe/callback_spec.rb +139 -0
  108. data/spec/chewy/index/observe_spec.rb +143 -0
  109. data/spec/chewy/index/settings_spec.rb +3 -1
  110. data/spec/chewy/index/specification_spec.rb +20 -30
  111. data/spec/chewy/{type → index}/syncer_spec.rb +14 -19
  112. data/spec/chewy/{type → index}/witchcraft_spec.rb +20 -22
  113. data/spec/chewy/index/wrapper_spec.rb +100 -0
  114. data/spec/chewy/index_spec.rb +60 -105
  115. data/spec/chewy/journal_spec.rb +25 -74
  116. data/spec/chewy/minitest/helpers_spec.rb +123 -15
  117. data/spec/chewy/minitest/search_index_receiver_spec.rb +28 -30
  118. data/spec/chewy/multi_search_spec.rb +4 -5
  119. data/spec/chewy/rake_helper_spec.rb +315 -55
  120. data/spec/chewy/rspec/build_query_spec.rb +34 -0
  121. data/spec/chewy/rspec/helpers_spec.rb +61 -0
  122. data/spec/chewy/rspec/update_index_spec.rb +74 -71
  123. data/spec/chewy/runtime_spec.rb +2 -2
  124. data/spec/chewy/search/loader_spec.rb +19 -53
  125. data/spec/chewy/search/pagination/kaminari_examples.rb +4 -6
  126. data/spec/chewy/search/pagination/kaminari_spec.rb +2 -2
  127. data/spec/chewy/search/parameters/collapse_spec.rb +5 -0
  128. data/spec/chewy/search/parameters/ignore_unavailable_spec.rb +67 -0
  129. data/spec/chewy/search/parameters/indices_spec.rb +26 -117
  130. data/spec/chewy/search/parameters/knn_spec.rb +5 -0
  131. data/spec/chewy/search/parameters/order_spec.rb +18 -11
  132. data/spec/chewy/search/parameters/query_storage_examples.rb +67 -21
  133. data/spec/chewy/search/parameters/search_after_spec.rb +4 -1
  134. data/spec/chewy/search/parameters/source_spec.rb +8 -2
  135. data/spec/chewy/search/parameters/track_total_hits_spec.rb +5 -0
  136. data/spec/chewy/search/parameters_spec.rb +18 -4
  137. data/spec/chewy/search/query_proxy_spec.rb +68 -17
  138. data/spec/chewy/search/request_spec.rb +292 -110
  139. data/spec/chewy/search/response_spec.rb +12 -12
  140. data/spec/chewy/search/scrolling_spec.rb +10 -17
  141. data/spec/chewy/search_spec.rb +40 -34
  142. data/spec/chewy/stash_spec.rb +9 -21
  143. data/spec/chewy/strategy/active_job_spec.rb +16 -16
  144. data/spec/chewy/strategy/atomic_no_refresh_spec.rb +60 -0
  145. data/spec/chewy/strategy/atomic_spec.rb +9 -10
  146. data/spec/chewy/strategy/delayed_sidekiq_spec.rb +202 -0
  147. data/spec/chewy/strategy/lazy_sidekiq_spec.rb +214 -0
  148. data/spec/chewy/strategy/sidekiq_spec.rb +12 -12
  149. data/spec/chewy/strategy_spec.rb +19 -15
  150. data/spec/chewy_spec.rb +24 -107
  151. data/spec/spec_helper.rb +3 -22
  152. data/spec/support/active_record.rb +25 -7
  153. metadata +78 -339
  154. data/.circleci/config.yml +0 -240
  155. data/Appraisals +0 -81
  156. data/gemfiles/rails.5.2.activerecord.gemfile +0 -17
  157. data/gemfiles/rails.5.2.mongoid.6.4.gemfile +0 -17
  158. data/gemfiles/rails.6.0.activerecord.gemfile +0 -17
  159. data/gemfiles/sequel.4.45.gemfile +0 -11
  160. data/lib/chewy/backports/deep_dup.rb +0 -46
  161. data/lib/chewy/backports/duplicable.rb +0 -91
  162. data/lib/chewy/search/pagination/will_paginate.rb +0 -43
  163. data/lib/chewy/search/parameters/types.rb +0 -20
  164. data/lib/chewy/strategy/resque.rb +0 -27
  165. data/lib/chewy/strategy/shoryuken.rb +0 -40
  166. data/lib/chewy/type/actions.rb +0 -43
  167. data/lib/chewy/type/adapter/mongoid.rb +0 -67
  168. data/lib/chewy/type/adapter/sequel.rb +0 -93
  169. data/lib/chewy/type/crutch.rb +0 -32
  170. data/lib/chewy/type/import/bulk_builder.rb +0 -122
  171. data/lib/chewy/type/observe.rb +0 -82
  172. data/lib/chewy/type.rb +0 -120
  173. data/lib/sequel/plugins/chewy_observe.rb +0 -63
  174. data/spec/chewy/search/pagination/will_paginate_examples.rb +0 -63
  175. data/spec/chewy/search/pagination/will_paginate_spec.rb +0 -23
  176. data/spec/chewy/search/parameters/types_spec.rb +0 -5
  177. data/spec/chewy/strategy/resque_spec.rb +0 -46
  178. data/spec/chewy/strategy/shoryuken_spec.rb +0 -70
  179. data/spec/chewy/type/actions_spec.rb +0 -50
  180. data/spec/chewy/type/adapter/mongoid_spec.rb +0 -372
  181. data/spec/chewy/type/adapter/sequel_spec.rb +0 -472
  182. data/spec/chewy/type/import/bulk_builder_spec.rb +0 -194
  183. data/spec/chewy/type/mapping_spec.rb +0 -175
  184. data/spec/chewy/type/observe_spec.rb +0 -137
  185. data/spec/chewy/type/wrapper_spec.rb +0 -100
  186. data/spec/chewy/type_spec.rb +0 -55
  187. data/spec/support/mongoid.rb +0 -93
  188. data/spec/support/sequel.rb +0 -80
@@ -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 { expect(described_class.new(:name, value: :last_name).compose(double(last_name: 'hello'))).to eq(name: 'hello') }
14
- specify { expect(described_class.new(:name, value: :last_name).compose('last_name' => 'hello')).to eq(name: 'hello') }
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) }
@@ -122,14 +126,12 @@ describe Chewy::Fields::Base do
122
126
  context 'default field type' do
123
127
  before do
124
128
  stub_index(:events) do
125
- define_type :event do
129
+ field :id
130
+ field :category do
126
131
  field :id
127
- field :category do
132
+ field :licenses do
128
133
  field :id
129
- field :licenses do
130
- field :id
131
- field :created_at, type: 'time'
132
- end
134
+ field :created_at, type: 'time'
133
135
  end
134
136
  end
135
137
  end
@@ -143,177 +145,217 @@ describe Chewy::Fields::Base do
143
145
  end
144
146
 
145
147
  specify do
146
- expect(EventsIndex::Event.mappings_hash).to eq(event: {
147
- properties: {
148
- id: {type: 'integer'},
149
- category: {
150
- type: 'object',
151
- properties: {
152
- id: {type: 'integer'},
153
- licenses: {
154
- type: 'object',
155
- properties: {
156
- id: {type: 'integer'},
157
- created_at: {type: 'time'}
148
+ expect(EventsIndex.mappings_hash).to eq(
149
+ mappings: {
150
+ properties: {
151
+ id: {type: 'integer'},
152
+ category: {
153
+ type: 'object',
154
+ properties: {
155
+ id: {type: 'integer'},
156
+ licenses: {
157
+ type: 'object',
158
+ properties: {
159
+ id: {type: 'integer'},
160
+ created_at: {type: 'time'}
161
+ }
158
162
  }
159
163
  }
160
164
  }
161
165
  }
162
166
  }
163
- })
167
+ )
164
168
  end
165
169
  end
166
170
 
167
171
  context 'objects, hashes and arrays' do
168
172
  before do
169
173
  stub_index(:events) do
170
- define_type :event do
174
+ field :id
175
+ field :category do
171
176
  field :id
172
- field :category do
177
+ field :licenses do
173
178
  field :id
174
- field :licenses do
175
- field :id
176
- field :name
177
- end
179
+ field :name
178
180
  end
179
181
  end
180
182
  end
181
183
  end
182
184
 
183
- # rubocop:disable Style/BracesAroundHashParameters
184
185
  specify do
185
- expect(EventsIndex::Event.root.compose({
186
- id: 1, category: {id: 2, licenses: {id: 3, name: 'Name'}}
187
- })).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}})
186
+ expect(
187
+ EventsIndex.root.compose({id: 1, category: {id: 2, licenses: {id: 3, name: 'Name'}}})
188
+ ).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}})
188
189
  end
189
190
 
190
191
  specify do
191
- expect(EventsIndex::Event.root.compose({id: 1, category: [
192
- {id: 2, 'licenses' => {id: 3, name: 'Name1'}},
193
- {id: 4, licenses: nil}
194
- ]})).to eq('id' => 1, 'category' => [
192
+ expect(
193
+ EventsIndex.root.compose({id: 1, category: [
194
+ {id: 2, 'licenses' => {id: 3, name: 'Name1'}},
195
+ {id: 4, licenses: nil}
196
+ ]})
197
+ ).to eq('id' => 1, 'category' => [
195
198
  {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name1'}},
196
199
  {'id' => 4, 'licenses' => nil.as_json}
197
200
  ])
198
201
  end
199
202
 
200
203
  specify do
201
- expect(EventsIndex::Event.root.compose({'id' => 1, category: {id: 2, licenses: [
202
- {id: 3, name: 'Name1'}, {id: 4, name: 'Name2'}
203
- ]}})).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => [
204
- {'id' => 3, 'name' => 'Name1'}, {'id' => 4, 'name' => 'Name2'}
205
- ]})
204
+ expect(
205
+ EventsIndex.root.compose({
206
+ 'id' => 1,
207
+ category: {
208
+ id: 2, licenses: [
209
+ {id: 3, name: 'Name1'},
210
+ {id: 4, name: 'Name2'}
211
+ ]
212
+ }
213
+ })
214
+ ).to eq(
215
+ 'id' => 1,
216
+ 'category' => {
217
+ 'id' => 2,
218
+ 'licenses' => [
219
+ {'id' => 3, 'name' => 'Name1'},
220
+ {'id' => 4, 'name' => 'Name2'}
221
+ ]
222
+ }
223
+ )
206
224
  end
207
225
 
208
226
  specify do
209
- expect(EventsIndex::Event.root.compose({id: 1, category: [
210
- {id: 2, licenses: [
211
- {id: 3, 'name' => 'Name1'}, {id: 4, name: 'Name2'}
212
- ]},
213
- {id: 5, licenses: []}
214
- ]})).to eq('id' => 1, 'category' => [
215
- {'id' => 2, 'licenses' => [
216
- {'id' => 3, 'name' => 'Name1'}, {'id' => 4, 'name' => 'Name2'}
217
- ]},
218
- {'id' => 5, 'licenses' => []}
219
- ])
227
+ expect(
228
+ EventsIndex.root.compose({id: 1, category: [
229
+ {id: 2, licenses: [
230
+ {id: 3, 'name' => 'Name1'}, {id: 4, name: 'Name2'}
231
+ ]},
232
+ {id: 5, licenses: []}
233
+ ]})
234
+ ).to eq(
235
+ 'id' => 1,
236
+ 'category' => [
237
+ {'id' => 2, 'licenses' => [
238
+ {'id' => 3, 'name' => 'Name1'},
239
+ {'id' => 4, 'name' => 'Name2'}
240
+ ]},
241
+ {'id' => 5, 'licenses' => []}
242
+ ]
243
+ )
220
244
  end
221
- # rubocop:enable Style/BracesAroundHashParameters
222
-
223
245
  specify do
224
- expect(EventsIndex::Event.root.compose(
225
- double(id: 1, category: double(id: 2, licenses: double(id: 3, name: 'Name')))
226
- )).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}})
246
+ expect(
247
+ EventsIndex.root.compose(double(id: 1, category: double(id: 2, licenses: double(id: 3, name: 'Name'))))
248
+ ).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}})
227
249
  end
228
250
 
229
251
  specify do
230
- expect(EventsIndex::Event.root.compose(double(id: 1, category: [
231
- double(id: 2, licenses: double(id: 3, name: 'Name1')),
232
- double(id: 4, licenses: nil)
233
- ]))).to eq('id' => 1, 'category' => [
252
+ expect(
253
+ EventsIndex.root.compose(double(id: 1, category: [
254
+ double(id: 2, licenses: double(id: 3, name: 'Name1')),
255
+ double(id: 4, licenses: nil)
256
+ ]))
257
+ ).to eq('id' => 1, 'category' => [
234
258
  {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name1'}},
235
259
  {'id' => 4, 'licenses' => nil.as_json}
236
260
  ])
237
261
  end
238
262
 
239
263
  specify do
240
- expect(EventsIndex::Event.root.compose(double(id: 1, category: double(id: 2, licenses: [
241
- double(id: 3, name: 'Name1'), double(id: 4, name: 'Name2')
242
- ])))).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => [
264
+ expect(
265
+ EventsIndex.root.compose(double(id: 1, category: double(id: 2, licenses: [
266
+ double(id: 3, name: 'Name1'), double(id: 4, name: 'Name2')
267
+ ])))
268
+ ).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => [
243
269
  {'id' => 3, 'name' => 'Name1'}, {'id' => 4, 'name' => 'Name2'}
244
270
  ]})
245
271
  end
246
272
 
247
273
  specify do
248
- expect(EventsIndex::Event.root.compose(double(id: 1, category: [
249
- double(id: 2, licenses: [
250
- double(id: 3, name: 'Name1'), double(id: 4, name: 'Name2')
251
- ]),
252
- double(id: 5, licenses: [])
253
- ]))).to eq('id' => 1, 'category' => [
254
- {'id' => 2, 'licenses' => [
255
- {'id' => 3, 'name' => 'Name1'}, {'id' => 4, 'name' => 'Name2'}
256
- ]},
257
- {'id' => 5, 'licenses' => []}
258
- ])
274
+ expect(
275
+ EventsIndex.root.compose(double(id: 1, category: [
276
+ double(id: 2, licenses: [
277
+ double(id: 3, name: 'Name1'), double(id: 4, name: 'Name2')
278
+ ]),
279
+ double(id: 5, licenses: [])
280
+ ]))
281
+ ).to eq(
282
+ 'id' => 1, 'category' => [
283
+ {'id' => 2, 'licenses' => [
284
+ {'id' => 3, 'name' => 'Name1'}, {'id' => 4, 'name' => 'Name2'}
285
+ ]},
286
+ {'id' => 5, 'licenses' => []}
287
+ ]
288
+ )
259
289
  end
260
290
  end
261
291
 
262
292
  context 'custom methods' do
263
293
  before do
264
294
  stub_index(:events) do
265
- define_type :event do
295
+ field :id, type: 'integer'
296
+ field :category, value: -> { categories } do
266
297
  field :id, type: 'integer'
267
- field :category, value: -> { categories } do
298
+ field :licenses, value: -> { license } do
268
299
  field :id, type: 'integer'
269
- field :licenses, value: -> { license } do
270
- field :id, type: 'integer'
271
- field :name
272
- end
300
+ field :name
273
301
  end
274
302
  end
275
303
  end
276
304
  end
277
305
 
278
306
  specify do
279
- expect(EventsIndex::Event.root.compose(
280
- double(id: 1, categories: double(id: 2, license: double(id: 3, name: 'Name')))
281
- )).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}})
307
+ expect(
308
+ EventsIndex.root.compose(
309
+ double(
310
+ id: 1, categories: double(
311
+ id: 2, license: double(
312
+ id: 3, name: 'Name'
313
+ )
314
+ )
315
+ )
316
+ )
317
+ ).to eq('id' => 1, 'category' => {'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}})
282
318
  end
283
319
  end
284
320
 
285
321
  context 'objects and multi_fields' do
286
322
  before do
287
323
  stub_index(:events) do
288
- define_type :event do
289
- field :id, type: 'integer'
290
- field :name, type: 'integer' do
291
- field :raw, analyzer: 'my_own'
292
- end
293
- field :category, type: 'object'
324
+ field :id, type: 'integer'
325
+ field :name, type: 'integer' do
326
+ field :raw, analyzer: 'my_own'
294
327
  end
328
+ field :category, type: 'object'
295
329
  end
296
330
  end
297
331
 
298
332
  specify do
299
- expect(EventsIndex::Event.mappings_hash).to eq(event: {
300
- properties: {
301
- id: {type: 'integer'},
302
- name: {
303
- type: 'integer',
304
- fields: {
305
- raw: {analyzer: 'my_own', type: Chewy.default_field_type}
306
- }
307
- },
308
- category: {type: 'object'}
333
+ expect(EventsIndex.mappings_hash).to eq(
334
+ mappings: {
335
+ properties: {
336
+ id: {type: 'integer'},
337
+ name: {
338
+ type: 'integer',
339
+ fields: {
340
+ raw: {analyzer: 'my_own', type: Chewy.default_field_type}
341
+ }
342
+ },
343
+ category: {type: 'object'}
344
+ }
309
345
  }
310
- })
346
+ )
311
347
  end
312
348
 
313
349
  specify do
314
- expect(EventsIndex::Event.root.compose(
315
- double(id: 1, name: 'Jonny', category: double(id: 2, as_json: {'name' => 'Borogoves'}))
316
- )).to eq(
350
+ expect(
351
+ EventsIndex.root.compose(
352
+ double(
353
+ id: 1, name: 'Jonny', category: double(
354
+ id: 2, as_json: {'name' => 'Borogoves'}
355
+ )
356
+ )
357
+ )
358
+ ).to eq(
317
359
  'id' => 1,
318
360
  'name' => 'Jonny',
319
361
  'category' => {'name' => 'Borogoves'}
@@ -321,12 +363,14 @@ describe Chewy::Fields::Base do
321
363
  end
322
364
 
323
365
  specify do
324
- expect(EventsIndex::Event.root.compose(
325
- double(id: 1, name: 'Jonny', category: [
326
- double(id: 2, as_json: {'name' => 'Borogoves1'}),
327
- double(id: 3, as_json: {'name' => 'Borogoves2'})
328
- ])
329
- )).to eq(
366
+ expect(
367
+ EventsIndex.root.compose(
368
+ double(id: 1, name: 'Jonny', category: [
369
+ double(id: 2, as_json: {'name' => 'Borogoves1'}),
370
+ double(id: 3, as_json: {'name' => 'Borogoves2'})
371
+ ])
372
+ )
373
+ ).to eq(
330
374
  'id' => 1,
331
375
  'name' => 'Jonny',
332
376
  'category' => [
@@ -337,56 +381,298 @@ describe Chewy::Fields::Base do
337
381
  end
338
382
  end
339
383
 
340
- context 'objects and scopes', :orm do
384
+ context 'ignore_blank option for field method', :orm do
341
385
  before do
386
+ stub_model(:location)
342
387
  stub_model(:city)
343
388
  stub_model(:country)
344
389
 
345
- case adapter
346
- when :active_record
347
- City.belongs_to :country
348
- if ActiveRecord::VERSION::MAJOR >= 4
349
- Country.has_many :cities, -> { order :id }
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
390
+ City.belongs_to :country
391
+ Location.belongs_to :city
392
+ City.has_one :location, -> { order :id }
393
+ Country.has_many :cities, -> { order :id }
394
+ end
364
395
 
365
- stub_index(:countries) do
366
- define_type Country do
396
+ context 'text fields with and without ignore_blank option' do
397
+ before do
398
+ stub_index(:countries) do
399
+ index_scope Country
367
400
  field :id
368
401
  field :cities do
369
402
  field :id
370
403
  field :name
404
+ field :historical_name, ignore_blank: false
405
+ field :description, ignore_blank: true
371
406
  end
372
407
  end
373
408
  end
409
+
410
+ let(:country_with_cities) do
411
+ cities = [
412
+ City.create!(id: 1, name: '', historical_name: '', description: ''),
413
+ City.create!(id: 2, name: '', historical_name: '', description: '')
414
+ ]
415
+
416
+ Country.create!(id: 1, cities: cities)
417
+ end
418
+
419
+ specify do
420
+ expect(CountriesIndex.root.compose(country_with_cities)).to eq(
421
+ 'id' => 1, 'cities' => [
422
+ {'id' => 1, 'name' => '', 'historical_name' => ''},
423
+ {'id' => 2, 'name' => '', 'historical_name' => ''}
424
+ ]
425
+ )
426
+ end
427
+ specify { expect(CountriesIndex.reset).to eq(true) }
374
428
  end
375
429
 
376
- let(:country_with_cities) do
377
- cities = [City.create!(id: 1, name: 'City1'), City.create!(id: 2, name: 'City2')]
430
+ context 'nested fields' do
431
+ context 'with ignore_blank: true option' do
432
+ before do
433
+ stub_index(:countries) do
434
+ index_scope Country
435
+ field :id
436
+ field :cities, ignore_blank: true do
437
+ field :id
438
+ field :name
439
+ field :historical_name, ignore_blank: true
440
+ field :description
441
+ end
442
+ end
443
+ end
378
444
 
379
- if adapter == :sequel
380
- Country.create(id: 1).tap do |country|
381
- cities.each { |city| country.add_city(city) }
445
+ let(:country) { Country.create!(id: 1, cities: cities) }
446
+ context('without cities') do
447
+ let(:cities) { [] }
448
+ specify do
449
+ expect(CountriesIndex.root.compose(country))
450
+ .to eq('id' => 1)
451
+ end
452
+ end
453
+ context('with cities') do
454
+ let(:cities) { [City.create!(id: 1, name: '', historical_name: '')] }
455
+ specify do
456
+ expect(CountriesIndex.root.compose(country)).to eq(
457
+ 'id' => 1, 'cities' => [
458
+ {'id' => 1, 'name' => '', 'description' => nil}
459
+ ]
460
+ )
461
+ end
462
+ end
463
+ end
464
+
465
+ context 'with ignore_blank: false option' do
466
+ before do
467
+ stub_index(:countries) do
468
+ index_scope Country
469
+ field :id
470
+ field :cities, ignore_blank: false do
471
+ field :id
472
+ field :name
473
+ field :historical_name
474
+ field :description
475
+ end
476
+ end
477
+ end
478
+
479
+ let(:country_with_cities) { Country.create!(id: 1) }
480
+
481
+ specify do
482
+ expect(CountriesIndex.root.compose(country_with_cities))
483
+ .to eq('id' => 1, 'cities' => [])
484
+ end
485
+ end
486
+
487
+ context 'without ignore_blank: true option' do
488
+ before do
489
+ stub_index(:countries) do
490
+ index_scope Country
491
+ field :id
492
+ field :cities do
493
+ field :id
494
+ field :name
495
+ field :historical_name
496
+ field :description
497
+ end
498
+ end
499
+ end
500
+
501
+ let(:country_with_cities) { Country.create!(id: 1) }
502
+
503
+ specify do
504
+ expect(CountriesIndex.root.compose(country_with_cities))
505
+ .to eq('id' => 1, 'cities' => [])
506
+ end
507
+ end
508
+ end
509
+
510
+ context 'geo_point field type' do
511
+ context 'with ignore_blank: true option' do
512
+ before do
513
+ stub_index(:countries) do
514
+ index_scope Country
515
+ field :id
516
+ field :cities do
517
+ field :id
518
+ field :name
519
+ field :location, type: :geo_point, ignore_blank: true do
520
+ field :lat
521
+ field :lon
522
+ end
523
+ end
524
+ end
525
+ end
526
+
527
+ specify do
528
+ expect(
529
+ CountriesIndex.root.compose({
530
+ 'id' => 1,
531
+ 'cities' => [
532
+ {'id' => 1, 'name' => 'City1', 'location' => {}},
533
+ {'id' => 2, 'name' => 'City2', 'location' => {}}
534
+ ]
535
+ })
536
+ ).to eq(
537
+ 'id' => 1, 'cities' => [
538
+ {'id' => 1, 'name' => 'City1'},
539
+ {'id' => 2, 'name' => 'City2'}
540
+ ]
541
+ )
542
+ end
543
+ end
544
+
545
+ context 'join field type' do
546
+ before do
547
+ stub_model(:comment)
548
+ stub_index(:comments) do
549
+ index_scope Comment
550
+ field :id
551
+ field :hierarchy, type: :join, relations: {question: %i[answer comment], answer: :vote, vote: :subvote}, join: {type: :comment_type, id: :commented_id}
552
+ end
553
+ end
554
+
555
+ specify do
556
+ expect(
557
+ CommentsIndex.root.compose(
558
+ {'id' => 1, 'comment_type' => 'question'}
559
+ )
560
+ ).to eq(
561
+ {'id' => 1, 'hierarchy' => 'question'}
562
+ )
563
+
564
+ expect(
565
+ CommentsIndex.root.compose(
566
+ {'id' => 2, 'comment_type' => 'answer', 'commented_id' => 1}
567
+ )
568
+ ).to eq(
569
+ {'id' => 2, 'hierarchy' => {'name' => 'answer', 'parent' => 1}}
570
+ )
571
+
572
+ expect do
573
+ CommentsIndex.root.compose(
574
+ {'id' => 2, 'comment_type' => 'asd', 'commented_id' => 1}
575
+ )
576
+ end.to raise_error Chewy::InvalidJoinFieldType
577
+ end
578
+ end
579
+
580
+ context 'without ignore_blank option' do
581
+ before do
582
+ stub_index(:countries) do
583
+ index_scope Country
584
+ field :id
585
+ field :cities do
586
+ field :id
587
+ field :name
588
+ field :location, type: :geo_point do
589
+ field :lat
590
+ field :lon
591
+ end
592
+ end
593
+ end
594
+ end
595
+
596
+ specify do
597
+ expect(
598
+ CountriesIndex.root.compose({
599
+ 'id' => 1,
600
+ 'cities' => [
601
+ {'id' => 1, 'name' => 'City1', 'location' => {}},
602
+ {'id' => 2, 'name' => 'City2', 'location' => {}}
603
+ ]
604
+ })
605
+ ).to eq(
606
+ 'id' => 1, 'cities' => [
607
+ {'id' => 1, 'name' => 'City1'},
608
+ {'id' => 2, 'name' => 'City2'}
609
+ ]
610
+ )
611
+ end
612
+ end
613
+
614
+ context 'with ignore_blank: false flag' do
615
+ before do
616
+ stub_index(:countries) do
617
+ index_scope Country
618
+ field :id
619
+ field :cities do
620
+ field :id
621
+ field :name
622
+ field :location, type: :geo_point, ignore_blank: false do
623
+ field :lat
624
+ field :lon
625
+ end
626
+ end
627
+ end
628
+ end
629
+
630
+ specify do
631
+ expect(
632
+ CountriesIndex.root.compose({
633
+ 'id' => 1,
634
+ 'cities' => [
635
+ {'id' => 1, 'location' => {}, 'name' => 'City1'},
636
+ {'id' => 2, 'location' => '', 'name' => 'City2'}
637
+ ]
638
+ })
639
+ ).to eq(
640
+ 'id' => 1, 'cities' => [
641
+ {'id' => 1, 'location' => {}, 'name' => 'City1'},
642
+ {'id' => 2, 'location' => '', 'name' => 'City2'}
643
+ ]
644
+ )
382
645
  end
383
- else
384
- Country.create!(id: 1, cities: cities)
385
646
  end
386
647
  end
648
+ end
649
+
650
+ context 'objects and scopes', :orm do
651
+ before do
652
+ stub_model(:city)
653
+ stub_model(:country)
654
+
655
+ City.belongs_to :country
656
+ Country.has_many :cities, -> { order :id }
657
+
658
+ stub_index(:countries) do
659
+ index_scope Country
660
+ field :id
661
+ field :cities do
662
+ field :id
663
+ field :name
664
+ end
665
+ end
666
+ end
667
+
668
+ let(:country_with_cities) do
669
+ cities = [City.create!(id: 1, name: 'City1'), City.create!(id: 2, name: 'City2')]
670
+
671
+ Country.create!(id: 1, cities: cities)
672
+ end
387
673
 
388
674
  specify do
389
- expect(CountriesIndex::Country.root.compose(country_with_cities)).to eq('id' => 1, 'cities' => [
675
+ expect(CountriesIndex.root.compose(country_with_cities)).to eq('id' => 1, 'cities' => [
390
676
  {'id' => 1, 'name' => 'City1'}, {'id' => 2, 'name' => 'City2'}
391
677
  ])
392
678
  end
@@ -394,20 +680,19 @@ describe Chewy::Fields::Base do
394
680
  context 'nested object' do
395
681
  before do
396
682
  stub_index(:cities) do
397
- define_type City do
683
+ index_scope City
684
+ field :id
685
+ field :country do
398
686
  field :id
399
- field :country do
400
- field :id
401
- field :name
402
- end
687
+ field :name
403
688
  end
404
689
  end
405
690
  end
406
691
 
407
692
  specify do
408
- expect(CitiesIndex::City.root.compose(
409
- City.create!(id: 1, country: Country.create!(id: 1, name: 'Country'))
410
- )).to eq('id' => 1, 'country' => {'id' => 1, 'name' => 'Country'})
693
+ expect(
694
+ CitiesIndex.root.compose(City.create!(id: 1, country: Country.create!(id: 1, name: 'Country')))
695
+ ).to eq('id' => 1, 'country' => {'id' => 1, 'name' => 'Country'})
411
696
  end
412
697
  end
413
698
  end