chewy 0.5.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +26 -4
  3. data/CHANGELOG.md +16 -0
  4. data/Gemfile +3 -1
  5. data/README.md +2 -10
  6. data/chewy.gemspec +0 -1
  7. data/gemfiles/Gemfile.rails-3.2.active_record +6 -0
  8. data/gemfiles/Gemfile.rails-3.2.active_record.kaminari +7 -0
  9. data/gemfiles/Gemfile.rails-3.2.active_record.will_paginate +7 -0
  10. data/gemfiles/Gemfile.rails-4.0.active_record +6 -0
  11. data/gemfiles/Gemfile.rails-4.0.active_record.kaminari +7 -0
  12. data/gemfiles/Gemfile.rails-4.0.active_record.will_paginate +7 -0
  13. data/gemfiles/Gemfile.rails-4.0.mongoid +6 -0
  14. data/gemfiles/Gemfile.rails-4.0.mongoid.kaminari +7 -0
  15. data/gemfiles/Gemfile.rails-4.0.mongoid.will_paginate +7 -0
  16. data/gemfiles/Gemfile.rails-4.1.active_record +6 -0
  17. data/gemfiles/Gemfile.rails-4.1.active_record.kaminari +7 -0
  18. data/gemfiles/Gemfile.rails-4.1.active_record.will_paginate +7 -0
  19. data/gemfiles/Gemfile.rails-4.1.mongoid +6 -0
  20. data/gemfiles/Gemfile.rails-4.1.mongoid.kaminari +7 -0
  21. data/gemfiles/Gemfile.rails-4.1.mongoid.will_paginate +7 -0
  22. data/gemfiles/Gemfile.rails-4.2.active_record +6 -0
  23. data/gemfiles/Gemfile.rails-4.2.active_record.kaminari +7 -0
  24. data/gemfiles/Gemfile.rails-4.2.active_record.will_paginate +7 -0
  25. data/gemfiles/Gemfile.rails-4.2.mongoid +6 -0
  26. data/gemfiles/Gemfile.rails-4.2.mongoid.kaminari +7 -0
  27. data/gemfiles/Gemfile.rails-4.2.mongoid.will_paginate +7 -0
  28. data/lib/chewy.rb +33 -5
  29. data/lib/chewy/config.rb +1 -0
  30. data/lib/chewy/index/search.rb +6 -3
  31. data/lib/chewy/query.rb +74 -1
  32. data/lib/chewy/query/compose.rb +4 -4
  33. data/lib/chewy/query/pagination.rb +5 -4
  34. data/lib/chewy/query/pagination/kaminari.rb +1 -1
  35. data/lib/chewy/query/pagination/will_paginate.rb +27 -0
  36. data/lib/chewy/type.rb +1 -0
  37. data/lib/chewy/type/adapter/active_record.rb +2 -2
  38. data/lib/chewy/type/adapter/mongoid.rb +147 -0
  39. data/lib/chewy/type/adapter/object.rb +1 -1
  40. data/lib/chewy/type/import.rb +1 -0
  41. data/lib/chewy/type/observe.rb +34 -6
  42. data/lib/chewy/version.rb +1 -1
  43. data/spec/chewy/config_spec.rb +17 -17
  44. data/spec/chewy/fields/base_spec.rb +62 -62
  45. data/spec/chewy/fields/root_spec.rb +5 -5
  46. data/spec/chewy/index/actions_spec.rb +127 -127
  47. data/spec/chewy/index/aliases_spec.rb +9 -9
  48. data/spec/chewy/index/search_spec.rb +4 -4
  49. data/spec/chewy/index/settings_spec.rb +33 -33
  50. data/spec/chewy/index_spec.rb +49 -49
  51. data/spec/chewy/query/criteria_spec.rb +173 -161
  52. data/spec/chewy/query/filters_spec.rb +76 -76
  53. data/spec/chewy/query/loading_spec.rb +54 -23
  54. data/spec/chewy/query/nodes/and_spec.rb +4 -4
  55. data/spec/chewy/query/nodes/bool_spec.rb +8 -8
  56. data/spec/chewy/query/nodes/equal_spec.rb +19 -19
  57. data/spec/chewy/query/nodes/exists_spec.rb +6 -6
  58. data/spec/chewy/query/nodes/has_child_spec.rb +25 -25
  59. data/spec/chewy/query/nodes/has_parent_spec.rb +25 -25
  60. data/spec/chewy/query/nodes/match_all_spec.rb +1 -1
  61. data/spec/chewy/query/nodes/missing_spec.rb +4 -4
  62. data/spec/chewy/query/nodes/not_spec.rb +4 -4
  63. data/spec/chewy/query/nodes/or_spec.rb +4 -4
  64. data/spec/chewy/query/nodes/prefix_spec.rb +5 -5
  65. data/spec/chewy/query/nodes/query_spec.rb +2 -2
  66. data/spec/chewy/query/nodes/range_spec.rb +18 -18
  67. data/spec/chewy/query/nodes/raw_spec.rb +1 -1
  68. data/spec/chewy/query/nodes/regexp_spec.rb +18 -18
  69. data/spec/chewy/query/nodes/script_spec.rb +4 -4
  70. data/spec/chewy/query/pagination/kaminari_spec.rb +41 -39
  71. data/spec/chewy/query/pagination/will_paginage_spec.rb +60 -0
  72. data/spec/chewy/query/pagination_spec.rb +8 -7
  73. data/spec/chewy/query_spec.rb +166 -167
  74. data/spec/chewy/rspec/update_index_spec.rb +1 -1
  75. data/spec/chewy/runtime/version_spec.rb +30 -30
  76. data/spec/chewy/runtime_spec.rb +3 -3
  77. data/spec/chewy/type/actions_spec.rb +3 -3
  78. data/spec/chewy/type/adapter/active_record_spec.rb +143 -143
  79. data/spec/chewy/type/adapter/mongoid_spec.rb +219 -0
  80. data/spec/chewy/type/adapter/object_spec.rb +39 -39
  81. data/spec/chewy/type/import_spec.rb +67 -37
  82. data/spec/chewy/type/mapping_spec.rb +12 -12
  83. data/spec/chewy/type/observe_spec.rb +5 -6
  84. data/spec/chewy/type/wrapper_spec.rb +12 -12
  85. data/spec/chewy_spec.rb +26 -28
  86. data/spec/spec_helper.rb +19 -31
  87. data/spec/support/active_record.rb +52 -0
  88. data/spec/support/class_helpers.rb +0 -4
  89. data/spec/support/mongoid.rb +87 -0
  90. metadata +33 -18
  91. data/gemfiles/Gemfile.rails-3.2 +0 -15
  92. data/gemfiles/Gemfile.rails-4.0 +0 -15
@@ -0,0 +1,219 @@
1
+ require 'spec_helper'
2
+
3
+ describe Chewy::Type::Adapter::Mongoid, :mongoid do
4
+ before { stub_model(:city) }
5
+
6
+ describe '#name' do
7
+ specify { expect(described_class.new(City).name).to eq('City') }
8
+ specify { expect(described_class.new(City.order(:id.asc)).name).to eq('City') }
9
+ specify { expect(described_class.new(City, name: 'town').name).to eq('Town') }
10
+
11
+ context do
12
+ before { stub_model('namespace/city') }
13
+
14
+ specify { expect(described_class.new(Namespace::City).name).to eq('City') }
15
+ specify { expect(described_class.new(Namespace::City.order(:id.asc)).name).to eq('City') }
16
+ end
17
+ end
18
+
19
+ describe '#type_name' do
20
+ specify { expect(described_class.new(City).type_name).to eq('city') }
21
+ specify { expect(described_class.new(City.order(:id.asc)).type_name).to eq('city') }
22
+ specify { expect(described_class.new(City, name: 'town').type_name).to eq('town') }
23
+
24
+ context do
25
+ before { stub_model('namespace/city') }
26
+
27
+ specify { expect(described_class.new(Namespace::City).type_name).to eq('city') }
28
+ specify { expect(described_class.new(Namespace::City.order(:id.asc)).type_name).to eq('city') }
29
+ end
30
+ end
31
+
32
+ describe '#import' do
33
+ def import(*args)
34
+ result = []
35
+ subject.import(*args) { |data| result.push data }
36
+ result
37
+ end
38
+
39
+ context do
40
+ let!(:cities) { 3.times.map { |i| City.create! }.sort_by(&:id) }
41
+ let!(:deleted) { 3.times.map { |i| City.create!.tap(&:destroy) }.sort_by(&:id) }
42
+ subject { described_class.new(City) }
43
+
44
+ specify { expect(import).to eq([{index: cities}]) }
45
+
46
+ specify { expect(import(City.order(:id.asc))).to eq([{index: cities}]) }
47
+ specify { expect(import(City.order(:id.asc), batch_size: 2))
48
+ .to eq([{index: cities.first(2)}, {index: cities.last(1)}]) }
49
+
50
+ specify { expect(import(cities)).to eq([{index: cities}]) }
51
+ specify { expect(import(cities, batch_size: 2))
52
+ .to eq([{index: cities.first(2)}, {index: cities.last(1)}]) }
53
+ specify { expect(import(cities, deleted)).to eq([{index: cities, delete: deleted}]) }
54
+ specify { expect(import(cities, deleted, batch_size: 2)).to eq([
55
+ {index: cities.first(2)},
56
+ {index: cities.last(1), delete: deleted.first(1)},
57
+ {delete: deleted.last(2)}]) }
58
+
59
+ specify { expect(import(cities.map(&:id))).to eq([{index: cities}]) }
60
+ specify { expect(import(deleted.map(&:id))).to eq([{delete: deleted.map(&:id)}]) }
61
+ specify { expect(import(cities.map(&:id), batch_size: 2))
62
+ .to eq([{index: cities.first(2)}, {index: cities.last(1)}]) }
63
+ specify { expect(import(cities.map(&:id), deleted.map(&:id)))
64
+ .to eq([{index: cities}, {delete: deleted.map(&:id)}]) }
65
+ specify { expect(import(cities.map(&:id), deleted.map(&:id), batch_size: 2)).to eq([
66
+ {index: cities.first(2)},
67
+ {index: cities.last(1)},
68
+ {delete: deleted.first(2).map(&:id)},
69
+ {delete: deleted.last(1).map(&:id)}]) }
70
+
71
+ specify { expect(import(cities.first, nil)).to eq([{index: [cities.first]}]) }
72
+ specify { expect(import(cities.first.id, nil)).to eq([{index: [cities.first]}]) }
73
+
74
+ context do
75
+ before { deleted.map { |object| allow(object).to receive_messages(delete_from_index?: true, destroyed?: true) } }
76
+ specify { expect(import(deleted)).to eq([{delete: deleted}]) }
77
+ end
78
+
79
+ context do
80
+ before { deleted.map { |object| allow(object).to receive_messages(delete_from_index?: true, destroyed?: false) } }
81
+ specify { expect(import(deleted)).to eq([{delete: deleted}]) }
82
+ end
83
+
84
+ context do
85
+ before { deleted.map { |object| allow(object).to receive_messages(delete_from_index?: false, destroyed?: true) } }
86
+ specify { expect(import(deleted)).to eq([{delete: deleted}]) }
87
+ end
88
+
89
+ context do
90
+ before { deleted.map { |object| allow(object).to receive_messages(delete_from_index?: false, destroyed?: false) } }
91
+ specify { expect(import(deleted)).to eq([{index: deleted}]) }
92
+ end
93
+ end
94
+
95
+ describe '#delete_from_index?' do
96
+ before do
97
+ stub_model(:city) do
98
+ def delete_from_index?
99
+ rating == 42
100
+ end
101
+ end
102
+ end
103
+ let!(:cities) { 3.times.map { |i| City.create! }.sort_by(&:id) }
104
+ let!(:deleted) { 3.times.map { |i| City.create!(rating: 42) }.sort_by(&:id) }
105
+ subject { described_class.new(City) }
106
+
107
+ specify { expect(import(cities, deleted)).to eq([{index: cities, delete: deleted}]) }
108
+ specify { expect(import(cities.map(&:id), deleted.map(&:id)))
109
+ .to eq([{index: cities, delete: deleted}]) }
110
+ specify { expect(import(City.order(:id.asc))).to eq([{index: cities, delete: deleted}]) }
111
+ end
112
+
113
+ context 'default scope' do
114
+ let!(:cities) { 3.times.map { |i| City.create!(rating: i/2) }.sort_by(&:id) }
115
+ let!(:deleted) { 2.times.map { |i| City.create!.tap(&:destroy) }.sort_by(&:id) }
116
+ subject { described_class.new(City.where(rating: 0)) }
117
+
118
+ specify { expect(import).to eq([{index: cities.first(2)}]) }
119
+
120
+ specify { expect(import(City.order(:id.asc))).to eq([{index: cities.first(2)}]) }
121
+ xspecify { expect(import(City.order(:id.asc), batch_size: 1))
122
+ .to eq([{index: [cities.first]}, {index: [cities.second]}]) }
123
+
124
+ specify { expect(import(cities)).to eq([{index: cities}]) }
125
+ specify { expect(import(cities, batch_size: 2))
126
+ .to eq([{index: cities.first(2)}, {index: cities.last(1)}]) }
127
+
128
+ specify { expect(import(cities.map(&:id)))
129
+ .to eq([{index: cities.first(2)}, {delete: [cities.last.id]}]) }
130
+ xspecify { expect(import(cities.map(&:id), batch_size: 1))
131
+ .to eq([{index: [cities.first]}, {index: [cities.second]}, {delete: [cities.last.id]}]) }
132
+ specify { expect(import(cities.map(&:id), deleted.map(&:id)))
133
+ .to eq([{index: cities.first(2)}, {delete: [cities.last.id] + deleted.map(&:id)}]) }
134
+ specify { expect(import(cities.map(&:id), deleted.map(&:id), batch_size: 2)).to eq([
135
+ {index: cities.first(2)},
136
+ {delete: [cities.last.id] + deleted.first(1).map(&:id)},
137
+ {delete: deleted.last(1).map(&:id)}]) }
138
+ end
139
+
140
+ context 'error handling' do
141
+ let!(:cities) { 6.times.map { |i| City.create! }.sort_by(&:id) }
142
+ let!(:deleted) { 4.times.map { |i| City.create!.tap(&:destroy) }.sort_by(&:id) }
143
+ let(:ids) { (cities + deleted).map(&:id) }
144
+ subject { described_class.new(City) }
145
+
146
+ let(:data_comparer) do
147
+ ->(ids, data) { objects = (data[:index] || data[:delete]).first(2); objects.map { |o| o.respond_to?(:id) ? o.id : o }.sort != ids.map(&:id).sort }
148
+ end
149
+
150
+ context 'implicit scope' do
151
+ specify { expect(subject.import { |data| true }).to eq(true) }
152
+ specify { expect(subject.import { |data| false }).to eq(false) }
153
+ specify { expect(subject.import(batch_size: 2, &data_comparer.curry[cities[0..1]])).to eq(false) }
154
+ specify { expect(subject.import(batch_size: 2, &data_comparer.curry[cities[2..3]])).to eq(false) }
155
+ specify { expect(subject.import(batch_size: 2, &data_comparer.curry[cities[4..5]])).to eq(false) }
156
+ specify { expect(subject.import(batch_size: 2, &data_comparer.curry[deleted[0..1]])).to eq(true) }
157
+ specify { expect(subject.import(batch_size: 2, &data_comparer.curry[deleted[2..3]])).to eq(true) }
158
+ end
159
+
160
+ context 'explicit scope' do
161
+ let(:scope) { mongoid? ? City.where(:id.in => ids) : City.where(id: ids) }
162
+
163
+ specify { expect(subject.import(scope) { |data| true }).to eq(true) }
164
+ specify { expect(subject.import(scope) { |data| false }).to eq(false) }
165
+ specify { expect(subject.import(scope, batch_size: 2, &data_comparer.curry[cities[0..1]])).to eq(false) }
166
+ specify { expect(subject.import(scope, batch_size: 2, &data_comparer.curry[cities[2..3]])).to eq(false) }
167
+ specify { expect(subject.import(scope, batch_size: 2, &data_comparer.curry[cities[4..5]])).to eq(false) }
168
+ specify { expect(subject.import(scope, batch_size: 2, &data_comparer.curry[deleted[0..1]])).to eq(true) }
169
+ specify { expect(subject.import(scope, batch_size: 2, &data_comparer.curry[deleted[2..3]])).to eq(true) }
170
+ end
171
+
172
+ context 'objects' do
173
+ specify { expect(subject.import(cities + deleted) { |data| true }).to eq(true) }
174
+ specify { expect(subject.import(cities + deleted) { |data| false }).to eq(false) }
175
+ specify { expect(subject.import(cities + deleted, batch_size: 2, &data_comparer.curry[cities[0..1]])).to eq(false) }
176
+ specify { expect(subject.import(cities + deleted, batch_size: 2, &data_comparer.curry[cities[2..3]])).to eq(false) }
177
+ specify { expect(subject.import(cities + deleted, batch_size: 2, &data_comparer.curry[cities[4..5]])).to eq(false) }
178
+ specify { expect(subject.import(cities + deleted, batch_size: 2, &data_comparer.curry[deleted[0..1]])).to eq(false) }
179
+ specify { expect(subject.import(cities + deleted, batch_size: 2, &data_comparer.curry[deleted[2..3]])).to eq(false) }
180
+ end
181
+
182
+ context 'ids' do
183
+ specify { expect(subject.import(ids) { |data| true }).to eq(true) }
184
+ specify { expect(subject.import(ids) { |data| false }).to eq(false) }
185
+ specify { expect(subject.import(ids, batch_size: 2, &data_comparer.curry[cities[0..1]])).to eq(false) }
186
+ specify { expect(subject.import(ids, batch_size: 2, &data_comparer.curry[cities[2..3]])).to eq(false) }
187
+ specify { expect(subject.import(ids, batch_size: 2, &data_comparer.curry[cities[4..5]])).to eq(false) }
188
+ specify { expect(subject.import(ids, batch_size: 2, &data_comparer.curry[deleted[0..1]])).to eq(false) }
189
+ specify { expect(subject.import(ids, batch_size: 2, &data_comparer.curry[deleted[2..3]])).to eq(false) }
190
+ end
191
+ end
192
+ end
193
+
194
+ describe '#load' do
195
+ context do
196
+ let!(:cities) { 3.times.map { |i| City.create!(rating: i/2) }.sort_by(&:id) }
197
+ let!(:deleted) { 2.times.map { |i| City.create!.tap(&:destroy) }.sort_by(&:id) }
198
+
199
+ let(:type) { double(type_name: 'user') }
200
+
201
+ subject { described_class.new(City) }
202
+
203
+ specify { expect(subject.load(cities.map { |c| double(id: c.id) }, _type: type)).to eq(cities) }
204
+ specify { expect(subject.load(cities.map { |c| double(id: c.id) }.reverse, _type: type)).to eq(cities.reverse) }
205
+ specify { expect(subject.load(deleted.map { |c| double(id: c.id) }, _type: type)).to eq([nil, nil]) }
206
+ specify { expect(subject.load((cities + deleted).map { |c| double(id: c.id) }, _type: type)).to eq([*cities, nil, nil]) }
207
+ specify { expect(subject.load(cities.map { |c| double(id: c.id) }, _type: type, scope: ->{ where(rating: 0) }))
208
+ .to eq(cities.first(2) + [nil]) }
209
+ specify { expect(subject.load(cities.map { |c| double(id: c.id) },
210
+ _type: type, scope: ->{ where(rating: 0) }, user: {scope: ->{ where(rating: 1)}}))
211
+ .to eq([nil, nil] + cities.last(1)) }
212
+ specify { expect(subject.load(cities.map { |c| double(id: c.id) }, _type: type, scope: City.where(rating: 1)))
213
+ .to eq([nil, nil] + cities.last(1)) }
214
+ specify { expect(subject.load(cities.map { |c| double(id: c.id) },
215
+ _type: type, scope: City.where(rating: 1), user: {scope: ->{ where(rating: 0)}}))
216
+ .to eq(cities.first(2) + [nil]) }
217
+ end
218
+ end
219
+ end
@@ -4,28 +4,28 @@ describe Chewy::Type::Adapter::Object do
4
4
  before { stub_class(:product) }
5
5
 
6
6
  describe '#name' do
7
- specify { described_class.new('product').name.should == 'Product' }
8
- specify { described_class.new(:products).name.should == 'Products' }
9
- specify { described_class.new(Product).name.should == 'Product' }
10
- specify { described_class.new(Product, name: 'house').name.should == 'House' }
7
+ specify { expect(described_class.new('product').name).to eq('Product') }
8
+ specify { expect(described_class.new(:products).name).to eq('Products') }
9
+ specify { expect(described_class.new(Product).name).to eq('Product') }
10
+ specify { expect(described_class.new(Product, name: 'house').name).to eq('House') }
11
11
 
12
12
  context do
13
13
  before { stub_class('namespace/product') }
14
14
 
15
- specify { described_class.new(Namespace::Product).name.should == 'Product' }
15
+ specify { expect(described_class.new(Namespace::Product).name).to eq('Product') }
16
16
  end
17
17
  end
18
18
 
19
19
  describe '#type_name' do
20
- specify { described_class.new('product').type_name.should == 'product' }
21
- specify { described_class.new(:products).type_name.should == 'products' }
22
- specify { described_class.new(Product).type_name.should == 'product' }
23
- specify { described_class.new(Product, name: 'house').type_name.should == 'house' }
20
+ specify { expect(described_class.new('product').type_name).to eq('product') }
21
+ specify { expect(described_class.new(:products).type_name).to eq('products') }
22
+ specify { expect(described_class.new(Product).type_name).to eq('product') }
23
+ specify { expect(described_class.new(Product, name: 'house').type_name).to eq('house') }
24
24
 
25
25
  context do
26
26
  before { stub_class('namespace/product') }
27
27
 
28
- specify { described_class.new(Namespace::Product).type_name.should == 'product' }
28
+ specify { expect(described_class.new(Namespace::Product).type_name).to eq('product') }
29
29
  end
30
30
  end
31
31
 
@@ -36,61 +36,61 @@ 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 eq(true) }
40
- specify { subject.import(3.times.map { |i| double }) { |data| false }.should eq(false) }
39
+ specify { expect(subject.import(3.times.map { |i| double }) { |data| true }).to eq(true) }
40
+ specify { expect(subject.import(3.times.map { |i| double }) { |data| false }).to eq(false) }
41
41
 
42
42
  context do
43
43
  let(:objects) { 3.times.map { |i| double } }
44
44
  let(:deleted) { 2.times.map { |i| double(destroyed?: true) } }
45
45
  subject { described_class.new('product') }
46
46
 
47
- specify { import.should == [] }
48
- specify { import(objects).should == [{index: objects}] }
49
- specify { import(objects, batch_size: 2)
50
- .should == [{index: objects.first(2)}, {index: objects.last(1)}] }
51
- specify { import(objects, deleted).should == [{index: objects, delete: deleted}] }
52
- specify { import(objects, deleted, batch_size: 2).should == [
47
+ specify { expect(import).to eq([]) }
48
+ specify { expect(import(objects)).to eq([{index: objects}]) }
49
+ specify { expect(import(objects, batch_size: 2))
50
+ .to eq([{index: objects.first(2)}, {index: objects.last(1)}]) }
51
+ specify { expect(import(objects, deleted)).to eq([{index: objects, delete: deleted}]) }
52
+ specify { expect(import(objects, deleted, batch_size: 2)).to eq([
53
53
  {index: objects.first(2)},
54
54
  {index: objects.last(1), delete: deleted.first(1)},
55
- {delete: deleted.last(1)}] }
55
+ {delete: deleted.last(1)}]) }
56
56
 
57
- specify { import(objects.first, nil).should == [{index: [objects.first]}] }
57
+ specify { expect(import(objects.first, nil)).to eq([{index: [objects.first]}]) }
58
58
 
59
59
  context do
60
60
  let(:deleted) { 2.times.map { |i| double(delete_from_index?: true, destroyed?: true) } }
61
- specify { import(deleted).should == [{delete: deleted}] }
61
+ specify { expect(import(deleted)).to eq([{delete: deleted}]) }
62
62
  end
63
63
 
64
64
  context do
65
65
  let(:deleted) { 2.times.map { |i| double(delete_from_index?: true, destroyed?: false) } }
66
- specify { import(deleted).should == [{delete: deleted}] }
66
+ specify { expect(import(deleted)).to eq([{delete: deleted}]) }
67
67
  end
68
68
 
69
69
 
70
70
  context do
71
71
  let(:deleted) { 2.times.map { |i| double(delete_from_index?: false, destroyed?: true) } }
72
- specify { import(deleted).should == [{delete: deleted}] }
72
+ specify { expect(import(deleted)).to eq([{delete: deleted}]) }
73
73
  end
74
74
 
75
75
  context do
76
76
  let(:deleted) { 2.times.map { |i| double(delete_from_index?: false, destroyed?: false) } }
77
- specify { import(deleted).should == [{index: deleted}] }
77
+ specify { expect(import(deleted)).to eq([{index: deleted}]) }
78
78
  end
79
79
  end
80
80
 
81
81
  context do
82
82
  let(:products) { 3.times.map { |i| double.tap { |product|
83
- product.stub(:is_a?).with(Product).and_return(true)
83
+ allow(product).to receive(:is_a?).with(Product).and_return(true)
84
84
  } } }
85
85
  let(:non_product) { double }
86
86
  subject { described_class.new(Product) }
87
87
 
88
- specify { import(products).should == [{index: products}] }
88
+ specify { expect(import(products)).to eq([{index: products}]) }
89
89
  specify { expect { import(products, non_product) {} }.to raise_error }
90
90
  end
91
91
 
92
92
  context 'error handling' do
93
- let(:products) { 3.times.map { |i| double.tap { |product| product.stub(rating: i.next) } } }
93
+ let(:products) { 3.times.map { |i| double.tap { |product| allow(product).to receive_messages(rating: i.next) } } }
94
94
  let(:deleted) { 2.times.map { |i| double(destroyed?: true, rating: i + 4) } }
95
95
  subject { described_class.new('product') }
96
96
 
@@ -98,13 +98,13 @@ describe Chewy::Type::Adapter::Object do
98
98
  ->(n, data) { (data[:index] || data[:delete]).first.rating != n }
99
99
  end
100
100
 
101
- specify { subject.import(products, deleted) { |data| true }.should eq(true) }
102
- specify { subject.import(products, deleted) { |data| false }.should eq(false) }
103
- specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[1]).should eq(false) }
104
- specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[2]).should eq(false) }
105
- specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[3]).should eq(false) }
106
- specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[4]).should eq(false) }
107
- specify { subject.import(products, deleted, batch_size: 1, &data_comparer.curry[5]).should eq(false) }
101
+ specify { expect(subject.import(products, deleted) { |data| true }).to eq(true) }
102
+ specify { expect(subject.import(products, deleted) { |data| false }).to eq(false) }
103
+ specify { expect(subject.import(products, deleted, batch_size: 1, &data_comparer.curry[1])).to eq(false) }
104
+ specify { expect(subject.import(products, deleted, batch_size: 1, &data_comparer.curry[2])).to eq(false) }
105
+ specify { expect(subject.import(products, deleted, batch_size: 1, &data_comparer.curry[3])).to eq(false) }
106
+ specify { expect(subject.import(products, deleted, batch_size: 1, &data_comparer.curry[4])).to eq(false) }
107
+ specify { expect(subject.import(products, deleted, batch_size: 1, &data_comparer.curry[5])).to eq(false) }
108
108
  end
109
109
  end
110
110
 
@@ -113,23 +113,23 @@ describe Chewy::Type::Adapter::Object do
113
113
  subject { described_class.new('product') }
114
114
  let(:objects) { 3.times.map { |i| double } }
115
115
 
116
- specify { subject.load(objects).should == objects }
116
+ specify { expect(subject.load(objects)).to eq(objects) }
117
117
  end
118
118
 
119
119
  context do
120
- before { Product.stub(:wrap) { |object| object.stub(wrapped?: true); object } }
120
+ before { allow(Product).to receive(:wrap) { |object| allow(object).to receive_messages(wrapped?: true); object } }
121
121
  subject { described_class.new(Product) }
122
122
  let(:objects) { 3.times.map { |i| double(wrapped?: false) } }
123
123
 
124
- specify { subject.load(objects).should satisfy { |objects| objects.all?(&:wrapped?) } }
124
+ specify { expect(subject.load(objects)).to satisfy { |objects| objects.all?(&:wrapped?) } }
125
125
  end
126
126
 
127
127
  context do
128
- before { Product.stub(:wrap) { |object| nil } }
128
+ before { allow(Product).to receive(:wrap) { |object| nil } }
129
129
  subject { described_class.new(Product) }
130
130
  let(:objects) { 3.times.map { |i| double(wrapped?: false) } }
131
131
 
132
- specify { subject.load(objects).should satisfy { |objects| objects.all?(&:nil?) } }
132
+ specify { expect(subject.load(objects)).to satisfy { |objects| objects.all?(&:nil?) } }
133
133
  end
134
134
  end
135
135
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Chewy::Type::Import do
4
- before { Chewy.client.indices.delete index: '*' }
4
+ before { Chewy.massacre }
5
5
 
6
6
  before do
7
7
  stub_model(:city)
@@ -15,23 +15,33 @@ describe Chewy::Type::Import do
15
15
  end
16
16
  end
17
17
 
18
- let!(:dummy_cities) { 3.times.map { |i| City.create(name: "name#{i}") } }
18
+ let!(:dummy_cities) { 3.times.map { |i| City.create(id: i + 1, name: "name#{i}") } }
19
19
  let(:city) { CitiesIndex::City }
20
20
 
21
- describe '.import' do
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) }
21
+ describe '.import', :orm do
22
+ specify { expect(city.import).to eq(true) }
23
+ specify { expect(city.import([])).to eq(true) }
24
+ specify { expect(city.import(dummy_cities)).to eq(true) }
25
+ specify { expect(city.import(dummy_cities.map(&:id))).to 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) }
29
29
  specify { expect { city.import dummy_cities }.to update_index(city).and_reindex(dummy_cities) }
30
30
  specify { expect { city.import dummy_cities.map(&:id) }.to update_index(city).and_reindex(dummy_cities) }
31
- specify { expect { city.import(City.where(name: ['name0', 'name1'])) }
32
- .to update_index(city).and_reindex(dummy_cities.first(2)) }
33
- specify { expect { city.import(City.where(name: ['name0', 'name1']).map(&:id)) }
34
- .to update_index(city).and_reindex(dummy_cities.first(2)) }
31
+
32
+ describe 'criteria-driven importing' do
33
+ let(:names) { %w(name0 name1) }
34
+
35
+ context 'mongoid', :mongoid do
36
+ specify { expect { city.import(City.where(:name.in => names)) }.to update_index(city).and_reindex(dummy_cities.first(2)) }
37
+ specify { expect { city.import(City.where(:name.in => names).map(&:id)) }.to update_index(city).and_reindex(dummy_cities.first(2)) }
38
+ end
39
+
40
+ context 'active record', :active_record do
41
+ specify { expect { city.import(City.where(name: names)) }.to update_index(city).and_reindex(dummy_cities.first(2)) }
42
+ specify { expect { city.import(City.where(name: names).map(&:id)) }.to update_index(city).and_reindex(dummy_cities.first(2)) }
43
+ end
44
+ end
35
45
 
36
46
  specify do
37
47
  dummy_cities.first.destroy
@@ -47,15 +57,16 @@ describe Chewy::Type::Import do
47
57
 
48
58
  specify do
49
59
  dummy_cities.first.destroy
60
+
50
61
  expect(CitiesIndex.client).to receive(:bulk).with(hash_including(
51
62
  body: [{delete: {_id: dummy_cities.first.id}}]
52
63
  ))
53
- dummy_cities.from(1).each.with_index do |c, i|
54
- expect(CitiesIndex.client).to receive(:bulk).with(hash_including(
55
- body: [{index: {_id: c.id, data: {'name' => "name#{i+1}"}}}]
56
- ))
57
- end
58
- city.import dummy_cities.map(&:id), batch_size: 1
64
+
65
+ expect(CitiesIndex.client).to receive(:bulk).with(hash_including(
66
+ body: [{index: {_id: 2, data: {'name' => "name1"}}}, {index: {_id: 3, data: {'name' => "name2"}}}]
67
+ ))
68
+
69
+ city.import dummy_cities.map(&:id), batch_size: 2
59
70
  end
60
71
 
61
72
  specify do
@@ -70,15 +81,34 @@ describe Chewy::Type::Import do
70
81
 
71
82
  context 'scoped' do
72
83
  before do
84
+ names = %w(name0 name1)
85
+
86
+ criteria = if defined?(::Mongoid)
87
+ { :name.in => names }
88
+ else
89
+ { name: names }
90
+ end
91
+
73
92
  stub_index(:cities) do
74
- define_type City.where(name: ['name0', 'name1']) do
93
+ define_type City.where(criteria) do
75
94
  field :name
76
95
  end
77
96
  end
78
97
  end
79
98
 
80
99
  specify { expect { city.import }.to update_index(city).and_reindex(dummy_cities.first(2)) }
81
- specify { expect { city.import City.where(id: dummy_cities.first.id) }.to update_index(city).and_reindex(dummy_cities.first).only }
100
+
101
+ context 'mongoid', :mongoid do
102
+ specify do
103
+ expect { city.import City.where(_id: dummy_cities.first.id) }.to update_index(city).and_reindex(dummy_cities.first).only
104
+ end
105
+ end
106
+
107
+ context 'active record', :active_record do
108
+ specify do
109
+ expect { city.import City.where(id: dummy_cities.first.id) }.to update_index(city).and_reindex(dummy_cities.first).only
110
+ end
111
+ end
82
112
  end
83
113
 
84
114
  context 'instrumentation payload' do
@@ -90,7 +120,7 @@ describe Chewy::Type::Import do
90
120
 
91
121
  dummy_cities.first.destroy
92
122
  city.import dummy_cities
93
- outer_payload.should == {type: CitiesIndex::City, import: {delete: 1, index: 2}}
123
+ expect(outer_payload).to eq({type: CitiesIndex::City, import: {delete: 1, index: 2}})
94
124
  end
95
125
 
96
126
  specify do
@@ -101,7 +131,7 @@ describe Chewy::Type::Import do
101
131
 
102
132
  dummy_cities.first.destroy
103
133
  city.import dummy_cities, batch_size: 1
104
- outer_payload.should == {type: CitiesIndex::City, import: {delete: 1, index: 2}}
134
+ expect(outer_payload).to eq({type: CitiesIndex::City, import: {delete: 1, index: 2}})
105
135
  end
106
136
 
107
137
  specify do
@@ -111,7 +141,7 @@ describe Chewy::Type::Import do
111
141
  end
112
142
 
113
143
  city.import dummy_cities, batch_size: 1
114
- outer_payload.should == {type: CitiesIndex::City, import: {index: 3}}
144
+ expect(outer_payload).to eq({type: CitiesIndex::City, import: {index: 3}})
115
145
  end
116
146
 
117
147
  context do
@@ -130,7 +160,7 @@ describe Chewy::Type::Import do
130
160
  end
131
161
 
132
162
  city.import dummy_cities, batch_size: 1
133
- outer_payload.should == {
163
+ expect(outer_payload).to eq({
134
164
  type: CitiesIndex::City,
135
165
  errors: {
136
166
  index: {
@@ -138,7 +168,7 @@ describe Chewy::Type::Import do
138
168
  }
139
169
  },
140
170
  import: {index: 3}
141
- }
171
+ })
142
172
  end
143
173
  end
144
174
  end
@@ -153,9 +183,9 @@ describe Chewy::Type::Import do
153
183
  end
154
184
  end
155
185
 
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) }
186
+ specify { expect(city.import(dummy_cities)).to eq(false) }
187
+ specify { expect(city.import(dummy_cities.map(&:id))).to eq(false) }
188
+ specify { expect(city.import(dummy_cities, batch_size: 1)).to eq(false) }
159
189
  end
160
190
 
161
191
  context do
@@ -167,15 +197,15 @@ describe Chewy::Type::Import do
167
197
  end
168
198
  end
169
199
 
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) }
200
+ specify { expect(city.import(dummy_cities)).to eq(false) }
201
+ specify { expect(city.import(dummy_cities.map(&:id))).to eq(false) }
202
+ specify { expect(city.import(dummy_cities, batch_size: 1)).to eq(false) }
173
203
  end
174
204
  end
175
205
 
176
- context 'parent-child relationship' do
177
- let(:country) { Country.create(name: 'country') }
178
- let(:another_country) { Country.create(name: 'another country') }
206
+ context 'parent-child relationship', :orm do
207
+ let(:country) { Country.create(id: 1, name: 'country') }
208
+ let(:another_country) { Country.create(id: 2, name: 'another country') }
179
209
 
180
210
  before do
181
211
  stub_model(:country)
@@ -198,10 +228,10 @@ describe Chewy::Type::Import do
198
228
 
199
229
  before { CountriesIndex::Country.import(country) }
200
230
 
201
- let(:child_city) { City.create(country_id: country.id, name: 'city') }
231
+ let(:child_city) { City.create(id: 4, country_id: country.id, name: 'city') }
202
232
  let(:city) { CountriesIndex::City }
203
233
 
204
- specify { city.import(child_city).should eq(true) }
234
+ specify { expect(city.import(child_city)).to eq(true) }
205
235
  specify { expect { city.import child_city }.to update_index(city).and_reindex(child_city) }
206
236
 
207
237
  specify do
@@ -251,8 +281,8 @@ describe Chewy::Type::Import do
251
281
  end
252
282
  end
253
283
 
254
- describe '.import!' do
255
- specify { expect { city.import!.should }.not_to raise_error }
284
+ describe '.import!', :orm do
285
+ specify { expect { city.import! }.not_to raise_error }
256
286
 
257
287
  context do
258
288
  before do