couch_potato 1.6.5 → 1.10.0

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