chewy 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,6 +6,7 @@ describe Chewy::Query::Criteria do
6
6
  its(:options) { should be_a Hash }
7
7
  its(:request_options) { should be_a Hash }
8
8
  its(:facets) { should == {} }
9
+ its(:scores) { should == [] }
9
10
  its(:aggregations) { should == {} }
10
11
  its(:queries) { should == [] }
11
12
  its(:filters) { should == [] }
@@ -14,17 +15,18 @@ describe Chewy::Query::Criteria do
14
15
  its(:fields) { should == [] }
15
16
  its(:types) { should == [] }
16
17
 
17
- its(:request_options?) { should be_false }
18
- its(:facets?) { should be_false }
19
- its(:aggregations?) { should be_false }
20
- its(:queries?) { should be_false }
21
- its(:filters?) { should be_false }
22
- its(:post_filters?) { should be_false }
23
- its(:sort?) { should be_false }
24
- its(:fields?) { should be_false }
25
- its(:types?) { should be_false }
18
+ its(:request_options?) { should eq(false) }
19
+ its(:facets?) { should eq(false) }
20
+ its(:scores?) { should eq(false) }
21
+ its(:aggregations?) { should eq(false) }
22
+ its(:queries?) { should eq(false) }
23
+ its(:filters?) { should eq(false) }
24
+ its(:post_filters?) { should eq(false) }
25
+ its(:sort?) { should eq(false) }
26
+ its(:fields?) { should eq(false) }
27
+ its(:types?) { should eq(false) }
26
28
 
27
- its(:none?){ should be_false }
29
+ its(:none?){ should eq(false) }
28
30
 
29
31
  describe '#update_options' do
30
32
  specify { expect { subject.update_options(field: 'hello') }.to change { subject.options }.to(hash_including(field: 'hello')) }
@@ -39,6 +41,14 @@ describe Chewy::Query::Criteria do
39
41
  specify { expect { subject.update_facets(field: 'hello') }.to change { subject.facets }.to(field: 'hello') }
40
42
  end
41
43
 
44
+ describe '#update_scores' do
45
+ specify { expect { subject.update_scores(:score) }.to change { subject.scores? }.to(true) }
46
+ specify { expect { subject.update_scores(:score) }.to change { subject.scores }.to([:score]) }
47
+ specify { expect { subject.update_scores([:score, :score2]) }.to change { subject.scores }.to([:score, :score2]) }
48
+ specify { expect { subject.tap { |s| s.update_scores(:score1) }.update_scores([:score2, :score3]) }
49
+ .to change { subject.scores }.to([:score1, :score2, :score3]) }
50
+ end
51
+
42
52
  describe '#update_aggregations' do
43
53
  specify { expect { subject.update_aggregations(field: 'hello') }.to change { subject.aggregations? }.to(true) }
44
54
  specify { expect { subject.update_aggregations(field: 'hello') }.to change { subject.aggregations }.to(field: 'hello') }
@@ -122,6 +132,8 @@ describe Chewy::Query::Criteria do
122
132
  .merge(criteria.tap { |c| c.update_request_options(opt2: 'hello') }).request_options.should include(opt1: 'hello', opt2: 'hello') }
123
133
  specify { subject.tap { |c| c.update_facets(field1: 'hello') }
124
134
  .merge(criteria.tap { |c| c.update_facets(field1: 'hello') }).facets.should == {field1: 'hello', field1: 'hello'} }
135
+ specify { subject.tap { |c| c.update_scores(script: 'hello') }
136
+ .merge(criteria.tap { |c| c.update_scores(script: 'foobar') }).scores.should == [{script: 'hello'}, { script: 'foobar' } ] }
125
137
  specify { subject.tap { |c| c.update_aggregations(field1: 'hello') }
126
138
  .merge(criteria.tap { |c| c.update_aggregations(field1: 'hello') }).aggregations.should == {field1: 'hello', field1: 'hello'} }
127
139
  specify { subject.tap { |c| c.update_queries(field1: 'hello') }
@@ -177,6 +189,24 @@ describe Chewy::Query::Criteria do
177
189
  specify { request_body { update_request_options(from: 10) }.should == {body: {from: 10}} }
178
190
  specify { request_body { update_request_options(explain: true) }.should == {body: {explain: true}} }
179
191
  specify { request_body { update_queries(:query) }.should == {body: {query: :query}} }
192
+ specify { request_body {
193
+ update_scores(script_score: { script: '_score'})
194
+ }.should == {body: {query: { function_score: { functions: [{ script_score: {script: '_score' }}] }}}} }
195
+ specify { request_body {
196
+ update_scores(script_score: { script: "boost_me" })
197
+ update_queries(:query)
198
+ update_options(boost_mode: :add)
199
+ update_options(score_mode: :avg)
200
+ }.should == {body: {query: {
201
+ function_score: {
202
+ functions: [{
203
+ script_score: {script: 'boost_me' }
204
+ }],
205
+ query: :query,
206
+ boost_mode: :add,
207
+ score_mode: :avg
208
+ }}}}
209
+ }
180
210
  specify { request_body {
181
211
  update_request_options(from: 10); update_sort(:field); update_fields(:field); update_queries(:query)
182
212
  }.should == {body: {query: :query, from: 10, sort: [:field], _source: ['field']}} }
@@ -233,6 +263,24 @@ describe Chewy::Query::Criteria do
233
263
  }
234
264
  end
235
265
 
266
+ describe "#_boost_query" do
267
+ specify { subject.send(:_boost_query, query: :query).should eq(query: :query) }
268
+ specify {
269
+ subject.update_scores({ boost_factor: 5 })
270
+ subject.send(:_boost_query, query: :query).should eq(query: { function_score: { functions: [{ boost_factor: 5 }], query: :query } })
271
+ }
272
+ specify {
273
+ subject.update_scores({ boost_factor: 5 })
274
+ subject.update_options(boost_mode: :multiply)
275
+ subject.update_options(score_mode: :add)
276
+ subject.send(:_boost_query, query: :query).should eq(query: { function_score: { functions: [{ boost_factor: 5 }], query: :query, boost_mode: :multiply, score_mode: :add } })
277
+ }
278
+ specify {
279
+ subject.update_scores({ boost_factor: 5 })
280
+ subject.send(:_boost_query, query: :query, filter: :filter).should eq(query: { function_score: { functions: [{ boost_factor: 5 }], query: { filtered: { query: :query, filter: :filter } } } })
281
+ }
282
+ end
283
+
236
284
  describe '#_request_filter' do
237
285
  def _request_filter &block
238
286
  subject.instance_exec(&block) if block
@@ -75,6 +75,20 @@ describe Chewy::Query do
75
75
  specify { expect { subject.post_filter_mode(:or) }.not_to change { subject.criteria.options } }
76
76
  end
77
77
 
78
+ describe '#boost_mode' do
79
+ specify { subject.boost_mode(:replace).should be_a described_class }
80
+ specify { subject.boost_mode(:replace).should_not == subject }
81
+ specify { subject.boost_mode(:replace).criteria.options.should include(boost_mode: :replace) }
82
+ specify { expect { subject.boost_mode(:replace) }.not_to change { subject.criteria.options } }
83
+ end
84
+
85
+ describe '#score_mode' do
86
+ specify { subject.score_mode(:first).should be_a described_class }
87
+ specify { subject.score_mode(:first).should_not == subject }
88
+ specify { subject.score_mode(:first).criteria.options.should include(score_mode: :first) }
89
+ specify { expect { subject.score_mode(:first) }.not_to change { subject.criteria.options } }
90
+ end
91
+
78
92
  describe '#limit' do
79
93
  specify { subject.limit(10).should be_a described_class }
80
94
  specify { subject.limit(10).should_not == subject }
@@ -89,6 +103,74 @@ describe Chewy::Query do
89
103
  specify { expect { subject.offset(10) }.not_to change { subject.criteria.request_options } }
90
104
  end
91
105
 
106
+ describe '#script_score' do
107
+ specify { subject.script_score('23').should be_a described_class }
108
+ specify { subject.script_score('23').should_not == subject }
109
+ specify { subject.script_score('23').criteria.scores.should == [ { script_score: { script: '23' } } ] }
110
+ specify { expect { subject.script_score('23') }.not_to change { subject.criteria.scores } }
111
+ specify { subject.script_score('23', filter: { foo: :bar}).criteria.scores.should == [{ script_score: { script: '23' }, filter: { foo: :bar } }] }
112
+ end
113
+
114
+ describe '#boost_factor' do
115
+ specify { subject.boost_factor('23').should be_a described_class }
116
+ specify { subject.boost_factor('23').should_not == subject }
117
+ specify { subject.boost_factor('23').criteria.scores.should == [ { boost_factor: 23 } ] }
118
+ specify { expect { subject.boost_factor('23') }.not_to change { subject.criteria.scores } }
119
+ specify { subject.boost_factor('23', filter: { foo: :bar}).criteria.scores.should == [{ boost_factor: 23, filter: { foo: :bar } }] }
120
+ end
121
+
122
+ describe '#random_score' do
123
+ specify { subject.random_score('23').should be_a described_class }
124
+ specify { subject.random_score('23').should_not == subject }
125
+ specify { subject.random_score('23').criteria.scores.should == [ { random_score: { seed: 23 } } ] }
126
+ specify { expect { subject.random_score('23') }.not_to change { subject.criteria.scores } }
127
+ specify { subject.random_score('23', filter: { foo: :bar}).criteria.scores.should == [{ random_score: { seed: 23 }, filter: { foo: :bar } }] }
128
+ end
129
+
130
+ describe '#field_value_score' do
131
+ specify { subject.field_value_factor(field: :boost).should be_a described_class }
132
+ specify { subject.field_value_factor(field: :boost).should_not == subject }
133
+ specify { subject.field_value_factor(field: :boost).criteria.scores.should == [ { field_value_factor: { field: :boost } } ] }
134
+ specify { expect { subject.field_value_factor(field: :boost) }.not_to change { subject.criteria.scores } }
135
+ specify { subject.field_value_factor({ field: :boost }, filter: { foo: :bar}).criteria.scores.should == [{ field_value_factor: { field: :boost }, filter: { foo: :bar } }] }
136
+ end
137
+
138
+ describe '#decay' do
139
+ specify { subject.decay(:gauss, :field).should be_a described_class }
140
+ specify { subject.decay(:gauss, :field).should_not == subject }
141
+ specify { subject.decay(:gauss, :field).criteria.scores.should == [ {
142
+ gauss: {
143
+ field: {
144
+ origin: 0,
145
+ scale: 1,
146
+ offset: 0,
147
+ decay: 0.1
148
+ }
149
+ }
150
+ }] }
151
+ specify { expect { subject.decay(:gauss, :field) }.not_to change { subject.criteria.scores } }
152
+ specify {
153
+ subject.decay(:gauss, :field,
154
+ origin: '11, 12',
155
+ scale: '2km',
156
+ offset: '5km',
157
+ decay: 0.4,
158
+ filter: { foo: :bar }).criteria.scores.should == [
159
+ {
160
+ gauss: {
161
+ field: {
162
+ origin: '11, 12',
163
+ scale: '2km',
164
+ offset: '5km',
165
+ decay: 0.4
166
+ }
167
+ },
168
+ filter: { foo: :bar }
169
+ }
170
+ ]
171
+ }
172
+ end
173
+
92
174
  describe '#facets' do
93
175
  specify { subject.facets(term: {field: 'hello'}).should be_a described_class }
94
176
  specify { subject.facets(term: {field: 'hello'}).should_not == subject }
@@ -161,7 +243,7 @@ describe Chewy::Query do
161
243
  describe '#suggest' do
162
244
  specify { subject.suggest(name1: {text: 'hello', term: {field: 'name'}}) }
163
245
  specify { subject.suggest(name1: {text: 'hello'}).should_not == subject }
164
- specify { subject.suggest(name1: {text: 'hello'}).criteria.suggest.should include(name1: {text: 'hello'}) }
246
+ specify { expect(subject.suggest(name1: {text: 'hello'}).criteria.suggest).to include(name1: {text: 'hello'}) }
165
247
  specify { expect { subject.suggest(name1: {text: 'hello'}) }.not_to change { subject.criteria.suggest } }
166
248
 
167
249
  context 'results' do
@@ -196,13 +278,31 @@ describe Chewy::Query do
196
278
  end
197
279
  end
198
280
 
281
+ describe '#delete_all' do
282
+ let(:products) { 3.times.map { |i| {id: i.next.to_s, name: "Name#{i.next}", age: 10 * i.next}.stringify_keys! } }
283
+ let(:cities) { 3.times.map { |i| {id: i.next.to_s}.stringify_keys! } }
284
+ let(:countries) { 3.times.map { |i| {id: i.next.to_s}.stringify_keys! } }
285
+
286
+ before do
287
+ ProductsIndex::Product.import!(products.map { |h| double(h) })
288
+ ProductsIndex::City.import!(cities.map { |h| double(h) })
289
+ ProductsIndex::Country.import!(countries.map { |h| double(h) })
290
+ end
291
+
292
+ specify { expect { subject.query(match: {name: 'name3'}).delete_all }.to change { ProductsIndex.total_count }.from(9).to(8) }
293
+ specify { expect { subject.filter { age == [10, 20] }.delete_all }.to change { ProductsIndex.total_count }.from(9).to(7) }
294
+ specify { expect { subject.types(:product).delete_all }.to change { ProductsIndex::Product.total_count }.from(3).to(0) }
295
+ specify { expect { ProductsIndex.delete_all }.to change { ProductsIndex.total_count }.from(9).to(0) }
296
+ specify { expect { ProductsIndex::City.delete_all }.to change { ProductsIndex.total_count }.from(9).to(6) }
297
+ end
298
+
199
299
  describe '#none' do
200
300
  specify { subject.none.should be_a described_class }
201
301
  specify { subject.none.should_not == subject }
202
302
  specify { subject.none.criteria.should be_none }
203
303
 
204
304
  context do
205
- before { described_class.any_instance.should_not_receive(:_response) }
305
+ before { expect_any_instance_of(described_class).not_to receive(:_response) }
206
306
 
207
307
  specify { subject.none.to_a.should == [] }
208
308
  specify { subject.query(match: 'hello').none.to_a.should == [] }
@@ -4,6 +4,6 @@ describe Chewy::Runtime do
4
4
  describe '.version' do
5
5
  specify { described_class.version.should be_a(described_class::Version) }
6
6
  specify { described_class.version.should be >= '1.0' }
7
- specify { described_class.version.should be < '1.3' }
7
+ specify { described_class.version.should be < '1.4' }
8
8
  end
9
9
  end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chewy::Type::Actions do
4
+ before { Chewy.client.indices.delete index: '*' }
5
+
6
+ before do
7
+ stub_model(:city)
8
+ end
9
+
10
+ before do
11
+ stub_index(:cities) do
12
+ define_type City do
13
+ field :name
14
+ end
15
+ end
16
+ end
17
+
18
+ let!(:dummy_cities) { 3.times.map { |i| City.create(name: "name#{i}") } }
19
+ let(:city) { CitiesIndex::City }
20
+
21
+ before do
22
+ city.import
23
+ end
24
+
25
+ describe '.reset' do
26
+ specify { expect { city.reset }.to update_index(city) }
27
+ end
28
+ end
@@ -104,6 +104,7 @@ describe Chewy::Type::Adapter::ActiveRecord do
104
104
  specify { import(cities, deleted).should == [{index: cities, delete: deleted}] }
105
105
  specify { import(cities.map(&:id), deleted.map(&:id))
106
106
  .should == [{index: cities, delete: deleted}] }
107
+ specify { import(City.order(:id)).should == [{index: cities, delete: deleted}] }
107
108
  end
108
109
 
109
110
  context 'custom primary_key' do
@@ -177,45 +178,45 @@ describe Chewy::Type::Adapter::ActiveRecord do
177
178
  end
178
179
 
179
180
  context 'implicit scope' do
180
- specify { subject.import { |data| true }.should be_true }
181
- specify { subject.import { |data| false }.should be_false }
182
- specify { subject.import(batch_size: 1, &data_comparer.curry[cities[0].id]).should be_false }
183
- specify { subject.import(batch_size: 1, &data_comparer.curry[cities[1].id]).should be_false }
184
- specify { subject.import(batch_size: 1, &data_comparer.curry[cities[2].id]).should be_false }
185
- specify { subject.import(batch_size: 1, &data_comparer.curry[deleted[0].id]).should be_true }
186
- specify { subject.import(batch_size: 1, &data_comparer.curry[deleted[1].id]).should be_true }
181
+ specify { subject.import { |data| true }.should eq(true) }
182
+ specify { subject.import { |data| false }.should eq(false) }
183
+ specify { subject.import(batch_size: 1, &data_comparer.curry[cities[0].id]).should eq(false) }
184
+ specify { subject.import(batch_size: 1, &data_comparer.curry[cities[1].id]).should eq(false) }
185
+ specify { subject.import(batch_size: 1, &data_comparer.curry[cities[2].id]).should eq(false) }
186
+ specify { subject.import(batch_size: 1, &data_comparer.curry[deleted[0].id]).should eq(true) }
187
+ specify { subject.import(batch_size: 1, &data_comparer.curry[deleted[1].id]).should eq(true) }
187
188
  end
188
189
 
189
190
  context 'explicit scope' do
190
191
  let(:scope) { City.where(id: ids) }
191
192
 
192
- specify { subject.import(scope) { |data| true }.should be_true }
193
- specify { subject.import(scope) { |data| false }.should be_false }
194
- specify { subject.import(scope, batch_size: 1, &data_comparer.curry[cities[0].id]).should be_false }
195
- specify { subject.import(scope, batch_size: 1, &data_comparer.curry[cities[1].id]).should be_false }
196
- specify { subject.import(scope, batch_size: 1, &data_comparer.curry[cities[2].id]).should be_false }
197
- specify { subject.import(scope, batch_size: 1, &data_comparer.curry[deleted[0].id]).should be_true }
198
- specify { subject.import(scope, batch_size: 1, &data_comparer.curry[deleted[1].id]).should be_true }
193
+ specify { subject.import(scope) { |data| true }.should eq(true) }
194
+ specify { subject.import(scope) { |data| false }.should eq(false) }
195
+ specify { subject.import(scope, batch_size: 1, &data_comparer.curry[cities[0].id]).should eq(false) }
196
+ specify { subject.import(scope, batch_size: 1, &data_comparer.curry[cities[1].id]).should eq(false) }
197
+ specify { subject.import(scope, batch_size: 1, &data_comparer.curry[cities[2].id]).should eq(false) }
198
+ specify { subject.import(scope, batch_size: 1, &data_comparer.curry[deleted[0].id]).should eq(true) }
199
+ specify { subject.import(scope, batch_size: 1, &data_comparer.curry[deleted[1].id]).should eq(true) }
199
200
  end
200
201
 
201
202
  context 'objects' do
202
- specify { subject.import(cities + deleted) { |data| true }.should be_true }
203
- specify { subject.import(cities + deleted) { |data| false }.should be_false }
204
- specify { subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[cities[0].id]).should be_false }
205
- specify { subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[cities[1].id]).should be_false }
206
- specify { subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[cities[2].id]).should be_false }
207
- specify { subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[deleted[0].id]).should be_false }
208
- specify { subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[deleted[1].id]).should be_false }
203
+ specify { subject.import(cities + deleted) { |data| true }.should eq(true) }
204
+ specify { subject.import(cities + deleted) { |data| false }.should eq(false) }
205
+ specify { subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[cities[0].id]).should eq(false) }
206
+ specify { subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[cities[1].id]).should eq(false) }
207
+ specify { subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[cities[2].id]).should eq(false) }
208
+ specify { subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[deleted[0].id]).should eq(false) }
209
+ specify { subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[deleted[1].id]).should eq(false) }
209
210
  end
210
211
 
211
212
  context 'ids' do
212
- specify { subject.import(ids) { |data| true }.should be_true }
213
- specify { subject.import(ids) { |data| false }.should be_false }
214
- specify { subject.import(ids, batch_size: 1, &data_comparer.curry[cities[0].id]).should be_false }
215
- specify { subject.import(ids, batch_size: 1, &data_comparer.curry[cities[1].id]).should be_false }
216
- specify { subject.import(ids, batch_size: 1, &data_comparer.curry[cities[2].id]).should be_false }
217
- specify { subject.import(ids, batch_size: 1, &data_comparer.curry[deleted[0].id]).should be_false }
218
- specify { subject.import(ids, batch_size: 1, &data_comparer.curry[deleted[1].id]).should be_false }
213
+ specify { subject.import(ids) { |data| true }.should eq(true) }
214
+ specify { subject.import(ids) { |data| false }.should eq(false) }
215
+ specify { subject.import(ids, batch_size: 1, &data_comparer.curry[cities[0].id]).should eq(false) }
216
+ specify { subject.import(ids, batch_size: 1, &data_comparer.curry[cities[1].id]).should eq(false) }
217
+ specify { subject.import(ids, batch_size: 1, &data_comparer.curry[cities[2].id]).should eq(false) }
218
+ specify { subject.import(ids, batch_size: 1, &data_comparer.curry[deleted[0].id]).should eq(false) }
219
+ specify { subject.import(ids, batch_size: 1, &data_comparer.curry[deleted[1].id]).should eq(false) }
219
220
  end
220
221
  end
221
222
  end
@@ -36,8 +36,8 @@ describe Chewy::Type::Adapter::Object do
36
36
  result
37
37
  end
38
38
 
39
- specify { subject.import(3.times.map { |i| double }) { |data| true }.should be_true }
40
- specify { subject.import(3.times.map { |i| double }) { |data| false }.should be_false }
39
+ specify { subject.import(3.times.map { |i| double }) { |data| true }.should eq(true) }
40
+ specify { subject.import(3.times.map { |i| double }) { |data| false }.should eq(false) }
41
41
 
42
42
  context do
43
43
  let(:objects) { 3.times.map { |i| double } }
@@ -96,13 +96,13 @@ describe Chewy::Type::Adapter::Object do
96
96
  ->(n, data) { (data[:index] || data[:delete]).first.rating != n }
97
97
  end
98
98
 
99
- specify { subject.import(products, deleted) { |data| true }.should be_true }
100
- specify { subject.import(products, deleted) { |data| false }.should be_false }
101
- specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[1]).should be_false }
102
- specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[2]).should be_false }
103
- specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[3]).should be_false }
104
- specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[4]).should be_false }
105
- specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[5]).should be_false }
99
+ specify { subject.import(products, deleted) { |data| true }.should eq(true) }
100
+ specify { subject.import(products, deleted) { |data| false }.should eq(false) }
101
+ specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[1]).should eq(false) }
102
+ specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[2]).should eq(false) }
103
+ specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[3]).should eq(false) }
104
+ specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[4]).should eq(false) }
105
+ specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[5]).should eq(false) }
106
106
  end
107
107
  end
108
108
 
@@ -19,10 +19,10 @@ describe Chewy::Type::Import do
19
19
  let(:city) { CitiesIndex::City }
20
20
 
21
21
  describe '.import' do
22
- specify { city.import.should be_true }
23
- specify { city.import([]).should be_true }
24
- specify { city.import(dummy_cities).should be_true }
25
- specify { city.import(dummy_cities.map(&:id)).should be_true }
22
+ specify { city.import.should eq(true) }
23
+ specify { city.import([]).should eq(true) }
24
+ specify { city.import(dummy_cities).should eq(true) }
25
+ specify { city.import(dummy_cities.map(&:id)).should eq(true) }
26
26
 
27
27
  specify { expect { city.import([]) }.not_to update_index(city) }
28
28
  specify { expect { city.import }.to update_index(city).and_reindex(dummy_cities) }
@@ -153,9 +153,9 @@ describe Chewy::Type::Import do
153
153
  end
154
154
  end
155
155
 
156
- specify { city.import(dummy_cities).should be_false }
157
- specify { city.import(dummy_cities.map(&:id)).should be_false }
158
- specify { city.import(dummy_cities, batch_size: 1).should be_false }
156
+ specify { city.import(dummy_cities).should eq(false) }
157
+ specify { city.import(dummy_cities.map(&:id)).should eq(false) }
158
+ specify { city.import(dummy_cities, batch_size: 1).should eq(false) }
159
159
  end
160
160
 
161
161
  context do
@@ -167,9 +167,86 @@ describe Chewy::Type::Import do
167
167
  end
168
168
  end
169
169
 
170
- specify { city.import(dummy_cities).should be_false }
171
- specify { city.import(dummy_cities.map(&:id)).should be_false }
172
- specify { city.import(dummy_cities, batch_size: 1).should be_false }
170
+ specify { city.import(dummy_cities).should eq(false) }
171
+ specify { city.import(dummy_cities.map(&:id)).should eq(false) }
172
+ specify { city.import(dummy_cities, batch_size: 1).should eq(false) }
173
+ end
174
+ end
175
+
176
+ context 'parent-child relationship' do
177
+ let(:country) { Country.create(name: 'country') }
178
+ let(:another_country) { Country.create(name: 'another country') }
179
+
180
+ before do
181
+ stub_model(:country)
182
+ stub_model(:city)
183
+ end
184
+
185
+ before do
186
+ stub_index(:countries) do
187
+ define_type Country do
188
+ field :name
189
+ end
190
+
191
+ define_type City do
192
+ root parent: { type: 'country' }, parent_id: -> { country_id } do
193
+ field :name
194
+ end
195
+ end
196
+ end
197
+ end
198
+
199
+ before { CountriesIndex::Country.import(country) }
200
+
201
+ let(:child_city) { City.create(country_id: country.id, name: 'city') }
202
+ let(:city) { CountriesIndex::City }
203
+
204
+ specify { city.import(child_city).should eq(true) }
205
+ specify { expect { city.import child_city }.to update_index(city).and_reindex(child_city) }
206
+
207
+ specify do
208
+ expect(CountriesIndex.client).to receive(:bulk).with(hash_including(
209
+ body: [{ index: { _id: child_city.id, parent: country.id, data: { 'name' => 'city' } } }]
210
+ ))
211
+
212
+ city.import child_city
213
+ end
214
+
215
+ context 'updating or deleting' do
216
+ before { city.import child_city }
217
+
218
+ specify do
219
+ child_city.update_attributes(country_id: another_country.id)
220
+
221
+ expect(CountriesIndex.client).to receive(:bulk).with(hash_including(
222
+ body: [
223
+ { delete: { _id: child_city.id, parent: country.id.to_s } },
224
+ { index: { _id: child_city.id, parent: another_country.id, data: { 'name' => 'city' } } }
225
+ ]
226
+ ))
227
+
228
+ city.import child_city
229
+ end
230
+
231
+ specify do
232
+ child_city.destroy
233
+
234
+ expect(CountriesIndex.client).to receive(:bulk).with(hash_including(
235
+ body: [{ delete: { _id: child_city.id, parent: country.id.to_s } }]
236
+ ))
237
+
238
+ city.import child_city
239
+ end
240
+
241
+ specify do
242
+ child_city.destroy
243
+
244
+ expect(CountriesIndex.client).to receive(:bulk).with(hash_including(
245
+ body: [{ delete: { _id: child_city.id, parent: country.id.to_s } }]
246
+ ))
247
+
248
+ city.import child_city.id
249
+ end
173
250
  end
174
251
  end
175
252
  end