couch_potato 1.7.0 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +50 -0
  3. data/.gitignore +3 -0
  4. data/CHANGES.md +180 -130
  5. data/Gemfile +4 -0
  6. data/README.md +61 -85
  7. data/Rakefile +11 -10
  8. data/couch_potato-rspec.gemspec +2 -1
  9. data/couch_potato.gemspec +9 -7
  10. data/gemfiles/active_support_5_0 +6 -0
  11. data/gemfiles/active_support_5_1 +7 -0
  12. data/gemfiles/active_support_5_2 +6 -0
  13. data/gemfiles/active_support_6_0 +6 -0
  14. data/gemfiles/active_support_6_1 +6 -0
  15. data/gemfiles/active_support_7_0 +6 -0
  16. data/lib/couch_potato/database.rb +170 -71
  17. data/lib/couch_potato/persistence/dirty_attributes.rb +3 -21
  18. data/lib/couch_potato/persistence/magic_timestamps.rb +3 -3
  19. data/lib/couch_potato/persistence/properties.rb +15 -10
  20. data/lib/couch_potato/persistence/simple_property.rb +0 -4
  21. data/lib/couch_potato/persistence/type_caster.rb +11 -6
  22. data/lib/couch_potato/persistence.rb +0 -1
  23. data/lib/couch_potato/railtie.rb +6 -11
  24. data/lib/couch_potato/validation.rb +8 -0
  25. data/lib/couch_potato/version.rb +2 -2
  26. data/lib/couch_potato/view/base_view_spec.rb +8 -32
  27. data/lib/couch_potato/view/custom_views.rb +4 -3
  28. data/lib/couch_potato/view/flex_view_spec.rb +121 -0
  29. data/lib/couch_potato/view/view_parameters.rb +34 -0
  30. data/lib/couch_potato.rb +37 -16
  31. data/spec/callbacks_spec.rb +45 -19
  32. data/spec/conflict_handling_spec.rb +1 -2
  33. data/spec/property_spec.rb +12 -3
  34. data/spec/railtie_spec.rb +10 -0
  35. data/spec/spec_helper.rb +4 -3
  36. data/spec/unit/active_model_compliance_spec.rb +7 -3
  37. data/spec/unit/attributes_spec.rb +54 -1
  38. data/spec/unit/caching_spec.rb +105 -0
  39. data/spec/unit/couch_potato_spec.rb +70 -5
  40. data/spec/unit/create_spec.rb +5 -4
  41. data/spec/unit/database_spec.rb +239 -135
  42. data/spec/unit/dirty_attributes_spec.rb +5 -26
  43. data/spec/unit/flex_view_spec_spec.rb +17 -0
  44. data/spec/unit/model_view_spec_spec.rb +1 -1
  45. data/spec/unit/rspec_stub_db_spec.rb +31 -0
  46. data/spec/unit/validation_spec.rb +42 -2
  47. data/spec/unit/view_query_spec.rb +12 -7
  48. data/spec/views_spec.rb +214 -103
  49. data/vendor/pouchdb-collate/LICENSE +202 -0
  50. data/vendor/pouchdb-collate/pouchdb-collate.js +430 -0
  51. metadata +47 -36
  52. data/.ruby-version +0 -1
  53. data/.travis.yml +0 -21
  54. data/gemfiles/active_support_4_0 +0 -11
  55. data/gemfiles/active_support_4_1 +0 -11
  56. data/gemfiles/active_support_4_2 +0 -11
  57. data/lib/couch_potato/persistence/deep_dirty_attributes.rb +0 -180
  58. data/spec/unit/deep_dirty_attributes_spec.rb +0 -434
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  class DbTestUser
@@ -20,68 +22,67 @@ describe CouchPotato::Database, 'full_url_to_database' do
20
22
  CouchPotato::Config.database_name = @database_url
21
23
  end
22
24
 
23
- it "should return the full URL when it starts with https" do
24
- CouchPotato::Config.database_name = "https://example.com/database"
25
+ it 'should return the full URL when it starts with https' do
26
+ CouchPotato::Config.database_name = 'https://example.com/database'
25
27
  expect(CouchPotato.full_url_to_database).to eq('https://example.com/database')
26
28
  end
27
29
 
28
- it "should return the full URL when it starts with http" do
29
- CouchPotato::Config.database_name = "http://example.com/database"
30
+ it 'should return the full URL when it starts with http' do
31
+ CouchPotato::Config.database_name = 'http://example.com/database'
30
32
  expect(CouchPotato.full_url_to_database).to eq('http://example.com/database')
31
33
  end
32
34
 
33
- it "should use localhost when no protocol was specified" do
34
- CouchPotato::Config.database_name = "database"
35
+ it 'should use localhost when no protocol was specified' do
36
+ CouchPotato::Config.database_name = 'database'
35
37
  expect(CouchPotato.full_url_to_database).to eq('http://127.0.0.1:5984/database')
36
38
  end
37
39
  end
38
40
 
39
41
  describe CouchPotato::Database, 'load' do
40
-
41
- let(:couchrest_db) { double('couchrest db', :info => nil).as_null_object }
42
+ let(:couchrest_db) { double('couchrest db', info: nil).as_null_object }
42
43
  let(:db) { CouchPotato::Database.new couchrest_db }
43
44
 
44
- it "should raise an exception if nil given" do
45
- expect {
45
+ it 'should raise an exception if nil given' do
46
+ expect do
46
47
  db.load nil
47
- }.to raise_error("Can't load a document without an id (got nil)")
48
+ end.to raise_error("Can't load a document without an id (got nil)")
48
49
  end
49
50
 
50
- it "should set itself on the model" do
51
+ it 'should set itself on the model' do
51
52
  user = double('user').as_null_object
52
53
  allow(DbTestUser).to receive(:new).and_return(user)
53
- allow(couchrest_db).to receive(:get).and_return DbTestUser.json_create({JSON.create_id => 'DbTestUser'})
54
+ allow(couchrest_db).to receive(:get).and_return DbTestUser.json_create({ JSON.create_id => 'DbTestUser' })
54
55
  expect(user).to receive(:database=).with(db)
55
56
  db.load '1'
56
57
  end
57
58
 
58
- it "should load namespaced models" do
59
- allow(couchrest_db).to receive(:get).and_return Parent::Child.json_create({JSON.create_id => 'Parent::Child'})
59
+ it 'should load namespaced models' do
60
+ allow(couchrest_db).to receive(:get).and_return Parent::Child.json_create({ JSON.create_id => 'Parent::Child' })
60
61
  expect(db.load('1').class).to eq(Parent::Child)
61
62
  end
62
63
 
63
- context "when several ids given" do
64
+ context 'when several ids given' do
64
65
  let(:doc1) { DbTestUser.new }
65
66
  let(:doc2) { DbTestUser.new }
66
67
  let(:response) do
67
- {"rows" => [{'doc' => nil}, {"doc" => doc1}, {"doc" => doc2}]}
68
+ { 'rows' => [{ 'doc' => nil }, { 'doc' => doc1 }, { 'doc' => doc2 }] }
68
69
  end
69
70
 
70
71
  before(:each) do
71
72
  allow(couchrest_db).to receive(:bulk_load) { response }
72
73
  end
73
74
 
74
- it "requests the couchrest bulk method" do
75
- expect(couchrest_db).to receive(:bulk_load).with(['1', '2', '3'])
76
- db.load ['1', '2', '3']
75
+ it 'requests the couchrest bulk method' do
76
+ expect(couchrest_db).to receive(:bulk_load).with(%w[1 2 3])
77
+ db.load %w[1 2 3]
77
78
  end
78
79
 
79
- it "returns only found documents" do
80
- expect(db.load(['1', '2', '3']).size).to eq(2)
80
+ it 'returns only found documents' do
81
+ expect(db.load(%w[1 2 3]).size).to eq(2)
81
82
  end
82
83
 
83
- it "writes itself to each of the documents" do
84
- db.load(['1', '2', '3']).each do |doc|
84
+ it 'writes itself to each of the documents' do
85
+ db.load(%w[1 2 3]).each do |doc|
85
86
  expect(doc.database).to eql(db)
86
87
  end
87
88
  end
@@ -90,39 +91,41 @@ describe CouchPotato::Database, 'load' do
90
91
  doc1 = double(:doc1)
91
92
  allow(doc1).to receive(:respond_to?).with(:database=) { false }
92
93
  allow(couchrest_db).to receive(:bulk_load) do
93
- {"rows" => [{'doc' => doc1}]}
94
+ { 'rows' => [{ 'doc' => doc1 }] }
94
95
  end
95
96
 
96
97
  expect(doc1).not_to receive(:database=)
97
98
 
98
99
  db.load(['1'])
99
100
  end
101
+
102
+ it 'returns an empty array when passing an empty array' do
103
+ expect(db.load([])).to eq([])
104
+ end
100
105
  end
101
106
  end
102
107
 
103
108
  describe CouchPotato::Database, 'load!' do
109
+ let(:db) { CouchPotato::Database.new(double('couchrest db', info: nil).as_null_object) }
104
110
 
105
- let(:db) { CouchPotato::Database.new(double('couchrest db', :info => nil).as_null_object) }
106
-
107
- it "should raise an error if no document found" do
111
+ it 'should raise an error if no document found' do
108
112
  allow(db.couchrest_database).to receive(:get).and_return(nil)
109
- expect {
113
+ expect do
110
114
  db.load! '1'
111
- }.to raise_error(CouchPotato::NotFound)
115
+ end.to raise_error(CouchPotato::NotFound)
112
116
  end
113
117
 
114
118
  it 'returns the found document' do
115
119
  doc = double(:doc).as_null_object
116
- allow(db.couchrest_database).to receive(:get) {doc}
120
+ allow(db.couchrest_database).to receive(:get) { doc }
117
121
  expect(db.load!('1')).to eq(doc)
118
122
  end
119
123
 
120
- context "when several ids given" do
121
-
124
+ context 'when several ids given' do
122
125
  let(:docs) do
123
126
  [
124
- DbTestUser.new(:id => '1'),
125
- DbTestUser.new(:id => '2')
127
+ DbTestUser.new(id: '1'),
128
+ DbTestUser.new(id: '2')
126
129
  ]
127
130
  end
128
131
 
@@ -130,17 +133,17 @@ describe CouchPotato::Database, 'load!' do
130
133
  allow(db).to receive(:load).and_return(docs)
131
134
  end
132
135
 
133
- it "raises an exception when not all documents could be found" do
134
- expect {
135
- db.load! ['1', '2', '3', '4']
136
- }.to raise_error(CouchPotato::NotFound, '3, 4')
136
+ it 'raises an exception when not all documents could be found' do
137
+ expect do
138
+ db.load! %w[1 2 3 4]
139
+ end.to raise_error(CouchPotato::NotFound, '3, 4')
137
140
  end
138
141
 
139
- it "raises no exception when all documents are found" do
140
- docs << DbTestUser.new(:id => '3')
141
- expect {
142
- db.load! ['1', '2', '3']
143
- }.not_to raise_error
142
+ it 'raises no exception when all documents are found' do
143
+ docs << DbTestUser.new(id: '3')
144
+ expect do
145
+ db.load! %w[1 2 3]
146
+ end.not_to raise_error
144
147
  end
145
148
  end
146
149
  end
@@ -150,9 +153,9 @@ describe CouchPotato::Database, 'save_document' do
150
153
  @db = CouchPotato::Database.new(double('couchrest db').as_null_object)
151
154
  end
152
155
 
153
- it "should set itself on the model for a new object before doing anything else" do
156
+ it 'should set itself on the model for a new object before doing anything else' do
154
157
  allow(@db).to receive(:valid_document?).and_return false
155
- user = double('user', :new? => true).as_null_object
158
+ user = double('user', new?: true).as_null_object
156
159
  expect(user).to receive(:database=).with(@db)
157
160
  @db.save_document user
158
161
  end
@@ -163,68 +166,68 @@ describe CouchPotato::Database, 'save_document' do
163
166
  validates_presence_of :name
164
167
  end
165
168
 
166
- it "should return false when creating a new document and the validations failed" do
169
+ it 'should return false when creating a new document and the validations failed' do
167
170
  expect(CouchPotato.database.save_document(Category.new)).to eq(false)
168
171
  end
169
172
 
170
- it "should return false when saving an existing document and the validations failed" do
171
- category = Category.new(:name => "pizza")
173
+ it 'should return false when saving an existing document and the validations failed' do
174
+ category = Category.new(name: 'pizza')
172
175
  expect(CouchPotato.database.save_document(category)).to eq(true)
173
176
  category.name = nil
174
177
  expect(CouchPotato.database.save_document(category)).to eq(false)
175
178
  end
176
179
 
177
- describe "when creating with validate options" do
178
- it "should not run the validations when saved with false" do
180
+ describe 'when creating with validate options' do
181
+ it 'should not run the validations when saved with false' do
179
182
  category = Category.new
180
183
  @db.save_document(category, false)
181
184
  expect(category.new?).to eq(false)
182
185
  end
183
186
 
184
- it "should run the validations when saved with true" do
187
+ it 'should run the validations when saved with true' do
185
188
  category = Category.new
186
189
  @db.save_document(category, true)
187
190
  expect(category.new?).to eq(true)
188
191
  end
189
192
 
190
- it "should run the validations when saved with default" do
193
+ it 'should run the validations when saved with default' do
191
194
  category = Category.new
192
195
  @db.save_document(category)
193
196
  expect(category.new?).to eq(true)
194
197
  end
195
198
  end
196
199
 
197
- describe "when updating with validate options" do
198
- it "should not run the validations when saved with false" do
199
- category = Category.new(:name => 'food')
200
+ describe 'when updating with validate options' do
201
+ it 'should not run the validations when saved with false' do
202
+ category = Category.new(name: 'food')
200
203
  @db.save_document(category)
201
204
  expect(category.new?).to be_falsey
202
205
  category.name = nil
203
206
  @db.save_document(category, false)
204
- expect(category.dirty?).to be_falsey
207
+ expect(category.changed?).to be_falsey
205
208
  end
206
209
 
207
- it "should run the validations when saved with true" do
208
- category = Category.new(:name => "food")
210
+ it 'should run the validations when saved with true' do
211
+ category = Category.new(name: 'food')
209
212
  @db.save_document(category)
210
213
  expect(category.new?).to eq(false)
211
214
  category.name = nil
212
215
  @db.save_document(category, true)
213
- expect(category.dirty?).to eq(true)
216
+ expect(category.changed?).to eq(true)
214
217
  expect(category.valid?).to eq(false)
215
218
  end
216
219
 
217
- it "should run the validations when saved with default" do
218
- category = Category.new(:name => "food")
220
+ it 'should run the validations when saved with default' do
221
+ category = Category.new(name: 'food')
219
222
  @db.save_document(category)
220
223
  expect(category.new?).to eq(false)
221
224
  category.name = nil
222
225
  @db.save_document(category)
223
- expect(category.dirty?).to eq(true)
226
+ expect(category.changed?).to eq(true)
224
227
  end
225
228
  end
226
229
 
227
- describe "when saving documents with errors set in callbacks" do
230
+ describe 'when saving documents with errors set in callbacks' do
228
231
  class Vulcan
229
232
  include CouchPotato::Persistence
230
233
  before_validation_on_create :set_errors
@@ -234,18 +237,18 @@ describe CouchPotato::Database, 'save_document' do
234
237
  validates_presence_of :name
235
238
 
236
239
  def set_errors
237
- errors.add(:validation, "failed")
240
+ errors.add(:validation, 'failed')
238
241
  end
239
242
  end
240
243
 
241
- it "should keep errors added in before_validation_on_* callbacks when creating a new object" do
242
- spock = Vulcan.new(:name => 'spock')
244
+ it 'should keep errors added in before_validation_on_* callbacks when creating a new object' do
245
+ spock = Vulcan.new(name: 'spock')
243
246
  @db.save_document(spock)
244
247
  expect(spock.errors[:validation]).to eq(['failed'])
245
248
  end
246
249
 
247
- it "should keep errors added in before_validation_on_* callbacks when creating a new object" do
248
- spock = Vulcan.new(:name => 'spock')
250
+ it 'should keep errors added in before_validation_on_* callbacks when creating a new object' do
251
+ spock = Vulcan.new(name: 'spock')
249
252
  @db.save_document(spock, false)
250
253
  expect(spock.new?).to eq(false)
251
254
  spock.name = "spock's father"
@@ -253,14 +256,14 @@ describe CouchPotato::Database, 'save_document' do
253
256
  expect(spock.errors[:validation]).to eq(['failed'])
254
257
  end
255
258
 
256
- it "should keep errors generated from normal validations together with errors set in normal validations" do
259
+ it 'should keep errors generated from normal validations together with errors set in normal validations' do
257
260
  spock = Vulcan.new
258
261
  @db.save_document(spock)
259
262
  expect(spock.errors[:validation]).to eq(['failed'])
260
263
  expect(spock.errors[:name].first).to match(/can't be (empty|blank)/)
261
264
  end
262
265
 
263
- it "should clear errors on subsequent, valid saves when creating" do
266
+ it 'should clear errors on subsequent, valid saves when creating' do
264
267
  spock = Vulcan.new
265
268
  @db.save_document(spock)
266
269
 
@@ -269,8 +272,8 @@ describe CouchPotato::Database, 'save_document' do
269
272
  expect(spock.errors[:name]).to eq([])
270
273
  end
271
274
 
272
- it "should clear errors on subsequent, valid saves when updating" do
273
- spock = Vulcan.new(:name => 'spock')
275
+ it 'should clear errors on subsequent, valid saves when updating' do
276
+ spock = Vulcan.new(name: 'spock')
274
277
  @db.save_document(spock, false)
275
278
 
276
279
  spock.name = nil
@@ -281,7 +284,6 @@ describe CouchPotato::Database, 'save_document' do
281
284
  @db.save_document(spock)
282
285
  expect(spock.errors[:name]).to eq([])
283
286
  end
284
-
285
287
  end
286
288
  end
287
289
 
@@ -290,16 +292,16 @@ describe CouchPotato::Database, 'first' do
290
292
  @couchrest_db = double('couchrest db').as_null_object
291
293
  @db = CouchPotato::Database.new(@couchrest_db)
292
294
  @result = double('result')
293
- @spec = double('view spec', :process_results => [@result]).as_null_object
294
- allow(CouchPotato::View::ViewQuery).to receive_messages(:new => double('view query', :query_view! => {'rows' => [@result]}))
295
+ @spec = double('view spec', process_results: [@result]).as_null_object
296
+ allow(CouchPotato::View::ViewQuery).to receive_messages(new: double('view query', query_view!: { 'rows' => [@result] }))
295
297
  end
296
298
 
297
- it "should return the first result from a view query" do
299
+ it 'should return the first result from a view query' do
298
300
  expect(@db.first(@spec)).to eq(@result)
299
301
  end
300
302
 
301
- it "should return nil if there are no results" do
302
- allow(@spec).to receive_messages(:process_results => [])
303
+ it 'should return nil if there are no results' do
304
+ allow(@spec).to receive_messages(process_results: [])
303
305
  expect(@db.first(@spec)).to be_nil
304
306
  end
305
307
  end
@@ -309,19 +311,19 @@ describe CouchPotato::Database, 'first!' do
309
311
  @couchrest_db = double('couchrest db').as_null_object
310
312
  @db = CouchPotato::Database.new(@couchrest_db)
311
313
  @result = double('result')
312
- @spec = double('view spec', :process_results => [@result]).as_null_object
313
- allow(CouchPotato::View::ViewQuery).to receive_messages(:new => double('view query', :query_view! => {'rows' => [@result]}))
314
+ @spec = double('view spec', process_results: [@result]).as_null_object
315
+ allow(CouchPotato::View::ViewQuery).to receive_messages(new: double('view query', query_view!: { 'rows' => [@result] }))
314
316
  end
315
317
 
316
- it "returns the first result from a view query" do
318
+ it 'returns the first result from a view query' do
317
319
  expect(@db.first!(@spec)).to eq(@result)
318
320
  end
319
321
 
320
- it "raises an error if there are no results" do
321
- allow(@spec).to receive_messages(:process_results => [])
322
- expect {
322
+ it 'raises an error if there are no results' do
323
+ allow(@spec).to receive_messages(process_results: [])
324
+ expect do
323
325
  @db.first!(@spec)
324
- }.to raise_error(CouchPotato::NotFound)
326
+ end.to raise_error(CouchPotato::NotFound)
325
327
  end
326
328
  end
327
329
 
@@ -330,76 +332,80 @@ describe CouchPotato::Database, 'view' do
330
332
  @couchrest_db = double('couchrest db').as_null_object
331
333
  @db = CouchPotato::Database.new(@couchrest_db)
332
334
  @result = double('result')
333
- @spec = double('view spec', :process_results => [@result]).as_null_object
334
- allow(CouchPotato::View::ViewQuery).to receive_messages(:new => double('view query', :query_view! => {'rows' => [@result]}))
335
+ @spec = double('view spec', process_results: [@result]).as_null_object
336
+ allow(CouchPotato::View::ViewQuery).to receive_messages(new: double('view query', query_view!: { 'rows' => [@result] }))
335
337
  end
336
338
 
337
- it "initialzes a view query with map/reduce/list/lib funtions" do
338
- allow(@spec).to receive_messages(:design_document => 'design_doc', :view_name => 'my_view',
339
- :map_function => '<map_code>', :reduce_function => '<reduce_code>',
340
- :lib => {:test => '<test_code>'},
341
- :list_name => 'my_list', :list_function => '<list_code>', :language => 'javascript')
339
+ it 'initialzes a view query with map/reduce/list/lib funtions' do
340
+ allow(@spec).to receive_messages(design_document: 'design_doc', view_name: 'my_view',
341
+ map_function: '<map_code>', reduce_function: '<reduce_code>',
342
+ lib: { test: '<test_code>' },
343
+ list_name: 'my_list', list_function: '<list_code>', language: 'javascript')
342
344
  expect(CouchPotato::View::ViewQuery).to receive(:new).with(
343
345
  @couchrest_db,
344
346
  'design_doc',
345
- {'my_view' => {
346
- :map => '<map_code>',
347
- :reduce => '<reduce_code>'
348
- }},
349
- {'my_list' => '<list_code>'},
350
- {:test => '<test_code>'},
351
- 'javascript')
347
+ { 'my_view' => {
348
+ map: '<map_code>',
349
+ reduce: '<reduce_code>'
350
+ } },
351
+ { 'my_list' => '<list_code>' },
352
+ { test: '<test_code>' },
353
+ 'javascript'
354
+ )
352
355
  @db.view(@spec)
353
356
  end
354
357
 
355
- it "initialzes a view query with map/reduce/list funtions" do
356
- allow(@spec).to receive_messages(:design_document => 'design_doc', :view_name => 'my_view',
357
- :map_function => '<map_code>', :reduce_function => '<reduce_code>',
358
- :lib => nil, :list_name => 'my_list', :list_function => '<list_code>',
359
- :language => 'javascript')
358
+ it 'initialzes a view query with map/reduce/list funtions' do
359
+ allow(@spec).to receive_messages(design_document: 'design_doc', view_name: 'my_view',
360
+ map_function: '<map_code>', reduce_function: '<reduce_code>',
361
+ lib: nil, list_name: 'my_list', list_function: '<list_code>',
362
+ language: 'javascript')
360
363
  expect(CouchPotato::View::ViewQuery).to receive(:new).with(
361
364
  @couchrest_db,
362
365
  'design_doc',
363
- {'my_view' => {
364
- :map => '<map_code>',
365
- :reduce => '<reduce_code>'
366
- }},
367
- {'my_list' => '<list_code>'},
366
+ { 'my_view' => {
367
+ map: '<map_code>',
368
+ reduce: '<reduce_code>'
369
+ } },
370
+ { 'my_list' => '<list_code>' },
368
371
  nil,
369
- 'javascript')
372
+ 'javascript'
373
+ )
370
374
  @db.view(@spec)
371
375
  end
372
376
 
373
- it "initialzes a view query with only map/reduce/lib functions" do
374
- allow(@spec).to receive_messages(:design_document => 'design_doc', :view_name => 'my_view',
375
- :map_function => '<map_code>', :reduce_function => '<reduce_code>',
376
- :list_name => nil, :list_function => nil,
377
- :lib => {:test => '<test_code>'})
377
+ it 'initialzes a view query with only map/reduce/lib functions' do
378
+ allow(@spec).to receive_messages(design_document: 'design_doc', view_name: 'my_view',
379
+ map_function: '<map_code>', reduce_function: '<reduce_code>',
380
+ list_name: nil, list_function: nil,
381
+ lib: { test: '<test_code>' })
378
382
  expect(CouchPotato::View::ViewQuery).to receive(:new).with(
379
383
  @couchrest_db,
380
384
  'design_doc',
381
- {'my_view' => {
382
- :map => '<map_code>',
383
- :reduce => '<reduce_code>'
384
- }}, nil, {:test => '<test_code>'}, anything)
385
+ { 'my_view' => {
386
+ map: '<map_code>',
387
+ reduce: '<reduce_code>'
388
+ } }, nil, { test: '<test_code>' }, anything
389
+ )
385
390
  @db.view(@spec)
386
391
  end
387
392
 
388
- it "initialzes a view query with only map/reduce functions" do
389
- allow(@spec).to receive_messages(:design_document => 'design_doc', :view_name => 'my_view',
390
- :map_function => '<map_code>', :reduce_function => '<reduce_code>',
391
- :lib => nil, :list_name => nil, :list_function => nil)
393
+ it 'initialzes a view query with only map/reduce functions' do
394
+ allow(@spec).to receive_messages(design_document: 'design_doc', view_name: 'my_view',
395
+ map_function: '<map_code>', reduce_function: '<reduce_code>',
396
+ lib: nil, list_name: nil, list_function: nil)
392
397
  expect(CouchPotato::View::ViewQuery).to receive(:new).with(
393
398
  @couchrest_db,
394
399
  'design_doc',
395
- {'my_view' => {
396
- :map => '<map_code>',
397
- :reduce => '<reduce_code>'
398
- }}, nil, nil, anything)
400
+ { 'my_view' => {
401
+ map: '<map_code>',
402
+ reduce: '<reduce_code>'
403
+ } }, nil, nil, anything
404
+ )
399
405
  @db.view(@spec)
400
406
  end
401
407
 
402
- it "sets itself on returned results that have an accessor" do
408
+ it 'sets itself on returned results that have an accessor' do
403
409
  allow(@result).to receive(:respond_to?).with(:database=).and_return(true)
404
410
  expect(@result).to receive(:database=).with(@db)
405
411
  @db.view(@spec)
@@ -411,15 +417,51 @@ describe CouchPotato::Database, 'view' do
411
417
  @db.view(@spec)
412
418
  end
413
419
 
414
- it "does not try to set itself on result sets that are not collections" do
415
- expect {
416
- allow(@spec).to receive_messages(:process_results => 1)
417
- }.not_to raise_error
420
+ it 'does not try to set itself on result sets that are not collections' do
421
+ expect do
422
+ allow(@spec).to receive_messages(process_results: 1)
423
+ end.not_to raise_error
418
424
 
419
425
  @db.view(@spec)
420
426
  end
421
427
  end
422
428
 
429
+ describe CouchPotato::Database, '#view_in_batches' do
430
+ let(:view_query) do
431
+ instance_double(
432
+ CouchPotato::View::ViewQuery,
433
+ query_view!: { 'rows' => [result] }
434
+ )
435
+ end
436
+ let(:result) { double('result') }
437
+ let(:spec) { double('view spec', process_results: [result]).as_null_object }
438
+ let(:couchrest_db) { double('couchrest db').as_null_object }
439
+ let(:db) { CouchPotato::Database.new(couchrest_db) }
440
+
441
+ before(:each) do
442
+ allow(CouchPotato::View::ViewQuery)
443
+ .to receive_messages(new: view_query)
444
+ end
445
+
446
+ it 'sets skip/limit for each batch' do
447
+ allow(spec).to receive(:process_results).and_return([result, result], [result]) # run twice
448
+ allow(spec).to receive(:view_parameters) { { key: 'x' } }
449
+
450
+ expect(spec).to receive(:view_parameters=)
451
+ .with({key: 'x', skip: 0, limit: 2})
452
+ expect(spec).to receive(:view_parameters=)
453
+ .with({key: 'x', skip: 2, limit: 2})
454
+
455
+ db.view_in_batches(spec, batch_size: 2) { |results| }
456
+ end
457
+
458
+ it 'yields batches until running out of data' do
459
+ allow(spec).to receive(:process_results).and_return([result, result], [result])
460
+
461
+ expect { |b| db.view_in_batches(spec, batch_size: 2, &b) }.to yield_successive_args([result, result], [result])
462
+ end
463
+ end
464
+
423
465
  describe CouchPotato::Database, '#destroy' do
424
466
  it 'does not try to delete an already deleted document' do
425
467
  couchrest_db = double(:couchrest_db)
@@ -428,8 +470,70 @@ describe CouchPotato::Database, '#destroy' do
428
470
  document = double(:document, reload: nil).as_null_object
429
471
  allow(document).to receive(:run_callbacks).and_yield
430
472
 
431
- expect {
473
+ expect do
432
474
  db.destroy document
433
- }.to_not raise_error
475
+ end.to_not raise_error
476
+ end
477
+ end
478
+
479
+ describe CouchPotato::Database, '#switch_to' do
480
+ let(:couchrest_db) { instance_double(CouchRest::Database) }
481
+ let(:db) { CouchPotato::Database.new couchrest_db }
482
+
483
+ it 'returns the database with the given name' do
484
+ new_db = db.switch_to('db2')
485
+
486
+ expect(new_db.couchrest_database.name).to eq('db2')
487
+ end
488
+
489
+ it 'adds a cleared cache to the new database if the original has one' do
490
+ db.cache = { key: 'value' }
491
+ new_db = db.switch_to('db2')
492
+
493
+ expect(new_db.cache).to be_empty
494
+ end
495
+
496
+ it 'does not clear the cache of the original database' do
497
+ db.cache = { key: 'value' }
498
+ _new_db = db.switch_to('db2')
499
+
500
+ expect(db.cache).to have_key(:key)
501
+ end
502
+
503
+ it 'adds no cache to the new database if the original has none' do
504
+ new_db = db.switch_to('db2')
505
+
506
+ expect(new_db.cache).to be_nil
507
+ end
508
+ end
509
+
510
+ describe CouchPotato::Database, '#switch_to_default' do
511
+ let(:couchrest_db) { instance_double(CouchRest::Database) }
512
+ let(:db) { CouchPotato::Database.new couchrest_db }
513
+
514
+ it 'returns the default database' do
515
+ new_db = db.switch_to_default
516
+
517
+ expect(new_db.couchrest_database.name).to eq('couch_potato_test')
518
+ end
519
+
520
+ it 'adds a cleared cache to the new database if the original has one' do
521
+ db.cache = { key: 'value' }
522
+ new_db = db.switch_to_default
523
+
524
+ expect(new_db.cache).to be_empty
525
+ end
526
+
527
+ it 'does not clear the cache of the original database' do
528
+ db.cache = { key: 'value' }
529
+ _new_db = db.switch_to_default
530
+
531
+ expect(db.cache).to have_key(:key)
532
+ end
533
+
534
+ it 'adds no cache to the new database if the original has none' do
535
+ new_db = db.switch_to_default
536
+
537
+ expect(new_db.cache).to be_nil
434
538
  end
435
539
  end