chewy 0.8.4 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +34 -0
  3. data/.rubocop_todo.yml +44 -0
  4. data/.travis.yml +20 -60
  5. data/Appraisals +15 -40
  6. data/CHANGELOG.md +42 -0
  7. data/Gemfile +1 -0
  8. data/Guardfile +5 -5
  9. data/README.md +155 -6
  10. data/Rakefile +11 -1
  11. data/chewy.gemspec +5 -7
  12. data/gemfiles/rails.3.2.activerecord.gemfile +1 -0
  13. data/gemfiles/rails.3.2.activerecord.kaminari.gemfile +1 -0
  14. data/gemfiles/rails.3.2.activerecord.will_paginate.gemfile +1 -0
  15. data/gemfiles/rails.4.2.activerecord.gemfile +1 -0
  16. data/gemfiles/rails.4.2.activerecord.kaminari.gemfile +1 -0
  17. data/gemfiles/rails.4.2.activerecord.will_paginate.gemfile +1 -0
  18. data/gemfiles/{rails.4.2.mongoid.4.0.0.gemfile → rails.4.2.mongoid.4.0.gemfile} +2 -1
  19. data/gemfiles/{rails.4.2.mongoid.4.0.0.kaminari.gemfile → rails.4.2.mongoid.4.0.kaminari.gemfile} +2 -1
  20. data/gemfiles/{rails.4.2.mongoid.4.0.0.will_paginate.gemfile → rails.4.2.mongoid.4.0.will_paginate.gemfile} +2 -1
  21. data/gemfiles/{rails.4.2.mongoid.5.1.0.gemfile → rails.4.2.mongoid.5.1.gemfile} +2 -1
  22. data/gemfiles/{rails.4.2.mongoid.5.1.0.kaminari.gemfile → rails.4.2.mongoid.5.1.kaminari.gemfile} +2 -1
  23. data/gemfiles/{rails.4.2.mongoid.5.1.0.will_paginate.gemfile → rails.4.2.mongoid.5.1.will_paginate.gemfile} +2 -1
  24. data/gemfiles/{rails.4.0.activerecord.gemfile → rails.5.0.activerecord.gemfile} +4 -2
  25. data/gemfiles/{rails.4.0.mongoid.4.0.0.kaminari.gemfile → rails.5.0.activerecord.kaminari.gemfile} +4 -2
  26. data/gemfiles/{rails.4.0.mongoid.4.0.0.will_paginate.gemfile → rails.5.0.activerecord.will_paginate.gemfile} +4 -2
  27. data/gemfiles/{sequel.4.31.gemfile → sequel.4.38.gemfile} +3 -2
  28. data/lib/chewy.rb +24 -16
  29. data/lib/chewy/backports/deep_dup.rb +1 -1
  30. data/lib/chewy/backports/duplicable.rb +1 -0
  31. data/lib/chewy/config.rb +13 -7
  32. data/lib/chewy/errors.rb +4 -4
  33. data/lib/chewy/fields/base.rb +19 -14
  34. data/lib/chewy/fields/root.rb +11 -9
  35. data/lib/chewy/index.rb +38 -25
  36. data/lib/chewy/index/actions.rb +17 -17
  37. data/lib/chewy/index/settings.rb +3 -4
  38. data/lib/chewy/journal.rb +107 -0
  39. data/lib/chewy/journal/apply.rb +31 -0
  40. data/lib/chewy/journal/clean.rb +24 -0
  41. data/lib/chewy/journal/entry.rb +83 -0
  42. data/lib/chewy/journal/query.rb +87 -0
  43. data/lib/chewy/log_subscriber.rb +8 -8
  44. data/lib/chewy/minitest.rb +1 -0
  45. data/lib/chewy/minitest/helpers.rb +77 -0
  46. data/lib/chewy/minitest/search_index_receiver.rb +80 -0
  47. data/lib/chewy/query.rb +116 -60
  48. data/lib/chewy/query/compose.rb +5 -6
  49. data/lib/chewy/query/criteria.rb +26 -16
  50. data/lib/chewy/query/filters.rb +9 -9
  51. data/lib/chewy/query/loading.rb +2 -2
  52. data/lib/chewy/query/nodes/and.rb +3 -3
  53. data/lib/chewy/query/nodes/base.rb +1 -1
  54. data/lib/chewy/query/nodes/bool.rb +6 -4
  55. data/lib/chewy/query/nodes/equal.rb +6 -6
  56. data/lib/chewy/query/nodes/exists.rb +2 -2
  57. data/lib/chewy/query/nodes/expr.rb +2 -2
  58. data/lib/chewy/query/nodes/field.rb +35 -31
  59. data/lib/chewy/query/nodes/has_child.rb +1 -0
  60. data/lib/chewy/query/nodes/has_parent.rb +1 -0
  61. data/lib/chewy/query/nodes/has_relation.rb +11 -13
  62. data/lib/chewy/query/nodes/match_all.rb +1 -1
  63. data/lib/chewy/query/nodes/missing.rb +2 -2
  64. data/lib/chewy/query/nodes/not.rb +3 -3
  65. data/lib/chewy/query/nodes/or.rb +3 -3
  66. data/lib/chewy/query/nodes/prefix.rb +4 -3
  67. data/lib/chewy/query/nodes/query.rb +3 -3
  68. data/lib/chewy/query/nodes/range.rb +11 -11
  69. data/lib/chewy/query/nodes/raw.rb +1 -1
  70. data/lib/chewy/query/nodes/regexp.rb +15 -11
  71. data/lib/chewy/query/nodes/script.rb +6 -6
  72. data/lib/chewy/query/pagination/will_paginate.rb +2 -2
  73. data/lib/chewy/railtie.rb +3 -3
  74. data/lib/chewy/rake_helper.rb +51 -30
  75. data/lib/chewy/repository.rb +2 -2
  76. data/lib/chewy/rspec.rb +1 -1
  77. data/lib/chewy/rspec/update_index.rb +46 -47
  78. data/lib/chewy/runtime/version.rb +4 -4
  79. data/lib/chewy/search.rb +7 -5
  80. data/lib/chewy/strategy.rb +10 -8
  81. data/lib/chewy/strategy/atomic.rb +2 -2
  82. data/lib/chewy/strategy/base.rb +4 -4
  83. data/lib/chewy/strategy/bypass.rb +1 -2
  84. data/lib/chewy/strategy/sidekiq.rb +2 -0
  85. data/lib/chewy/strategy/urgent.rb +1 -1
  86. data/lib/chewy/type.rb +51 -45
  87. data/lib/chewy/type/adapter/active_record.rb +23 -12
  88. data/lib/chewy/type/adapter/base.rb +4 -4
  89. data/lib/chewy/type/adapter/mongoid.rb +6 -6
  90. data/lib/chewy/type/adapter/object.rb +15 -12
  91. data/lib/chewy/type/adapter/orm.rb +24 -15
  92. data/lib/chewy/type/adapter/sequel.rb +11 -7
  93. data/lib/chewy/type/crutch.rb +4 -3
  94. data/lib/chewy/type/import.rb +51 -32
  95. data/lib/chewy/type/mapping.rb +17 -17
  96. data/lib/chewy/type/observe.rb +9 -7
  97. data/lib/chewy/type/witchcraft.rb +62 -23
  98. data/lib/chewy/type/wrapper.rb +20 -14
  99. data/lib/chewy/version.rb +1 -1
  100. data/lib/generators/chewy/install_generator.rb +3 -3
  101. data/lib/tasks/chewy.rake +28 -23
  102. data/spec/chewy/config_spec.rb +33 -12
  103. data/spec/chewy/fields/base_spec.rb +143 -154
  104. data/spec/chewy/fields/root_spec.rb +22 -20
  105. data/spec/chewy/fields/time_fields_spec.rb +11 -9
  106. data/spec/chewy/index/actions_spec.rb +27 -4
  107. data/spec/chewy/index/aliases_spec.rb +2 -2
  108. data/spec/chewy/index/settings_spec.rb +72 -50
  109. data/spec/chewy/index_spec.rb +95 -43
  110. data/spec/chewy/journal/apply_spec.rb +120 -0
  111. data/spec/chewy/journal/entry_spec.rb +237 -0
  112. data/spec/chewy/journal_spec.rb +173 -0
  113. data/spec/chewy/minitest/helpers_spec.rb +90 -0
  114. data/spec/chewy/minitest/search_index_receiver_spec.rb +120 -0
  115. data/spec/chewy/query/criteria_spec.rb +504 -237
  116. data/spec/chewy/query/filters_spec.rb +94 -66
  117. data/spec/chewy/query/loading_spec.rb +76 -40
  118. data/spec/chewy/query/nodes/and_spec.rb +3 -7
  119. data/spec/chewy/query/nodes/bool_spec.rb +5 -13
  120. data/spec/chewy/query/nodes/equal_spec.rb +20 -20
  121. data/spec/chewy/query/nodes/exists_spec.rb +7 -7
  122. data/spec/chewy/query/nodes/has_child_spec.rb +42 -23
  123. data/spec/chewy/query/nodes/has_parent_spec.rb +42 -23
  124. data/spec/chewy/query/nodes/match_all_spec.rb +2 -2
  125. data/spec/chewy/query/nodes/missing_spec.rb +6 -5
  126. data/spec/chewy/query/nodes/not_spec.rb +3 -7
  127. data/spec/chewy/query/nodes/or_spec.rb +3 -7
  128. data/spec/chewy/query/nodes/prefix_spec.rb +6 -6
  129. data/spec/chewy/query/nodes/query_spec.rb +3 -3
  130. data/spec/chewy/query/nodes/range_spec.rb +19 -19
  131. data/spec/chewy/query/nodes/raw_spec.rb +2 -2
  132. data/spec/chewy/query/nodes/regexp_spec.rb +31 -19
  133. data/spec/chewy/query/nodes/script_spec.rb +5 -5
  134. data/spec/chewy/query/pagination/kaminari_spec.rb +2 -2
  135. data/spec/chewy/query/pagination/will_paginage_spec.rb +6 -7
  136. data/spec/chewy/query/pagination_spec.rb +2 -3
  137. data/spec/chewy/query_spec.rb +208 -145
  138. data/spec/chewy/repository_spec.rb +8 -8
  139. data/spec/chewy/rspec/update_index_spec.rb +180 -111
  140. data/spec/chewy/search_spec.rb +8 -8
  141. data/spec/chewy/strategy/active_job_spec.rb +2 -2
  142. data/spec/chewy/strategy/atomic_spec.rb +4 -1
  143. data/spec/chewy/strategy/resque_spec.rb +2 -2
  144. data/spec/chewy/strategy/sidekiq_spec.rb +2 -2
  145. data/spec/chewy/type/actions_spec.rb +1 -1
  146. data/spec/chewy/type/adapter/active_record_spec.rb +255 -149
  147. data/spec/chewy/type/adapter/mongoid_spec.rb +169 -108
  148. data/spec/chewy/type/adapter/object_spec.rb +56 -40
  149. data/spec/chewy/type/adapter/sequel_spec.rb +248 -163
  150. data/spec/chewy/type/import_spec.rb +78 -47
  151. data/spec/chewy/type/mapping_spec.rb +6 -6
  152. data/spec/chewy/type/observe_spec.rb +20 -14
  153. data/spec/chewy/type/witchcraft_spec.rb +89 -43
  154. data/spec/chewy/type_spec.rb +4 -3
  155. data/spec/chewy_spec.rb +10 -8
  156. data/spec/spec_helper.rb +3 -0
  157. data/spec/support/active_record.rb +1 -1
  158. data/spec/support/class_helpers.rb +10 -11
  159. data/spec/support/mongoid.rb +2 -2
  160. data/spec/support/sequel.rb +1 -1
  161. metadata +65 -35
  162. data/gemfiles/rails.4.0.activerecord.kaminari.gemfile +0 -14
  163. data/gemfiles/rails.4.0.activerecord.will_paginate.gemfile +0 -14
  164. data/gemfiles/rails.4.0.mongoid.4.0.0.gemfile +0 -15
  165. data/gemfiles/rails.4.0.mongoid.5.1.0.gemfile +0 -15
  166. data/gemfiles/rails.4.0.mongoid.5.1.0.kaminari.gemfile +0 -14
  167. data/gemfiles/rails.4.0.mongoid.5.1.0.will_paginate.gemfile +0 -14
  168. data/gemfiles/rails.4.1.activerecord.gemfile +0 -15
  169. data/gemfiles/rails.4.1.activerecord.kaminari.gemfile +0 -14
  170. data/gemfiles/rails.4.1.activerecord.will_paginate.gemfile +0 -14
  171. data/gemfiles/rails.4.1.mongoid.4.0.0.gemfile +0 -15
  172. data/gemfiles/rails.4.1.mongoid.4.0.0.kaminari.gemfile +0 -14
  173. data/gemfiles/rails.4.1.mongoid.4.0.0.will_paginate.gemfile +0 -14
  174. data/gemfiles/rails.4.1.mongoid.5.1.0.gemfile +0 -15
  175. data/gemfiles/rails.4.1.mongoid.5.1.0.kaminari.gemfile +0 -14
  176. data/gemfiles/rails.4.1.mongoid.5.1.0.will_paginate.gemfile +0 -14
  177. data/gemfiles/rails.5.0.0.beta3.activerecord.gemfile +0 -16
  178. data/gemfiles/rails.5.0.0.beta3.activerecord.kaminari.gemfile +0 -16
  179. data/gemfiles/rails.5.0.0.beta3.activerecord.will_paginate.gemfile +0 -15
@@ -51,7 +51,10 @@ describe Chewy::Strategy::Atomic, :orm do
51
51
  end
52
52
 
53
53
  specify do
54
- expect { country.save!; other_country.destroy }
54
+ expect do
55
+ country.save!
56
+ other_country.destroy
57
+ end
55
58
  .to update_index(CountriesIndex::Country, strategy: :atomic)
56
59
  .and_reindex('HL').and_delete('WD').only
57
60
  end
@@ -33,8 +33,8 @@ if defined?(::Resque)
33
33
  end
34
34
 
35
35
  specify do
36
- expect(CitiesIndex::City).to receive(:import!).with([city.id, other_city.id], {suffix: '201601'})
37
- Chewy::Strategy::Resque::Worker.perform("CitiesIndex::City", [city.id, other_city.id], suffix: '201601')
36
+ expect(CitiesIndex::City).to receive(:import!).with([city.id, other_city.id], suffix: '201601')
37
+ Chewy::Strategy::Resque::Worker.perform('CitiesIndex::City', [city.id, other_city.id], suffix: '201601')
38
38
  end
39
39
  end
40
40
  end
@@ -33,8 +33,8 @@ if defined?(::Sidekiq)
33
33
  end
34
34
 
35
35
  specify do
36
- expect(CitiesIndex::City).to receive(:import!).with([city.id, other_city.id], {suffix: '201601'})
37
- Chewy::Strategy::Sidekiq::Worker.new.perform("CitiesIndex::City", [city.id, other_city.id], suffix: '201601')
36
+ expect(CitiesIndex::City).to receive(:import!).with([city.id, other_city.id], suffix: '201601')
37
+ Chewy::Strategy::Sidekiq::Worker.new.perform('CitiesIndex::City', [city.id, other_city.id], suffix: '201601')
38
38
  end
39
39
  end
40
40
  end
@@ -15,7 +15,7 @@ describe Chewy::Type::Actions, :orm 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) { Array.new(3) { |i| City.create(name: "name#{i}") } }
19
19
  let(:city) { CitiesIndex::City }
20
20
 
21
21
  before do
@@ -41,7 +41,7 @@ describe Chewy::Type::Adapter::ActiveRecord, :active_record do
41
41
  subject { described_class.new(City) }
42
42
 
43
43
  context do
44
- let!(:cities) { 3.times.map { City.create! } }
44
+ let!(:cities) { Array.new(3) { City.create! } }
45
45
 
46
46
  specify { expect(subject.identify(City.where(nil))).to match_array(cities.map(&:id)) }
47
47
  specify { expect(subject.identify(cities)).to eq(cities.map(&:id)) }
@@ -51,7 +51,7 @@ describe Chewy::Type::Adapter::ActiveRecord, :active_record do
51
51
 
52
52
  context 'custom primary_key' do
53
53
  before { stub_model(:city) { self.primary_key = 'rating' } }
54
- let!(:cities) { 3.times.map { |i| City.create! { |c| c.rating = i } } }
54
+ let!(:cities) { Array.new(3) { |i| City.create! { |c| c.rating = i } } }
55
55
 
56
56
  specify { expect(subject.identify(City.where(nil))).to match_array([0, 1, 2]) }
57
57
  specify { expect(subject.identify(cities)).to eq([0, 1, 2]) }
@@ -68,46 +68,83 @@ describe Chewy::Type::Adapter::ActiveRecord, :active_record do
68
68
  end
69
69
 
70
70
  context do
71
- let!(:cities) { 3.times.map { City.create! } }
72
- let!(:deleted) { 4.times.map { City.create!.tap(&:destroy) } }
71
+ let!(:cities) { Array.new(3) { City.create! } }
72
+ let!(:deleted) { Array.new(4) { City.create!.tap(&:destroy) } }
73
73
  subject { described_class.new(City) }
74
74
 
75
- specify { expect(import).to eq([{index: cities}]) }
76
- specify { expect(import nil).to eq([]) }
77
-
78
- specify { expect(import(City.order(:id))).to eq([{index: cities}]) }
79
- specify { expect(import(City.order(:id), batch_size: 2))
80
- .to eq([{index: cities.first(2)}, {index: cities.last(1)}]) }
81
-
82
- specify { expect(import(cities)).to eq([{index: cities}]) }
83
- specify { expect(import(cities, batch_size: 2))
84
- .to eq([{index: cities.first(2)}, {index: cities.last(1)}]) }
85
- specify { expect(import(cities, deleted))
86
- .to eq([{index: cities}, {delete: deleted}]) }
87
- specify { expect(import(cities, deleted, batch_size: 2)).to eq([
88
- {index: cities.first(2)},
89
- {index: cities.last(1)},
90
- {delete: deleted.first(2)},
91
- {delete: deleted.last(2)}]) }
92
-
93
- specify { expect(import(cities.map(&:id))).to eq([{index: cities}]) }
94
- specify { expect(import(deleted.map(&:id))).to eq([{delete: deleted.map(&:id)}]) }
95
- specify { expect(import(cities.map(&:id), batch_size: 2))
96
- .to eq([{index: cities.first(2)}, {index: cities.last(1)}]) }
97
- specify { expect(import(cities.map(&:id), deleted.map(&:id)))
98
- .to eq([{index: cities}, {delete: deleted.map(&:id)}]) }
99
- specify { expect(import(cities.map(&:id), deleted.map(&:id), batch_size: 2)).to eq([
100
- {index: cities.first(2)},
101
- {index: cities.last(1)},
102
- {delete: deleted.first(2).map(&:id)},
103
- {delete: deleted.last(2).map(&:id)}]) }
104
-
105
- specify { expect(import(cities.first, nil)).to eq([{index: [cities.first]}]) }
106
- specify { expect(import(cities.first.id, nil)).to eq([{index: [cities.first]}]) }
75
+ specify { expect(import).to eq([{ index: cities }]) }
76
+ specify { expect(import(nil)).to eq([]) }
77
+
78
+ specify { expect(import(City.order(:id))).to eq([{ index: cities }]) }
79
+ specify do
80
+ expect(import(City.order(:id), batch_size: 2))
81
+ .to eq([{ index: cities.first(2) }, { index: cities.last(1) }])
82
+ end
83
+
84
+ specify { expect(import(cities)).to eq([{ index: cities }]) }
85
+ specify do
86
+ expect(import(cities, batch_size: 2))
87
+ .to eq([{ index: cities.first(2) }, { index: cities.last(1) }])
88
+ end
89
+ specify do
90
+ expect(import(cities, deleted))
91
+ .to eq([{ index: cities }, { delete: deleted }])
92
+ end
93
+ specify do
94
+ expect(import(cities, deleted, batch_size: 2)).to eq([
95
+ { index: cities.first(2) },
96
+ { index: cities.last(1) },
97
+ { delete: deleted.first(2) },
98
+ { delete: deleted.last(2) }
99
+ ])
100
+ end
101
+
102
+ specify { expect(import(cities.map(&:id))).to eq([{ index: cities }]) }
103
+ specify { expect(import(deleted.map(&:id))).to eq([{ delete: deleted.map(&:id) }]) }
104
+ specify do
105
+ expect(import(cities.map(&:id), batch_size: 2))
106
+ .to eq([{ index: cities.first(2) }, { index: cities.last(1) }])
107
+ end
108
+ specify do
109
+ expect(import(cities.map(&:id), deleted.map(&:id)))
110
+ .to eq([{ index: cities }, { delete: deleted.map(&:id) }])
111
+ end
112
+ specify do
113
+ expect(import(cities.map(&:id), deleted.map(&:id), batch_size: 2)).to eq([
114
+ { index: cities.first(2) },
115
+ { index: cities.last(1) },
116
+ { delete: deleted.first(2).map(&:id) },
117
+ { delete: deleted.last(2).map(&:id) }
118
+ ])
119
+ end
120
+
121
+ specify { expect(import(cities.first, nil)).to eq([{ index: [cities.first] }]) }
122
+ specify { expect(import(cities.first.id, nil)).to eq([{ index: [cities.first] }]) }
123
+
124
+ context 'raw_import' do
125
+ let(:probe) { double }
126
+ let(:converter) { ->(raw_hash) { probe.call(raw_hash) } }
127
+ let(:moscow) { OpenStruct.new(id: 1, name: 'Moscow') }
128
+ let(:warsaw) { OpenStruct.new(id: 2, name: 'Warsaw') }
129
+ let(:madrid) { OpenStruct.new(id: 3, name: 'Madrid') }
130
+ before do
131
+ @one, @two, @three = City.all.to_a
132
+ end
133
+
134
+ it 'uses the raw import converter to make objects out of raw hashes from the database' do
135
+ expect(City).not_to receive(:new)
136
+
137
+ expect(probe).to receive(:call).with(a_hash_including('id' => @one.id, 'name' => @one.name)).and_return(moscow)
138
+ expect(probe).to receive(:call).with(a_hash_including('id' => @two.id, 'name' => @one.name)).and_return(warsaw)
139
+ expect(probe).to receive(:call).with(a_hash_including('id' => @three.id, 'name' => @three.name)).and_return(madrid)
140
+
141
+ expect(import(City.where(nil), raw_import: converter)).to eq([{ index: [moscow, warsaw, madrid] }])
142
+ end
143
+ end
107
144
  end
108
145
 
109
- context 'additional delete conitions' do
110
- let!(:cities) { 4.times.map { |i| City.create! rating: i } }
146
+ context 'additional delete conditions' do
147
+ let!(:cities) { Array.new(4) { |i| City.create! rating: i } }
111
148
  before { cities.last(2).map(&:destroy) }
112
149
  subject { described_class.new(City) }
113
150
 
@@ -118,111 +155,164 @@ describe Chewy::Type::Adapter::ActiveRecord, :active_record do
118
155
  end
119
156
  end
120
157
  end
121
- subject { described_class.new(City, delete_if: ->{ delete_already? }) }
122
-
123
- specify { expect(import(City.where(nil))).to eq([
124
- { index: [cities[0]], delete: [cities[1]] }
125
- ]) }
126
- specify { expect(import(cities)).to eq([
127
- { index: [cities[0]], delete: [cities[1]] },
128
- { delete: cities.last(2) }
129
- ]) }
130
- specify { expect(import(cities.map(&:id))).to eq([
131
- { index: [cities[0]], delete: [cities[1]] },
132
- { delete: cities.last(2).map(&:id) }
133
- ]) }
158
+ subject { described_class.new(City, delete_if: -> { delete_already? }) }
159
+
160
+ specify do
161
+ expect(import(City.where(nil))).to eq([
162
+ { index: [cities[0]], delete: [cities[1]] }
163
+ ])
164
+ end
165
+ specify do
166
+ expect(import(cities)).to eq([
167
+ { index: [cities[0]], delete: [cities[1]] },
168
+ { delete: cities.last(2) }
169
+ ])
170
+ end
171
+ specify do
172
+ expect(import(cities.map(&:id))).to eq([
173
+ { index: [cities[0]], delete: [cities[1]] },
174
+ { delete: cities.last(2).map(&:id) }
175
+ ])
176
+ end
134
177
  end
135
178
 
136
179
  context 'custom primary_key' do
137
180
  before { stub_model(:city) { self.primary_key = 'rating' } }
138
- let!(:cities) { 3.times.map { |i| City.create! { |c| c.rating = i + 7 } } }
139
- let!(:deleted) { 3.times.map { |i| City.create! { |c| c.rating = i + 10 }.tap(&:destroy) } }
181
+ let!(:cities) { Array.new(3) { |i| City.create! { |c| c.rating = i + 7 } } }
182
+ let!(:deleted) { Array.new(3) { |i| City.create! { |c| c.rating = i + 10 }.tap(&:destroy) } }
140
183
  subject { described_class.new(City) }
141
184
 
142
- specify { expect(import).to eq([{index: cities}]) }
143
-
144
- specify { expect(import(City.order(:rating))).to eq([{index: cities}]) }
145
- specify { expect(import(City.order(:rating), batch_size: 2))
146
- .to eq([{index: cities.first(2)}, {index: cities.last(1)}]) }
147
-
148
- specify { expect(import(cities)).to eq([{index: cities}]) }
149
- specify { expect(import(cities, batch_size: 2))
150
- .to eq([{index: cities.first(2)}, {index: cities.last(1)}]) }
151
- specify { expect(import(cities, deleted))
152
- .to eq([{index: cities}, {delete: deleted}]) }
153
- specify { expect(import(cities, deleted, batch_size: 2)).to eq([
154
- {index: cities.first(2)},
155
- {index: cities.last(1)},
156
- {delete: deleted.first(2)},
157
- {delete: deleted.last(1)}]) }
158
-
159
- specify { expect(import(cities.map(&:id))).to eq([{index: cities}]) }
160
- specify { expect(import(cities.map(&:id), batch_size: 2))
161
- .to eq([{index: cities.first(2)}, {index: cities.last(1)}]) }
162
- specify { expect(import(cities.map(&:id), deleted.map(&:id)))
163
- .to eq([{index: cities}, {delete: deleted.map(&:id)}]) }
164
- specify { expect(import(cities.map(&:id), deleted.map(&:id), batch_size: 2)).to eq([
165
- {index: cities.first(2)},
166
- {index: cities.last(1)},
167
- {delete: deleted.first(2).map(&:id)},
168
- {delete: deleted.last(1).map(&:id)}]) }
185
+ specify { expect(import).to eq([{ index: cities }]) }
186
+
187
+ specify { expect(import(City.order(:rating))).to eq([{ index: cities }]) }
188
+ specify do
189
+ expect(import(City.order(:rating), batch_size: 2))
190
+ .to eq([{ index: cities.first(2) }, { index: cities.last(1) }])
191
+ end
192
+
193
+ specify { expect(import(cities)).to eq([{ index: cities }]) }
194
+ specify do
195
+ expect(import(cities, batch_size: 2))
196
+ .to eq([{ index: cities.first(2) }, { index: cities.last(1) }])
197
+ end
198
+ specify do
199
+ expect(import(cities, deleted))
200
+ .to eq([{ index: cities }, { delete: deleted }])
201
+ end
202
+ specify do
203
+ expect(import(cities, deleted, batch_size: 2)).to eq([
204
+ { index: cities.first(2) },
205
+ { index: cities.last(1) },
206
+ { delete: deleted.first(2) },
207
+ { delete: deleted.last(1) }
208
+ ])
209
+ end
210
+
211
+ specify { expect(import(cities.map(&:id))).to eq([{ index: cities }]) }
212
+ specify do
213
+ expect(import(cities.map(&:id), batch_size: 2))
214
+ .to eq([{ index: cities.first(2) }, { index: cities.last(1) }])
215
+ end
216
+ specify do
217
+ expect(import(cities.map(&:id), deleted.map(&:id)))
218
+ .to eq([{ index: cities }, { delete: deleted.map(&:id) }])
219
+ end
220
+ specify do
221
+ expect(import(cities.map(&:id), deleted.map(&:id), batch_size: 2)).to eq([
222
+ { index: cities.first(2) },
223
+ { index: cities.last(1) },
224
+ { delete: deleted.first(2).map(&:id) },
225
+ { delete: deleted.last(1).map(&:id) }
226
+ ])
227
+ end
169
228
  end
170
229
 
171
230
  context 'default scope' do
172
- let!(:cities) { 4.times.map { |i| City.create!(rating: i/3) } }
173
- let!(:deleted) { 3.times.map { |i| City.create!.tap(&:destroy) } }
231
+ let!(:cities) { Array.new(4) { |i| City.create!(rating: i / 3) } }
232
+ let!(:deleted) { Array.new(3) { City.create!.tap(&:destroy) } }
174
233
  subject { described_class.new(City.where(rating: 0)) }
175
234
 
176
- specify { expect(import).to eq([{index: cities.first(3)}]) }
235
+ specify { expect(import).to eq([{ index: cities.first(3) }]) }
177
236
 
178
- specify { expect(import(City.where('rating < 2')))
179
- .to eq([{index: cities.first(3)}]) }
180
- specify { expect(import(City.where('rating < 2'), batch_size: 2))
181
- .to eq([{index: cities.first(2)}, {index: [cities[2]]}]) }
182
- specify { expect(import(City.where('rating < 1')))
183
- .to eq([{index: cities.first(3)}]) }
237
+ specify do
238
+ expect(import(City.where('rating < 2')))
239
+ .to eq([{ index: cities.first(3) }])
240
+ end
241
+ specify do
242
+ expect(import(City.where('rating < 2'), batch_size: 2))
243
+ .to eq([{ index: cities.first(2) }, { index: [cities[2]] }])
244
+ end
245
+ specify do
246
+ expect(import(City.where('rating < 1')))
247
+ .to eq([{ index: cities.first(3) }])
248
+ end
184
249
  specify { expect(import(City.where('rating > 1'))).to eq([]) }
185
250
 
186
- specify { expect(import(cities.first(2)))
187
- .to eq([{index: cities.first(2)}]) }
188
- specify { expect(import(cities))
189
- .to eq([{index: cities.first(3)}, {delete: cities.last(1)}]) }
190
- specify { expect(import(cities, batch_size: 2))
191
- .to eq([{index: cities.first(2)}, {index: [cities[2]]}, {delete: cities.last(1)}]) }
192
- specify { expect(import(cities, deleted))
193
- .to eq([{index: cities.first(3)}, {delete: cities.last(1) + deleted}]) }
194
- specify { expect(import(cities, deleted, batch_size: 3)).to eq([
195
- {index: cities.first(3)},
196
- {delete: cities.last(1) + deleted.first(2)},
197
- {delete: deleted.last(1)}]) }
198
-
199
- specify { expect(import(cities.first(2).map(&:id)))
200
- .to eq([{index: cities.first(2)}]) }
201
- specify { expect(import(cities.map(&:id)))
202
- .to eq([{index: cities.first(3)}, {delete: [cities.last.id]}]) }
203
- specify { expect(import(cities.map(&:id), batch_size: 2))
204
- .to eq([{index: cities.first(2)}, {index: [cities[2]]}, {delete: [cities.last.id]}]) }
205
- specify { expect(import(cities.map(&:id), deleted.map(&:id)))
206
- .to eq([{index: cities.first(3)}, {delete: [cities.last.id] + deleted.map(&:id)}]) }
207
- specify { expect(import(cities.map(&:id), deleted.map(&:id), batch_size: 3)).to eq([
208
- {index: cities.first(3)},
209
- {delete: [cities.last.id] + deleted.first(2).map(&:id)},
210
- {delete: deleted.last(1).map(&:id)}]) }
251
+ specify do
252
+ expect(import(cities.first(2)))
253
+ .to eq([{ index: cities.first(2) }])
254
+ end
255
+ specify do
256
+ expect(import(cities))
257
+ .to eq([{ index: cities.first(3) }, { delete: cities.last(1) }])
258
+ end
259
+ specify do
260
+ expect(import(cities, batch_size: 2))
261
+ .to eq([{ index: cities.first(2) }, { index: [cities[2]] }, { delete: cities.last(1) }])
262
+ end
263
+ specify do
264
+ expect(import(cities, deleted))
265
+ .to eq([{ index: cities.first(3) }, { delete: cities.last(1) + deleted }])
266
+ end
267
+ specify do
268
+ expect(import(cities, deleted, batch_size: 3)).to eq([
269
+ { index: cities.first(3) },
270
+ { delete: cities.last(1) + deleted.first(2) },
271
+ { delete: deleted.last(1) }
272
+ ])
273
+ end
274
+
275
+ specify do
276
+ expect(import(cities.first(2).map(&:id)))
277
+ .to eq([{ index: cities.first(2) }])
278
+ end
279
+ specify do
280
+ expect(import(cities.map(&:id)))
281
+ .to eq([{ index: cities.first(3) }, { delete: [cities.last.id] }])
282
+ end
283
+ specify do
284
+ expect(import(cities.map(&:id), batch_size: 2))
285
+ .to eq([{ index: cities.first(2) }, { index: [cities[2]] }, { delete: [cities.last.id] }])
286
+ end
287
+ specify do
288
+ expect(import(cities.map(&:id), deleted.map(&:id)))
289
+ .to eq([{ index: cities.first(3) }, { delete: [cities.last.id] + deleted.map(&:id) }])
290
+ end
291
+ specify do
292
+ expect(import(cities.map(&:id), deleted.map(&:id), batch_size: 3)).to eq([
293
+ { index: cities.first(3) },
294
+ { delete: [cities.last.id] + deleted.first(2).map(&:id) },
295
+ { delete: deleted.last(1).map(&:id) }
296
+ ])
297
+ end
211
298
  end
212
299
 
213
300
  context 'error handling' do
214
- let!(:cities) { 3.times.map { |i| City.create! } }
215
- let!(:deleted) { 2.times.map { |i| City.create!.tap(&:destroy) } }
301
+ let!(:cities) { Array.new(3) { City.create! } }
302
+ let!(:deleted) { Array.new(2) { City.create!.tap(&:destroy) } }
216
303
  let(:ids) { (cities + deleted).map(&:id) }
217
304
  subject { described_class.new(City) }
218
305
 
219
306
  let(:data_comparer) do
220
- ->(id, data) { objects = data[:index] || data[:delete]; !objects.map { |o| o.respond_to?(:id) ? o.id : o }.include?(id) }
307
+ lambda do |id, data|
308
+ objects = data[:index] || data[:delete]
309
+ !objects.map { |o| o.respond_to?(:id) ? o.id : o }.include?(id)
310
+ end
221
311
  end
222
312
 
223
313
  context 'implicit scope' do
224
- specify { expect(subject.import { |data| true }).to eq(true) }
225
- specify { expect(subject.import { |data| false }).to eq(false) }
314
+ specify { expect(subject.import { |_data| true }).to eq(true) }
315
+ specify { expect(subject.import { |_data| false }).to eq(false) }
226
316
  specify { expect(subject.import(batch_size: 1, &data_comparer.curry[cities[0].id])).to eq(false) }
227
317
  specify { expect(subject.import(batch_size: 1, &data_comparer.curry[cities[1].id])).to eq(false) }
228
318
  specify { expect(subject.import(batch_size: 1, &data_comparer.curry[cities[2].id])).to eq(false) }
@@ -233,8 +323,8 @@ describe Chewy::Type::Adapter::ActiveRecord, :active_record do
233
323
  context 'explicit scope' do
234
324
  let(:scope) { City.where(id: ids) }
235
325
 
236
- specify { expect(subject.import(scope) { |data| true }).to eq(true) }
237
- specify { expect(subject.import(scope) { |data| false }).to eq(false) }
326
+ specify { expect(subject.import(scope) { |_data| true }).to eq(true) }
327
+ specify { expect(subject.import(scope) { |_data| false }).to eq(false) }
238
328
  specify { expect(subject.import(scope, batch_size: 1, &data_comparer.curry[cities[0].id])).to eq(false) }
239
329
  specify { expect(subject.import(scope, batch_size: 1, &data_comparer.curry[cities[1].id])).to eq(false) }
240
330
  specify { expect(subject.import(scope, batch_size: 1, &data_comparer.curry[cities[2].id])).to eq(false) }
@@ -243,8 +333,8 @@ describe Chewy::Type::Adapter::ActiveRecord, :active_record do
243
333
  end
244
334
 
245
335
  context 'objects' do
246
- specify { expect(subject.import(cities + deleted) { |data| true }).to eq(true) }
247
- specify { expect(subject.import(cities + deleted) { |data| false }).to eq(false) }
336
+ specify { expect(subject.import(cities + deleted) { |_data| true }).to eq(true) }
337
+ specify { expect(subject.import(cities + deleted) { |_data| false }).to eq(false) }
248
338
  specify { expect(subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[cities[0].id])).to eq(false) }
249
339
  specify { expect(subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[cities[1].id])).to eq(false) }
250
340
  specify { expect(subject.import(cities + deleted, batch_size: 1, &data_comparer.curry[cities[2].id])).to eq(false) }
@@ -253,8 +343,8 @@ describe Chewy::Type::Adapter::ActiveRecord, :active_record do
253
343
  end
254
344
 
255
345
  context 'ids' do
256
- specify { expect(subject.import(ids) { |data| true }).to eq(true) }
257
- specify { expect(subject.import(ids) { |data| false }).to eq(false) }
346
+ specify { expect(subject.import(ids) { |_data| true }).to eq(true) }
347
+ specify { expect(subject.import(ids) { |_data| false }).to eq(false) }
258
348
  specify { expect(subject.import(ids, batch_size: 1, &data_comparer.curry[cities[0].id])).to eq(false) }
259
349
  specify { expect(subject.import(ids, batch_size: 1, &data_comparer.curry[cities[1].id])).to eq(false) }
260
350
  specify { expect(subject.import(ids, batch_size: 1, &data_comparer.curry[cities[2].id])).to eq(false) }
@@ -266,8 +356,8 @@ describe Chewy::Type::Adapter::ActiveRecord, :active_record do
266
356
 
267
357
  describe '#load' do
268
358
  context do
269
- let!(:cities) { 3.times.map { |i| City.create!(rating: i/2) } }
270
- let!(:deleted) { 2.times.map { |i| City.create!.tap(&:destroy) } }
359
+ let!(:cities) { Array.new(3) { |i| City.create!(rating: i / 2) } }
360
+ let!(:deleted) { Array.new(2) { City.create!.tap(&:destroy) } }
271
361
 
272
362
  let(:type) { double(type_name: 'user') }
273
363
 
@@ -277,22 +367,30 @@ describe Chewy::Type::Adapter::ActiveRecord, :active_record do
277
367
  specify { expect(subject.load(cities.map { |c| double(id: c.id) }.reverse, _type: type)).to eq(cities.reverse) }
278
368
  specify { expect(subject.load(deleted.map { |c| double(id: c.id) }, _type: type)).to eq([nil, nil]) }
279
369
  specify { expect(subject.load((cities + deleted).map { |c| double(id: c.id) }, _type: type)).to eq([*cities, nil, nil]) }
280
- specify { expect(subject.load(cities.map { |c| double(id: c.id) }, _type: type, scope: ->{ where(rating: 0) }))
281
- .to eq(cities.first(2) + [nil]) }
282
- specify { expect(subject.load(cities.map { |c| double(id: c.id) },
283
- _type: type, scope: ->{ where(rating: 0) }, user: {scope: ->{ where(rating: 1)}}))
284
- .to eq([nil, nil] + cities.last(1)) }
285
- specify { expect(subject.load(cities.map { |c| double(id: c.id) }, _type: type, scope: City.where(rating: 1)))
286
- .to eq([nil, nil] + cities.last(1)) }
287
- specify { expect(subject.load(cities.map { |c| double(id: c.id) },
288
- _type: type, scope: City.where(rating: 1), user: {scope: ->{ where(rating: 0)}}))
289
- .to eq(cities.first(2) + [nil]) }
370
+ specify do
371
+ expect(subject.load(cities.map { |c| double(id: c.id) }, _type: type, scope: -> { where(rating: 0) }))
372
+ .to eq(cities.first(2) + [nil])
373
+ end
374
+ specify do
375
+ expect(subject.load(cities.map { |c| double(id: c.id) },
376
+ _type: type, scope: -> { where(rating: 0) }, user: { scope: -> { where(rating: 1) } }))
377
+ .to eq([nil, nil] + cities.last(1))
378
+ end
379
+ specify do
380
+ expect(subject.load(cities.map { |c| double(id: c.id) }, _type: type, scope: City.where(rating: 1)))
381
+ .to eq([nil, nil] + cities.last(1))
382
+ end
383
+ specify do
384
+ expect(subject.load(cities.map { |c| double(id: c.id) },
385
+ _type: type, scope: City.where(rating: 1), user: { scope: -> { where(rating: 0) } }))
386
+ .to eq(cities.first(2) + [nil])
387
+ end
290
388
  end
291
389
 
292
390
  context 'custom primary_key' do
293
391
  before { stub_model(:city) { self.primary_key = 'rating' } }
294
- let!(:cities) { 3.times.map { |i| City.create!(country_id: i/2) { |c| c.rating = i + 7 } } }
295
- let!(:deleted) { 2.times.map { |i| City.create! { |c| c.rating = i + 10 }.tap(&:destroy) } }
392
+ let!(:cities) { Array.new(3) { |i| City.create!(country_id: i / 2) { |c| c.rating = i + 7 } } }
393
+ let!(:deleted) { Array.new(2) { |i| City.create! { |c| c.rating = i + 10 }.tap(&:destroy) } }
296
394
 
297
395
  let(:type) { double(type_name: 'user') }
298
396
 
@@ -302,16 +400,24 @@ describe Chewy::Type::Adapter::ActiveRecord, :active_record do
302
400
  specify { expect(subject.load(cities.map { |c| double(id: c.id) }.reverse, _type: type)).to eq(cities.reverse) }
303
401
  specify { expect(subject.load(deleted.map { |c| double(id: c.id) }, _type: type)).to eq([nil, nil]) }
304
402
  specify { expect(subject.load((cities + deleted).map { |c| double(id: c.id) }, _type: type)).to eq([*cities, nil, nil]) }
305
- specify { expect(subject.load(cities.map { |c| double(id: c.id) }, _type: type, scope: ->{ where(country_id: 0) }))
306
- .to eq(cities.first(2) + [nil]) }
307
- specify { expect(subject.load(cities.map { |c| double(id: c.id) },
308
- _type: type, scope: ->{ where(country_id: 0) }, user: {scope: ->{ where(country_id: 1)}}))
309
- .to eq([nil, nil] + cities.last(1)) }
310
- specify { expect(subject.load(cities.map { |c| double(id: c.id) }, _type: type, scope: City.where(country_id: 1)))
311
- .to eq([nil, nil] + cities.last(1)) }
312
- specify { expect(subject.load(cities.map { |c| double(id: c.id) },
313
- _type: type, scope: City.where(country_id: 1), user: {scope: ->{ where(country_id: 0)}}))
314
- .to eq(cities.first(2) + [nil]) }
403
+ specify do
404
+ expect(subject.load(cities.map { |c| double(id: c.id) }, _type: type, scope: -> { where(country_id: 0) }))
405
+ .to eq(cities.first(2) + [nil])
406
+ end
407
+ specify do
408
+ expect(subject.load(cities.map { |c| double(id: c.id) },
409
+ _type: type, scope: -> { where(country_id: 0) }, user: { scope: -> { where(country_id: 1) } }))
410
+ .to eq([nil, nil] + cities.last(1))
411
+ end
412
+ specify do
413
+ expect(subject.load(cities.map { |c| double(id: c.id) }, _type: type, scope: City.where(country_id: 1)))
414
+ .to eq([nil, nil] + cities.last(1))
415
+ end
416
+ specify do
417
+ expect(subject.load(cities.map { |c| double(id: c.id) },
418
+ _type: type, scope: City.where(country_id: 1), user: { scope: -> { where(country_id: 0) } }))
419
+ .to eq(cities.first(2) + [nil])
420
+ end
315
421
  end
316
422
  end
317
423
  end