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