mongoid_archival 0.1.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.
@@ -0,0 +1,5 @@
1
+ class Sport
2
+ include Mongoid::Document
3
+ include Mongoid::Archivable
4
+ include Mongoid::Archivable::Protected
5
+ end
@@ -0,0 +1,6 @@
1
+ class Tag
2
+ include Mongoid::Document
3
+ field :text, type: String
4
+ has_and_belongs_to_many :archivable_posts
5
+ has_and_belongs_to_many :related, class_name: 'Tag', inverse_of: :related
6
+ end
@@ -0,0 +1,4 @@
1
+ class Title
2
+ include Mongoid::Document
3
+ belongs_to :archivable_post
4
+ end
@@ -0,0 +1,341 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'Mongoid::Archivable#archive' do
4
+ describe '#archive' do
5
+
6
+ context 'when the document is a root' do
7
+
8
+ let(:post) do
9
+ ArchivablePost.create(title: 'testing')
10
+ end
11
+
12
+ before do
13
+ post.archive
14
+ end
15
+
16
+ let(:raw) do
17
+ ArchivablePost.collection.find(_id: post.id).first
18
+ end
19
+
20
+ it 'archives the document' do
21
+ expect(raw['archived_at']).to be_within(1).of(Time.now)
22
+ end
23
+
24
+ it 'is still marked as persisted' do
25
+ expect(post.persisted?).to eq(true)
26
+ end
27
+
28
+ it 'does not return the document in a find' do
29
+ expect(ArchivablePost.find(post.id)).to eq post
30
+ end
31
+
32
+ it 'executes the before archive callbacks' do
33
+ expect(post.before_archive_called).to be_truthy
34
+ end
35
+
36
+ it 'executes the after archive callbacks' do
37
+ expect(post.after_archive_called).to be_truthy
38
+ end
39
+ end
40
+
41
+ # context 'when the document is embedded' do
42
+ #
43
+ # let(:person) do
44
+ # Person.create
45
+ # end
46
+ #
47
+ # let(:phone) do
48
+ # person.archivable_phones.create(number: '911')
49
+ # end
50
+ #
51
+ # before do
52
+ # phone.archive
53
+ # end
54
+ #
55
+ # let(:raw) do
56
+ # Person.collection.find(_id: person.id).first
57
+ # end
58
+ #
59
+ # it 'archives the document' do
60
+ # expect(raw['archivable_phones'].first['archived_at']).to be_within(1).of(Time.now)
61
+ # end
62
+ #
63
+ # it 'does not return the document in a find' do
64
+ # expect {
65
+ # person.archivable_phones.find(phone.id)
66
+ # }.to raise_error(Mongoid::Errors::DocumentNotFound)
67
+ # end
68
+ #
69
+ # it 'does not include the document in the relation' do
70
+ # expect(person.archivable_phones.scoped).to be_empty
71
+ # end
72
+ #
73
+ # it 'executes the before archive callbacks' do
74
+ # expect(phone.before_archive_called).to be_truthy
75
+ # end
76
+ #
77
+ # it 'executes the after archive callbacks' do
78
+ # expect(phone.after_archive_called).to be_truthy
79
+ # end
80
+ # end
81
+
82
+ context 'when the document has a dependent: :archive relation' do
83
+
84
+ let(:post) do
85
+ ArchivablePost.create(title: 'test')
86
+ end
87
+
88
+ let!(:fish) do
89
+ post.fish = Fish.create
90
+ end
91
+
92
+ before do
93
+ post.archive
94
+ end
95
+
96
+ it 'cascades the dependent option' do
97
+ expect(fish.reload.archived_at).to be_a(Time)
98
+ end
99
+ end
100
+
101
+ context 'when the document has a dependent: :destroy relation' do
102
+
103
+ let(:post) do
104
+ ArchivablePost.create(title: 'test')
105
+ end
106
+
107
+ let!(:author) do
108
+ post.authors.create(name: 'poe')
109
+ end
110
+
111
+ before do
112
+ post.archive
113
+ end
114
+
115
+ it 'ignores dependent :destroy option' do
116
+ expect(author.reload).to be_a(Author)
117
+ end
118
+ end
119
+
120
+ context 'when the document has a dependent: :restrict relation' do
121
+
122
+ let(:post) do
123
+ ArchivablePost.create(title: 'test')
124
+ end
125
+
126
+ let!(:title) do
127
+ post.titles.create
128
+ end
129
+
130
+ before do
131
+ begin
132
+ post.archive
133
+ rescue Mongoid::Errors::DeleteRestriction
134
+ end
135
+ end
136
+
137
+ it 'does not archive the document' do
138
+ expect(post).not_to be_archived
139
+ end
140
+ end
141
+ end
142
+
143
+ describe '#archive_without_callbacks' do
144
+
145
+ context 'when the document is a root' do
146
+
147
+ let(:post) do
148
+ ArchivablePost.create(title: 'testing')
149
+ end
150
+
151
+ before do
152
+ post.archive_without_callbacks
153
+ end
154
+
155
+ let(:raw) do
156
+ ArchivablePost.collection.find(_id: post.id).first
157
+ end
158
+
159
+ it 'archives the document' do
160
+ expect(raw['archived_at']).to be_within(1).of(Time.now)
161
+ end
162
+
163
+ it 'does not return the document in a find' do
164
+ expect { ArchivablePost.current.find(post.id) }.to raise_error(Mongoid::Errors::DocumentNotFound)
165
+ expect { ArchivablePost.find(post.id) }.to_not raise_error(Mongoid::Errors::DocumentNotFound)
166
+ end
167
+ end
168
+
169
+ # context 'when the document is embedded' do
170
+ #
171
+ # let(:person) do
172
+ # Person.create
173
+ # end
174
+ #
175
+ # let(:phone) do
176
+ # person.archivable_phones.create(number: '911')
177
+ # end
178
+ #
179
+ # before do
180
+ # phone.archive_without_callbacks
181
+ # end
182
+ #
183
+ # let(:raw) do
184
+ # Person.collection.find(_id: person.id).first
185
+ # end
186
+ #
187
+ # it 'archives the document' do
188
+ # expect(raw['archivable_phones'].first['archived_at']).to be_within(1).of(Time.now)
189
+ # end
190
+ #
191
+ # it 'does not return the document in a find' do
192
+ # expect {
193
+ # person.archivable_phones.find(phone.id)
194
+ # }.to raise_error(Mongoid::Errors::DocumentNotFound)
195
+ # end
196
+ #
197
+ # it 'does not include the document in the relation' do
198
+ # expect(person.archivable_phones.scoped).to be_empty
199
+ # end
200
+ # end
201
+
202
+ context 'when the document has a dependent relation' do
203
+
204
+ let(:post) do
205
+ ArchivablePost.create(title: 'test')
206
+ end
207
+
208
+ let!(:author) do
209
+ post.authors.create(name: 'poe')
210
+ end
211
+
212
+ before do
213
+ post.archive_without_callbacks
214
+ end
215
+
216
+ it 'does not cascade the dependent option' do
217
+ expect {
218
+ author.reload
219
+ }.to_not raise_error(Mongoid::Errors::DocumentNotFound)
220
+ end
221
+ end
222
+
223
+ context 'when the document has a dependent: :restrict relation' do
224
+
225
+ let(:post) do
226
+ ArchivablePost.create(title: 'test')
227
+ end
228
+
229
+ let!(:title) do
230
+ post.titles.create
231
+ end
232
+
233
+ before do
234
+ begin
235
+ post.archive_without_callbacks
236
+ rescue Mongoid::Errors::DeleteRestriction
237
+ end
238
+ end
239
+
240
+ it 'ignores restrict and archives the document' do
241
+ expect(post).to be_archived
242
+ end
243
+ end
244
+ end
245
+
246
+ describe '#archived?' do
247
+
248
+ context 'when the document is a root' do
249
+
250
+ let(:post) do
251
+ ArchivablePost.create(title: 'testing')
252
+ end
253
+
254
+ context 'when the document is archived' do
255
+
256
+ before do
257
+ post.archive
258
+ end
259
+
260
+ it 'returns true' do
261
+ expect(post).to be_archived
262
+ end
263
+
264
+ it 'returns true for archived scope document' do
265
+ expect(ArchivablePost.archived.last).to be_archived
266
+ end
267
+ end
268
+ end
269
+
270
+ context 'when the document is embedded' do
271
+
272
+ let(:person) do
273
+ Person.create
274
+ end
275
+
276
+ let(:phone) do
277
+ person.archivable_phones.create(number: '911')
278
+ end
279
+
280
+ context 'when the document is hard deleted' do
281
+
282
+ before do
283
+ phone.destroy!
284
+ end
285
+
286
+ it 'returns true' do
287
+ expect(phone).to be_destroyed
288
+ end
289
+ end
290
+
291
+ context 'when the document is archived' do
292
+
293
+ before do
294
+ phone.archive
295
+ end
296
+
297
+ it 'returns true' do
298
+ expect(phone).to_not be_destroyed
299
+ expect(phone).to be_archived
300
+ end
301
+ end
302
+
303
+ context 'when the document has non-dependent relation' do
304
+ let(:post) do
305
+ ArchivablePost.create(title: 'test')
306
+ end
307
+
308
+ let!(:tag) do
309
+ post.tags.create(text: 'tagie')
310
+ end
311
+
312
+ before do
313
+ post.archive
314
+ end
315
+
316
+ it 'does not cascades the dependent option' do
317
+ expect(tag.reload).to eq(tag)
318
+ end
319
+ end
320
+ end
321
+ end
322
+
323
+ describe '#set' do
324
+
325
+ let!(:post) do
326
+ ArchivablePost.create
327
+ end
328
+
329
+ let(:time) do
330
+ 20.days.ago
331
+ end
332
+
333
+ let!(:set) do
334
+ post.set(archived_at: time)
335
+ end
336
+
337
+ it 'persists the change' do
338
+ expect(post.reload.archived_at).to be_within(1).of(time)
339
+ end
340
+ end
341
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Mongoid::Archivable::Configuration do
4
+ context 'configuring the archived_field setting' do
5
+ before do
6
+ Mongoid::Archivable.configure do |c|
7
+ c.archived_field = :my_field_name
8
+ end
9
+ end
10
+
11
+ describe '.configure' do
12
+ before do
13
+ class ArchivableConfigured
14
+ include Mongoid::Document
15
+ include Mongoid::Archivable
16
+ end
17
+ end
18
+
19
+ it 'allows custom setting of the archived_field' do
20
+ archivable_configured = ArchivableConfigured.new
21
+ expect(archivable_configured.attribute_names).to include('my_field_name')
22
+ end
23
+
24
+ after(:each) do
25
+ Mongoid::Archivable.reset
26
+ end
27
+ end
28
+
29
+ describe '.reset' do
30
+ before do
31
+ Mongoid::Archivable.reset
32
+
33
+ # the configuration gets set at include time
34
+ # so you need to reset before defining a new class
35
+ class ArchivableConfiguredReset
36
+ include Mongoid::Document
37
+ include Mongoid::Archivable
38
+ end
39
+ end
40
+
41
+ it 'restores the archived_field to the default setting' do
42
+ archivable_configured = ArchivableConfiguredReset.new
43
+ expect(archivable_configured.attribute_names).to include('archived_at')
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '#archived_field' do
49
+ it 'initializes with default value set to :archived_at' do
50
+ expect(Mongoid::Archivable::Configuration.new.archived_field).to eq(:archived_at)
51
+ end
52
+
53
+ it 'can be updated' do
54
+ config = Mongoid::Archivable::Configuration.new
55
+ config.archived_field = :my_field_name
56
+ expect(config.archived_field).to eq(:my_field_name)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'Mongoid::Archivable.archivable?' do
4
+
5
+ describe '.archivable?' do
6
+
7
+ context 'when Mongoid::Archivable is included' do
8
+ subject { ArchivablePost }
9
+ it 'returns true' do
10
+ expect(subject.archivable?).to eq true
11
+ end
12
+ end
13
+
14
+ context 'when Mongoid::Archivable not included' do
15
+ subject { Author }
16
+ it 'returns true' do
17
+ expect(subject.respond_to?(:archivable?)).to eq false
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,164 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Mongoid::Attributes::Nested do
4
+ describe '##{name}_attributes=' do
5
+ context 'when the parent document is new' do
6
+ context 'when the relation is an embeds many' do
7
+ context 'when ids are passed' do
8
+
9
+ let(:person) do
10
+ Person.create
11
+ end
12
+
13
+ let(:address_one) do
14
+ Address.new(street: 'Unter den Linden')
15
+ end
16
+
17
+ let(:address_two) do
18
+ Address.new(street: 'Kurfeurstendamm')
19
+ end
20
+
21
+ let(:phone_one) do
22
+ ArchivablePhone.new(number: '1')
23
+ end
24
+
25
+ let(:phone_two) do
26
+ ArchivablePhone.new(number: '2')
27
+ end
28
+
29
+ before do
30
+ person.addresses << [ address_one, address_two ]
31
+ end
32
+
33
+ # context 'when archive attributes are passed' do
34
+ # context 'when the ids match' do
35
+ # context 'when allow_archive is true' do
36
+ # context 'when the child is archivable' do
37
+ #
38
+ # before(:all) do
39
+ # Person.send(:undef_method, :archivable_phones_attributes=)
40
+ # Person.accepts_nested_attributes_for :archivable_phones,
41
+ # allow_archive: true
42
+ # end
43
+ #
44
+ # after(:all) do
45
+ # Person.send(:undef_method, :archivable_phones_attributes=)
46
+ # Person.accepts_nested_attributes_for :archivable_phones
47
+ # end
48
+ #
49
+ # [ 1, '1', true, 'true' ].each do |truth|
50
+ #
51
+ # context 'when passed a #{truth} with archive' do
52
+ # context 'when the parent is persisted' do
53
+ #
54
+ # let!(:persisted) do
55
+ # Person.create do |p|
56
+ # p.archivable_phones << [ phone_one, phone_two ]
57
+ # end
58
+ # end
59
+ #
60
+ # context 'when setting, pulling, and pushing in one op' do
61
+ #
62
+ # before do
63
+ # persisted.archivable_phones_attributes =
64
+ # {
65
+ # 'bar' => { 'id' => phone_one.id, '_archive' => truth },
66
+ # 'foo' => { 'id' => phone_two.id, 'number' => '3' },
67
+ # 'baz' => { 'number' => '4' }
68
+ # }
69
+ # end
70
+ #
71
+ # it 'removes the first document from the relation' do
72
+ # expect(persisted.archivable_phones.size).to eq(2)
73
+ # end
74
+ #
75
+ # it 'does not delete the unmarked document' do
76
+ # expect(persisted.archivable_phones.first.number).to eq('3')
77
+ # end
78
+ #
79
+ # it 'adds the new document to the relation' do
80
+ # expect(persisted.archivable_phones.last.number).to eq('4')
81
+ # end
82
+ #
83
+ # it 'has the proper persisted count' do
84
+ # expect(persisted.archivable_phones.count).to eq(1)
85
+ # end
86
+ #
87
+ # it 'archives the removed document' do
88
+ # expect(phone_one).to be_archiveed
89
+ # end
90
+ #
91
+ # context 'when saving the parent' do
92
+ #
93
+ # before do
94
+ # persisted.save
95
+ # end
96
+ #
97
+ # it 'deletes the marked document from the relation' do
98
+ # expect(persisted.reload.archivable_phones.count).to eq(2)
99
+ # end
100
+ #
101
+ # it 'does not delete the unmarked document' do
102
+ # expect(persisted.reload.archivable_phones.first.number).to eq('3')
103
+ # end
104
+ #
105
+ # it 'persists the new document to the relation' do
106
+ # expect(persisted.reload.archivable_phones.last.number).to eq('4')
107
+ # end
108
+ # end
109
+ # end
110
+ # end
111
+ # end
112
+ # end
113
+ # end
114
+ #
115
+ # context 'when the child has defaults' do
116
+ #
117
+ # before(:all) do
118
+ # Person.accepts_nested_attributes_for :appointments, allow_archive: true
119
+ # end
120
+ #
121
+ # after(:all) do
122
+ # Person.send(:undef_method, :appointments_attributes=)
123
+ # end
124
+ # context 'when the parent is persisted' do
125
+ # context 'when the child returns false in a before callback' do
126
+ # context 'when the child is archivable' do
127
+ #
128
+ # before(:all) do
129
+ # Person.accepts_nested_attributes_for :archivable_phones, allow_archive: true
130
+ # end
131
+ #
132
+ # after(:all) do
133
+ # Person.send(:undef_method, :archivable_phones=)
134
+ # Person.accepts_nested_attributes_for :archivable_phones
135
+ # end
136
+ #
137
+ # let!(:persisted) do
138
+ # Person.create(age: 42)
139
+ # end
140
+ #
141
+ # let!(:phone) do
142
+ # persisted.archivable_phones.create
143
+ # end
144
+ #
145
+ # before do
146
+ # persisted.archivable_phones_attributes =
147
+ # { 'foo' => { 'id' => phone.id, 'number' => 42, '_archive' => true }}
148
+ # end
149
+ #
150
+ # it 'does not archive the child' do
151
+ # expect(persisted.reload.archivable_phones).not_to be_empty
152
+ # end
153
+ # end
154
+ # end
155
+ # end
156
+ # end
157
+ # end
158
+ # end
159
+ # end
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end