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
@@ -13,19 +13,13 @@ describe 'dirty attribute tracking' do
13
13
  end
14
14
 
15
15
  describe "save" do
16
- it "should not save when nothing dirty" do
16
+ it "should save when nothing dirty" do
17
17
  plate = Plate.new :food => 'sushi'
18
18
  @db.save_document!(plate)
19
- expect(@couchrest_db).not_to receive(:save_doc)
19
+ expect(@couchrest_db).to receive(:save_doc)
20
20
  @db.save_document(plate)
21
21
  end
22
22
 
23
- it "should return true when not dirty" do
24
- plate = Plate.new :food => 'sushi'
25
- @db.save_document!(plate)
26
- expect(@db.save_document(plate)).to be_truthy
27
- end
28
-
29
23
  it "should save when there are dirty attributes" do
30
24
  plate = Plate.new :food => 'sushi'
31
25
  @db.save_document!(plate)
@@ -57,13 +51,13 @@ describe 'dirty attribute tracking' do
57
51
  it "should not dup BigDecimal" do
58
52
 
59
53
  expect {
60
- Bowl.new :price => BigDecimal.new("5.23")
54
+ Bowl.new :price => BigDecimal("5.23")
61
55
  }.not_to raise_error
62
56
  end
63
57
 
64
58
  it "should return the old value" do
65
- bowl = Bowl.new :price => BigDecimal.new("5.23")
66
- bowl.price = BigDecimal.new("2.23")
59
+ bowl = Bowl.new :price => BigDecimal("5.23")
60
+ bowl.price = BigDecimal("2.23")
67
61
  expect(bowl.price_was).to eq(5.23)
68
62
  end
69
63
 
@@ -79,11 +73,6 @@ describe 'dirty attribute tracking' do
79
73
  it "should return false if attribute not changed" do
80
74
  expect(Plate.new).not_to be_food_changed
81
75
  end
82
-
83
- it "should return true if forced dirty" do
84
- @plate.is_dirty
85
- expect(@plate).to be_dirty
86
- end
87
76
  end
88
77
  end
89
78
 
@@ -122,15 +111,5 @@ describe 'dirty attribute tracking' do
122
111
  db.save! @plate
123
112
  expect(@plate).not_to be_food_changed
124
113
  end
125
-
126
- it "should reset a forced dirty state" do
127
- couchrest_db = double('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => 'sushi', JSON.create_id => 'Plate'}), :info => nil, :save_doc => {'rev' => '3'})
128
- db = CouchPotato::Database.new(couchrest_db)
129
- @plate = db.load_document '1'
130
- @plate.is_dirty
131
- db.save! @plate
132
- expect(@plate).not_to be_dirty
133
- end
134
114
  end
135
-
136
115
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe CouchPotato::View::FlexViewSpec::Results, '#reduce_count' do
6
+ it 'returns the value of the first row (which is the result of reduce)' do
7
+ result = CouchPotato::View::FlexViewSpec::Results.new 'rows' => [{ 'value' => 3 }]
8
+
9
+ expect(result.reduce_count).to eq(3)
10
+ end
11
+
12
+ it 'returns 0 if there is no first row (empty result set)' do
13
+ result = CouchPotato::View::FlexViewSpec::Results.new 'rows' => []
14
+
15
+ expect(result.reduce_count).to eq(0)
16
+ end
17
+ end
@@ -108,6 +108,6 @@ describe CouchPotato::View::ModelViewSpec, '#map_function' do
108
108
 
109
109
  it "should raise exception when emit value cannot be handled" do
110
110
  spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:emit_value => []}, {}
111
- expect { spec.map_function }.to raise_error
111
+ expect { spec.map_function }.to raise_error(RuntimeError)
112
112
  end
113
113
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'couch_potato-rspec'
3
5
 
@@ -40,6 +42,35 @@ describe 'stubbing a view' do
40
42
  expect(@db.first!(WithStubbedView.stubbed_view('123'))).to eq(:result)
41
43
  end
42
44
 
45
+ it 'stubs the database to return fake results in batches with no given batch size' do
46
+ @db.stub_view(WithStubbedView, :stubbed_view).with('123').and_return([:result] * 501)
47
+
48
+ expect do |b|
49
+ @db.view_in_batches(WithStubbedView.stubbed_view('123'), &b)
50
+ end.to yield_successive_args([:result] * 500, [:result])
51
+ end
52
+
53
+ it 'stubs the database to return fake results in batches with a given batch size' do
54
+ @db.stub_view(WithStubbedView, :stubbed_view).with('123').and_return([:result] * 3)
55
+
56
+ expect do |b|
57
+ @db.view_in_batches(WithStubbedView.stubbed_view('123'), batch_size: 2, &b)
58
+ end.to yield_successive_args([:result] * 2, [:result])
59
+ end
60
+
61
+ it 'stubs the database to return fake results in batches for multiple view specs' do
62
+ @db.stub_view(WithStubbedView, :stubbed_view).with('123').and_return([:result])
63
+ @db.stub_view(WithStubbedView, :stubbed_view).with('456').and_return([:result2])
64
+
65
+ expect do |b|
66
+ @db.view_in_batches(WithStubbedView.stubbed_view('123'), &b)
67
+ end.to yield_successive_args([:result])
68
+
69
+ expect do |b|
70
+ @db.view_in_batches(WithStubbedView.stubbed_view('456'), &b)
71
+ end.to yield_successive_args([:result2])
72
+ end
73
+
43
74
  it 'raises an error if there is no first result' do
44
75
  @db.stub_view(WithStubbedView, :stubbed_view).and_return([])
45
76
  expect do
@@ -1,13 +1,53 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'CouchPotato Validation' do
4
-
4
+
5
5
  describe "access to errors object" do
6
- it "should description" do
6
+ it "adds an errors method the the errors object to be compatible with Validatable" do
7
7
  model_class = Class.new
8
8
  model_class.send(:include, CouchPotato::Persistence)
9
9
  expect(model_class.new.errors).to respond_to(:errors)
10
10
  end
11
11
  end
12
12
 
13
+ class Monkey
14
+ include CouchPotato::Persistence
15
+ property :create_property
16
+ property :update_property
17
+
18
+ validates :create_property, presence: true, on: :create
19
+ validates :update_property, presence: true, on: :update
20
+ end
21
+
22
+ context 'create' do
23
+ let(:monkey) { Monkey.new }
24
+
25
+ before do
26
+ monkey.valid?
27
+ end
28
+
29
+ it 'has an error on the create property' do
30
+ expect(monkey.errors[:create_property]).to be_present
31
+ end
32
+
33
+ it 'has no error on the update property' do
34
+ expect(monkey.errors[:update_property]).not_to be_present
35
+ end
36
+ end
37
+
38
+ context 'update' do
39
+ let(:monkey) { Monkey.new _rev: '1' }
40
+
41
+ before do
42
+ monkey.valid?
43
+ end
44
+
45
+ it 'has no error on the create property' do
46
+ expect(monkey.errors[:create_property]).to_not be_present
47
+ end
48
+
49
+ it 'has an error on the update property' do
50
+ expect(monkey.errors[:update_property]).to be_present
51
+ end
52
+ end
13
53
  end
@@ -15,10 +15,12 @@ describe CouchPotato::View::ViewQuery, 'query_view!' do
15
15
 
16
16
  it 'updates a view if it does not exist' do
17
17
  expect(db).to receive(:save_doc).with(
18
- 'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}, 'lib' => {'test' => '<lib_code>'}},
19
- 'lists' => {},
20
- "_id" => "_design/design",
21
- "language" => "javascript"
18
+ {
19
+ 'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}, 'lib' => {'test' => '<lib_code>'}},
20
+ 'lists' => {},
21
+ "_id" => "_design/design",
22
+ "language" => "javascript"
23
+ }
22
24
  )
23
25
 
24
26
  CouchPotato::View::ViewQuery.new(db, 'design', {:view => {:map => '<map_code>', :reduce => '<reduce_code>'}}, nil, {'test' => "<lib_code>"}).query_view!
@@ -46,8 +48,11 @@ describe CouchPotato::View::ViewQuery, 'query_view!' do
46
48
 
47
49
  it 'updates a view in erlang if it does not exist' do
48
50
  expect(db).to receive(:save_doc).with(
49
- 'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
50
- 'lists' => {}, "_id" => "_design/design", "language" => "erlang")
51
+ {
52
+ 'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
53
+ 'lists' => {}, "_id" => "_design/design", "language" => "erlang"
54
+ }
55
+ )
51
56
 
52
57
  CouchPotato::View::ViewQuery.new(db, 'design',
53
58
  {:view => {:map => '<map_code>', :reduce => '<reduce_code>'}},
@@ -120,7 +125,7 @@ describe CouchPotato::View::ViewQuery, 'query_view!' do
120
125
 
121
126
  it 'does not pass in reduce or lib keys if there is no lib or reduce object' do
122
127
  allow(db).to receive(:get).and_return({'views' => {}})
123
- expect(db).to receive(:save_doc).with('views' => {'view7' => {'map' => '<map code>'}})
128
+ expect(db).to receive(:save_doc).with({'views' => {'view7' => {'map' => '<map code>'}}})
124
129
  CouchPotato::View::ViewQuery.new(db, 'design', :view7 => {:map => '<map code>', :reduce => nil}).query_view!
125
130
  end
126
131