couch_potato 1.7.1 → 1.9.0
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.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +38 -0
- data/.gitignore +3 -0
- data/CHANGES.md +169 -131
- data/Gemfile +4 -0
- data/README.md +55 -75
- data/Rakefile +11 -10
- data/couch_potato-rspec.gemspec +2 -1
- data/couch_potato.gemspec +8 -6
- data/gemfiles/active_support_5_0 +1 -5
- data/gemfiles/active_support_5_1 +7 -0
- data/gemfiles/active_support_5_2 +7 -0
- data/gemfiles/active_support_6_0 +7 -0
- data/gemfiles/active_support_6_1 +7 -0
- data/lib/couch_potato/database.rb +165 -70
- data/lib/couch_potato/persistence/dirty_attributes.rb +3 -21
- data/lib/couch_potato/persistence/magic_timestamps.rb +3 -3
- data/lib/couch_potato/persistence/properties.rb +15 -10
- data/lib/couch_potato/persistence/simple_property.rb +0 -4
- data/lib/couch_potato/persistence/type_caster.rb +9 -6
- data/lib/couch_potato/persistence.rb +0 -1
- data/lib/couch_potato/railtie.rb +6 -11
- data/lib/couch_potato/validation.rb +8 -0
- data/lib/couch_potato/version.rb +1 -1
- data/lib/couch_potato/view/base_view_spec.rb +8 -32
- data/lib/couch_potato/view/custom_views.rb +4 -3
- data/lib/couch_potato/view/flex_view_spec.rb +121 -0
- data/lib/couch_potato/view/view_parameters.rb +34 -0
- data/lib/couch_potato.rb +32 -9
- data/spec/callbacks_spec.rb +45 -19
- data/spec/conflict_handling_spec.rb +0 -1
- data/spec/property_spec.rb +2 -2
- data/spec/railtie_spec.rb +10 -0
- data/spec/spec_helper.rb +4 -3
- data/spec/unit/active_model_compliance_spec.rb +7 -3
- data/spec/unit/attributes_spec.rb +1 -1
- data/spec/unit/caching_spec.rb +105 -0
- data/spec/unit/couch_potato_spec.rb +70 -5
- data/spec/unit/create_spec.rb +5 -4
- data/spec/unit/database_spec.rb +235 -135
- data/spec/unit/dirty_attributes_spec.rb +5 -26
- data/spec/unit/flex_view_spec_spec.rb +17 -0
- data/spec/unit/model_view_spec_spec.rb +1 -1
- data/spec/unit/rspec_stub_db_spec.rb +31 -0
- data/spec/unit/validation_spec.rb +42 -2
- data/spec/views_spec.rb +214 -103
- data/vendor/pouchdb-collate/LICENSE +202 -0
- data/vendor/pouchdb-collate/pouchdb-collate.js +430 -0
- metadata +46 -42
- data/.ruby-version +0 -1
- data/.travis.yml +0 -21
- data/gemfiles/active_support_4_0 +0 -11
- data/gemfiles/active_support_4_1 +0 -11
- data/gemfiles/active_support_4_2 +0 -11
- data/lib/couch_potato/persistence/deep_dirty_attributes.rb +0 -180
- data/spec/unit/deep_dirty_attributes_spec.rb +0 -434
@@ -1,434 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
class Cover
|
4
|
-
include CouchPotato::Persistence
|
5
|
-
|
6
|
-
def initialize(*args)
|
7
|
-
self._id = SecureRandom.uuid
|
8
|
-
super
|
9
|
-
end
|
10
|
-
|
11
|
-
property :color
|
12
|
-
end
|
13
|
-
|
14
|
-
class Page
|
15
|
-
include CouchPotato::Persistence
|
16
|
-
|
17
|
-
def initialize(*args)
|
18
|
-
self._id = SecureRandom.uuid
|
19
|
-
super
|
20
|
-
end
|
21
|
-
|
22
|
-
property :number
|
23
|
-
property :headline
|
24
|
-
end
|
25
|
-
|
26
|
-
class Book
|
27
|
-
include CouchPotato::Persistence
|
28
|
-
include CouchPotato::Persistence::DeepDirtyAttributes
|
29
|
-
|
30
|
-
property :title
|
31
|
-
property :cover, :type => Cover
|
32
|
-
property :authors, :type => [String]
|
33
|
-
property :pages, :type => [Page]
|
34
|
-
end
|
35
|
-
|
36
|
-
class TextBook < Book
|
37
|
-
property :edition
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "deep dirty attribute tracking" do
|
41
|
-
describe "standard dirty checking" do
|
42
|
-
describe "_changed?" do
|
43
|
-
it "should return true if only root simple properties have changed" do
|
44
|
-
book = Book.new(:title => "A")
|
45
|
-
book.title = "B"
|
46
|
-
expect(book).to be_title_changed
|
47
|
-
expect(book).to be_changed
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe "_was" do
|
52
|
-
it "gives access to old values of simple root properties" do
|
53
|
-
book = Book.new(:title => "A")
|
54
|
-
book.title = "B"
|
55
|
-
expect(book.title_was).to eq("A")
|
56
|
-
expect(book.title_change).to eq(["A", "B"])
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
describe "_change" do
|
61
|
-
it "returns standard _change" do
|
62
|
-
book = Book.new(:title => "A")
|
63
|
-
book.title = "B"
|
64
|
-
expect(book.title_change).to eq(["A", "B"])
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
describe "single nested document" do
|
70
|
-
describe "_changed?" do
|
71
|
-
it "should return true if a nested attribute has changed" do
|
72
|
-
book = Book.new(:cover => Cover.new(:color => "red"))
|
73
|
-
book.cover.color = "blue"
|
74
|
-
expect(book).to be_cover_changed
|
75
|
-
expect(book).to be_changed
|
76
|
-
end
|
77
|
-
|
78
|
-
it "should return true if changed to a different document" do
|
79
|
-
book = Book.new(:cover => Cover.new(:color => "red"))
|
80
|
-
book.cover = Cover.new(:color => "blue")
|
81
|
-
expect(book).to be_cover_changed
|
82
|
-
expect(book).to be_changed
|
83
|
-
end
|
84
|
-
|
85
|
-
it "should return false if changed to a clone of the original document" do
|
86
|
-
book = Book.new(:cover => Cover.new(:color => "red"))
|
87
|
-
book.cover = book.cover.clone
|
88
|
-
expect(book).not_to be_cover_changed
|
89
|
-
expect(book).not_to be_changed
|
90
|
-
end
|
91
|
-
|
92
|
-
it "should return false if set to nil and unchanged" do
|
93
|
-
book = Book.new
|
94
|
-
expect(book).not_to be_cover_changed
|
95
|
-
expect(book).not_to be_changed
|
96
|
-
end
|
97
|
-
|
98
|
-
it "should return true when reassigned with changes but the same _id" do
|
99
|
-
book = Book.new(:cover => Cover.new(:_id => "cid", :color => "red"))
|
100
|
-
book.cover = Cover.new(:_id => "cid", :color => "blue")
|
101
|
-
expect(book).to be_cover_changed
|
102
|
-
expect(book).to be_changed
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
describe "_was" do
|
107
|
-
it "gives access to the old value" do
|
108
|
-
book = Book.new(:cover => Cover.new(:color => "red"))
|
109
|
-
book.cover.color = "blue"
|
110
|
-
expect(book.cover_was.color).to eq("red")
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
describe "_change" do
|
115
|
-
it "should return the standard changes when a nested document is reassigned" do
|
116
|
-
book = Book.new(:cover => Cover.new(:color => "red"))
|
117
|
-
book.cover = Cover.new(:color => "blue")
|
118
|
-
expect(book.cover_change[0]).to be_a Cover
|
119
|
-
expect(book.cover_change[0].color).to eq("red")
|
120
|
-
expect(book.cover_change[1]).to be_a Cover
|
121
|
-
expect(book.cover_change[1].color).to eq("blue")
|
122
|
-
end
|
123
|
-
|
124
|
-
it "should return the standard changes when a nested document is reassigned from nil" do
|
125
|
-
book = Book.new
|
126
|
-
book.cover = Cover.new
|
127
|
-
expect(book.cover_change[0]).to eq(nil)
|
128
|
-
expect(book.cover_change[1]).to eq(book.cover)
|
129
|
-
end
|
130
|
-
|
131
|
-
it "should return the standard changes when a nested document is reassigned to nil" do
|
132
|
-
cover = Cover.new
|
133
|
-
book = Book.new(:cover => cover)
|
134
|
-
book.cover = nil
|
135
|
-
expect(book.cover_change[0]).to eq(cover)
|
136
|
-
expect(book.cover_change[1]).to eq(nil)
|
137
|
-
end
|
138
|
-
|
139
|
-
it "should return the nested changes when a nested document is changed" do
|
140
|
-
book = Book.new(:cover => Cover.new(:color => "red"))
|
141
|
-
book.cover.color = "blue"
|
142
|
-
expect(book.cover_change[0]).to be_a Cover
|
143
|
-
expect(book.cover_change[0].color).to eq("red")
|
144
|
-
expect(book.cover_change[1]).to eq(book.cover.changes)
|
145
|
-
end
|
146
|
-
|
147
|
-
it "should return the nested changes when reassigned with changes but the same _id" do
|
148
|
-
book = Book.new(:cover => Cover.new(:_id => "cid", :color => "red"))
|
149
|
-
book.cover = Cover.new(:_id => "cid", :color => "blue")
|
150
|
-
expect(book.cover_change[0]).to be_a Cover
|
151
|
-
expect(book.cover_change[0].color).to eq("red")
|
152
|
-
expect(book.cover_change[1]).to eq({"color" => ["red", "blue"]})
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
describe "simple array" do
|
158
|
-
describe "_changed?" do
|
159
|
-
it "returns true if the array is reassigned" do
|
160
|
-
book = Book.new(:authors => ["Sarah"])
|
161
|
-
book.authors = ["Jane"]
|
162
|
-
expect(book).to be_authors_changed
|
163
|
-
end
|
164
|
-
|
165
|
-
it "returns true if an item is added" do
|
166
|
-
book = Book.new(:authors => ["Jane"])
|
167
|
-
book.authors << "Sue"
|
168
|
-
expect(book).to be_authors_changed
|
169
|
-
expect(book).to be_changed
|
170
|
-
end
|
171
|
-
|
172
|
-
it "returns true if an item is removed" do
|
173
|
-
book = Book.new(:authors => ["Sue"])
|
174
|
-
book.authors.delete "Sue"
|
175
|
-
expect(book).to be_authors_changed
|
176
|
-
expect(book).to be_changed
|
177
|
-
end
|
178
|
-
|
179
|
-
it "returns false if an empty array is unchanged" do
|
180
|
-
book = Book.new(:authors => [])
|
181
|
-
book.authors = []
|
182
|
-
expect(book).not_to be_authors_changed
|
183
|
-
expect(book).not_to be_changed
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
describe "_was" do
|
188
|
-
it "gives access to the old values" do
|
189
|
-
book = Book.new(:authors => ["Jane"])
|
190
|
-
book.authors << "Sue"
|
191
|
-
expect(book.authors_was).to eq(["Jane"])
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
describe "_change" do
|
196
|
-
it "returns a hash of added and removed items" do
|
197
|
-
book = Book.new(:authors => ["Jane"])
|
198
|
-
book.authors << "Sue"
|
199
|
-
book.authors.delete "Jane"
|
200
|
-
expect(book.authors_change[0]).to eq(["Jane"])
|
201
|
-
expect(book.authors_change[1]).to be_a HashWithIndifferentAccess
|
202
|
-
expect(book.authors_change[1][:added]).to eq(["Sue"])
|
203
|
-
expect(book.authors_change[1][:removed]).to eq(["Jane"])
|
204
|
-
end
|
205
|
-
|
206
|
-
it "returns a hash of added and removed items when the array is reassigned" do
|
207
|
-
book = Book.new(:authors => ["Jane"])
|
208
|
-
book.authors = ["Sue"]
|
209
|
-
expect(book.authors_change[0]).to eq(["Jane"])
|
210
|
-
expect(book.authors_change[1]).to be_a HashWithIndifferentAccess
|
211
|
-
expect(book.authors_change[1][:added]).to eq(["Sue"])
|
212
|
-
expect(book.authors_change[1][:removed]).to eq(["Jane"])
|
213
|
-
end
|
214
|
-
|
215
|
-
it "returns a hash of added items when the value is changed from nil to an array" do
|
216
|
-
book = Book.new
|
217
|
-
book.authors = ["Sue"]
|
218
|
-
expect(book.authors_change[0]).to eq([])
|
219
|
-
expect(book.authors_change[1]).to be_a HashWithIndifferentAccess
|
220
|
-
expect(book.authors_change[1][:added]).to eq(["Sue"])
|
221
|
-
expect(book.authors_change[1][:removed]).to eq([])
|
222
|
-
end
|
223
|
-
|
224
|
-
it "returns a hash of removed items when the value is changed from an array to nil" do
|
225
|
-
book = Book.new(:authors => ["Jane"])
|
226
|
-
book.authors = nil
|
227
|
-
expect(book.authors_change[0]).to eq(["Jane"])
|
228
|
-
expect(book.authors_change[1]).to be_a HashWithIndifferentAccess
|
229
|
-
expect(book.authors_change[1][:added]).to eq([])
|
230
|
-
expect(book.authors_change[1][:removed]).to eq(["Jane"])
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
describe "document array" do
|
236
|
-
describe "_changed?" do
|
237
|
-
it "returns true if an item is changed" do
|
238
|
-
book = Book.new(:pages => [Page.new(:number => 1)])
|
239
|
-
book.pages[0].number = 2
|
240
|
-
expect(book).to be_pages_changed
|
241
|
-
expect(book).to be_changed
|
242
|
-
end
|
243
|
-
|
244
|
-
it "returns true if an item is added" do
|
245
|
-
book = Book.new(:pages => [Page.new(:number => 1)])
|
246
|
-
book.pages << Page.new(:number => 2)
|
247
|
-
expect(book).to be_pages_changed
|
248
|
-
expect(book).to be_changed
|
249
|
-
end
|
250
|
-
|
251
|
-
it "returns true if an items is removed" do
|
252
|
-
book = Book.new(:pages => [Page.new(:number => 1)])
|
253
|
-
book.pages.delete_at 0
|
254
|
-
expect(book).to be_pages_changed
|
255
|
-
expect(book).to be_changed
|
256
|
-
end
|
257
|
-
|
258
|
-
it "returns true if an item is replaced" do
|
259
|
-
book = Book.new(:pages => [Page.new(:number => 1)])
|
260
|
-
book.pages[0] = Page.new(:number => 2)
|
261
|
-
expect(book).to be_pages_changed
|
262
|
-
expect(book).to be_changed
|
263
|
-
end
|
264
|
-
|
265
|
-
it "returns false if an item is replaced with a clone" do
|
266
|
-
book = Book.new(:pages => [Page.new(:number => 1)])
|
267
|
-
book.pages[0] = book.pages[0].clone
|
268
|
-
expect(book).not_to be_pages_changed
|
269
|
-
expect(book).not_to be_changed
|
270
|
-
end
|
271
|
-
|
272
|
-
it "returns true if an item is replaced with changes but the same _id" do
|
273
|
-
book = Book.new(:pages => [Page.new(:_id => "pid", :number => 1)])
|
274
|
-
book.pages[0] = Page.new(:_id => "pid", :number => 2)
|
275
|
-
expect(book).to be_pages_changed
|
276
|
-
expect(book).to be_changed
|
277
|
-
end
|
278
|
-
|
279
|
-
it "returns false if an empty array is unchanged" do
|
280
|
-
book = Book.new(:pages => [])
|
281
|
-
book.pages = []
|
282
|
-
expect(book).not_to be_authors_changed
|
283
|
-
expect(book).not_to be_changed
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
describe "_was" do
|
288
|
-
it "gives access to the old values" do
|
289
|
-
book = Book.new(:pages => [Page.new(:number => 1)])
|
290
|
-
book.pages[0].number = 2
|
291
|
-
expect(book.pages_was[0].number).to eq(1)
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
describe "_change" do
|
296
|
-
it "returns a changes hash with added, removed, and changed items" do
|
297
|
-
p1 = Page.new
|
298
|
-
p2 = Page.new(:headline => "A")
|
299
|
-
p3 = Page.new
|
300
|
-
book = Book.new(:pages => [p1, p2])
|
301
|
-
pages = book.pages.clone
|
302
|
-
book.pages = [p2]
|
303
|
-
p2.headline = "B"
|
304
|
-
book.pages << p3
|
305
|
-
expect(book.pages_change[0]).to eq(pages)
|
306
|
-
expect(book.pages_change[1]).to be_a HashWithIndifferentAccess
|
307
|
-
expect(book.pages_change[1][:added]).to eq([p3])
|
308
|
-
expect(book.pages_change[1][:removed]).to eq([p1])
|
309
|
-
expect(book.pages_change[1][:changed][0][0]).to be_a Page
|
310
|
-
expect(book.pages_change[1][:changed][0][0].headline).to eq("A")
|
311
|
-
expect(book.pages_change[1][:changed][0][1]).to eq(p2.changes)
|
312
|
-
end
|
313
|
-
|
314
|
-
it "returns added items when changing from nil to an array" do
|
315
|
-
p1 = Page.new
|
316
|
-
p2 = Page.new(:headline => "A")
|
317
|
-
book = Book.new
|
318
|
-
book.pages = [p1, p2]
|
319
|
-
expect(book.pages_change[0]).to eq([])
|
320
|
-
expect(book.pages_change[1]).to be_a HashWithIndifferentAccess
|
321
|
-
expect(book.pages_change[1][:added]).to eq([p1, p2])
|
322
|
-
expect(book.pages_change[1][:removed]).to eq([])
|
323
|
-
expect(book.pages_change[1][:changed]).to eq([])
|
324
|
-
end
|
325
|
-
|
326
|
-
it "does not return unchanged cloned items as changes" do
|
327
|
-
book = Book.new(:pages => [Page.new(:number => 1)])
|
328
|
-
book.pages[0] = book.pages[0].clone
|
329
|
-
expect(book.pages_change).to be_nil
|
330
|
-
end
|
331
|
-
|
332
|
-
it "returns changes if an item is replaced with changes but the same _id" do
|
333
|
-
book = Book.new(:pages => [Page.new(:_id => "pid", :number => 1)])
|
334
|
-
pages = book.pages.clone
|
335
|
-
book.pages[0] = Page.new(:_id => "pid", :number => 2)
|
336
|
-
expect(book.pages_change[0]).to eq(pages)
|
337
|
-
expect(book.pages_change[1]).to be_a HashWithIndifferentAccess
|
338
|
-
expect(book.pages_change[1][:added]).to eq([])
|
339
|
-
expect(book.pages_change[1][:removed]).to eq([])
|
340
|
-
expect(book.pages_change[1][:changed]).to eq([[pages[0], {"number" => [1, 2]}]])
|
341
|
-
end
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
|
-
describe "changes" do
|
346
|
-
it "includes simple property changes" do
|
347
|
-
book = Book.new(:title => "Title A")
|
348
|
-
book.title = "Title B"
|
349
|
-
expect(book.changes[:title]).to eq(book.title_change)
|
350
|
-
end
|
351
|
-
|
352
|
-
it "includes embedded document changes" do
|
353
|
-
book = Book.new(:cover => Cover.new(:color => "red"))
|
354
|
-
cover = book.cover.clone
|
355
|
-
book.cover.color = "blue"
|
356
|
-
expect(book.changes[:cover]).to eq(book.cover_change)
|
357
|
-
end
|
358
|
-
|
359
|
-
it "does not include unchanged embedded documents" do
|
360
|
-
book = Book.new(:cover => Cover.new(:color => "red"))
|
361
|
-
expect(book.changes).not_to have_key :cover
|
362
|
-
end
|
363
|
-
|
364
|
-
it "includes simple array changes" do
|
365
|
-
book = Book.new(:authors => ["Sarah"])
|
366
|
-
book.authors = ["Jane"]
|
367
|
-
expect(book.changes[:authors]).to eq(book.authors_change)
|
368
|
-
end
|
369
|
-
|
370
|
-
it "does not include unchanged simple arrays" do
|
371
|
-
book = Book.new(:authors => ["Sarah"])
|
372
|
-
expect(book.changes).not_to have_key :authors
|
373
|
-
end
|
374
|
-
|
375
|
-
it "includes document array changes" do
|
376
|
-
book = Book.new(:pages => [Page.new(:number => 1)])
|
377
|
-
book.pages = [Page.new(:number => 2)]
|
378
|
-
expect(book.changes[:pages]).to eq(book.pages_change)
|
379
|
-
end
|
380
|
-
|
381
|
-
it "does not include unchanged document arrays" do
|
382
|
-
book = Book.new(:pages => [Page.new(:number => 1)])
|
383
|
-
expect(book.changes).not_to have_key :pages
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
describe "after save" do
|
388
|
-
before :each do
|
389
|
-
book = Book.json_create(:_id => "1", :title => "A", :cover => {:color => "red"}, :pages => [{:_id => "p1", :number => 1}, {:_id => "p2", :number => 2}])
|
390
|
-
@couchrest_db = double('database', :info => nil, :save_doc => {}, :get => book)
|
391
|
-
@db = CouchPotato::Database.new(@couchrest_db)
|
392
|
-
@book = @db.load_document "1"
|
393
|
-
end
|
394
|
-
|
395
|
-
it "should reset all attributes to not dirty" do
|
396
|
-
@book.title = "B"
|
397
|
-
@book.cover.color = "blue"
|
398
|
-
@db.save! @book
|
399
|
-
expect(@book).not_to be_dirty
|
400
|
-
expect(@book.cover).not_to be_dirty
|
401
|
-
end
|
402
|
-
|
403
|
-
it "should reset all elements in a document array" do
|
404
|
-
@book.pages.each(&:is_dirty)
|
405
|
-
@db.save! @book
|
406
|
-
expect(@book).not_to be_dirty
|
407
|
-
@book.pages.each do |page|
|
408
|
-
expect(page).not_to be_dirty
|
409
|
-
end
|
410
|
-
end
|
411
|
-
|
412
|
-
it "should reset a forced dirty state" do
|
413
|
-
@book.is_dirty
|
414
|
-
@db.save! @book
|
415
|
-
expect(@book).not_to be_dirty
|
416
|
-
end
|
417
|
-
|
418
|
-
it "clears old values" do
|
419
|
-
@book.cover.color = "blue"
|
420
|
-
@db.save! @book
|
421
|
-
expect(@book.cover_was).to be_nil
|
422
|
-
expect(@book.cover_change).to be_nil
|
423
|
-
end
|
424
|
-
end
|
425
|
-
|
426
|
-
describe "on inherited models" do
|
427
|
-
it "still uses deep dirty tracking" do
|
428
|
-
book = TextBook.new(:pages => [Page.new(:number => 1)])
|
429
|
-
book.pages[0].number = 2
|
430
|
-
expect(book).to be_pages_changed
|
431
|
-
expect(book).to be_changed
|
432
|
-
end
|
433
|
-
end
|
434
|
-
end
|