chewy 0.5.0 → 0.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.
@@ -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