couch_potato 1.7.0 → 1.10.1

Sign up to get free protection for your applications and to get access to all the features.
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