mongoid_archival 0.1.0

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