espinita 0.0.8 → 0.0.9
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 +4 -4
- data/README.md +46 -1
- data/lib/espinita/auditor_behavior.rb +75 -3
- data/lib/espinita/version.rb +1 -1
- data/spec/dummy/log/test.log +422 -0
- data/spec/models/models/general_model_spec.rb +219 -3
- data/spec/spec_helper.rb +2 -0
- metadata +44 -30
@@ -20,14 +20,14 @@ describe GeneralModel do
|
|
20
20
|
|
21
21
|
it "general auditable only method" do
|
22
22
|
general_model.auditable only: [:name]
|
23
|
-
expect(general_model.
|
24
|
-
expect(general_model.
|
23
|
+
expect(general_model.permitted_columns).to include("name")
|
24
|
+
expect(general_model.permitted_columns.size).to eql 1
|
25
25
|
end
|
26
26
|
|
27
27
|
it "general auditable except method" do
|
28
28
|
general_model.auditable except: [:name]
|
29
29
|
expect(general_model.excluded_cols).to include("name")
|
30
|
-
expect(general_model.
|
30
|
+
expect(general_model.permitted_columns).not_to include("name")
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -217,4 +217,220 @@ describe GeneralModel do
|
|
217
217
|
end
|
218
218
|
end
|
219
219
|
|
220
|
+
context "history_from_audits_for" do
|
221
|
+
before do
|
222
|
+
Timecop.freeze(Time.now.localtime)
|
223
|
+
end
|
224
|
+
|
225
|
+
after do
|
226
|
+
Timecop.return
|
227
|
+
end
|
228
|
+
|
229
|
+
let!(:later){ Time.now.localtime + 10.days }
|
230
|
+
let!(:even_later){ Time.now.localtime + 1.year }
|
231
|
+
|
232
|
+
let!(:general_model) do
|
233
|
+
[:create, :update, :destroy].each do |c|
|
234
|
+
GeneralModel.reset_callbacks(c)
|
235
|
+
end
|
236
|
+
GeneralModel.auditable on: [:update]
|
237
|
+
FactoryGirl.create(:general_model)
|
238
|
+
end
|
239
|
+
|
240
|
+
let!(:updated_model) do
|
241
|
+
general_model.update_attributes(name: "Foo", audit_comment: "Some comment" )
|
242
|
+
general_model
|
243
|
+
end
|
244
|
+
|
245
|
+
context "given a single column as an argument" do
|
246
|
+
|
247
|
+
it "should accept a symbol column name" do
|
248
|
+
expect(updated_model.history_from_audits_for(:name)).to eq([
|
249
|
+
{changes: {name:"Foo"}, changed_at: Time.now.localtime}
|
250
|
+
])
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should accept a string column name" do
|
254
|
+
expect(updated_model.history_from_audits_for("name")).to eq([
|
255
|
+
{changes: {name:"Foo"}, changed_at: Time.now.localtime}
|
256
|
+
])
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should handle multiple audits" do
|
260
|
+
Timecop.freeze(later) do
|
261
|
+
updated_model.update_attributes(name: "Baz", audit_comment: "Some comment" )
|
262
|
+
end
|
263
|
+
Timecop.freeze(even_later) do
|
264
|
+
updated_model.update_attributes(name: "Arglebargle", audit_comment: "Some comment" )
|
265
|
+
end
|
266
|
+
expect(updated_model.history_from_audits_for(:name)).to eq(
|
267
|
+
[
|
268
|
+
{changes: {name:"Arglebargle"}, changed_at: even_later},
|
269
|
+
{changes: {name:"Baz"}, changed_at: later},
|
270
|
+
{changes: {name:"Foo"}, changed_at: Time.now.localtime},
|
271
|
+
]
|
272
|
+
)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
context "for multiple specified columns" do
|
277
|
+
|
278
|
+
before do
|
279
|
+
Timecop.freeze(later) do
|
280
|
+
updated_model.update_attributes(name: "Baz", position: 42, audit_comment: "Some comment" )
|
281
|
+
end
|
282
|
+
Timecop.freeze(even_later) do
|
283
|
+
updated_model.update_attributes(name: "Arglebargle", settings: "Waffles", audit_comment: "Some comment" )
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
it "should return history including each specified column" do
|
288
|
+
expect(updated_model.history_from_audits_for([:name, :settings])).to eq(
|
289
|
+
[
|
290
|
+
{changes: {name: "Arglebargle", settings: "Waffles"}, changed_at: even_later},
|
291
|
+
{changes: {name: "Baz"}, changed_at: later},
|
292
|
+
{changes: {name: "Foo"}, changed_at: Time.now.localtime},
|
293
|
+
]
|
294
|
+
)
|
295
|
+
expect(updated_model.history_from_audits_for([:position, :settings])).to eq(
|
296
|
+
[
|
297
|
+
{changes: {settings: "Waffles"}, changed_at: even_later},
|
298
|
+
{changes: {position: 42}, changed_at: later},
|
299
|
+
]
|
300
|
+
)
|
301
|
+
end
|
302
|
+
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should raise an error if the requested column does not exist" do
|
306
|
+
expect{ updated_model.history_from_audits_for(:waffles) }.to raise_error(ArgumentError)
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
|
311
|
+
context "restore_attributes!" do
|
312
|
+
|
313
|
+
let!(:general_model) do
|
314
|
+
[:create, :update, :destroy].each do |c|
|
315
|
+
GeneralModel.reset_callbacks(c)
|
316
|
+
end
|
317
|
+
GeneralModel.auditable on: [:update]
|
318
|
+
FactoryGirl.create(:general_model)
|
319
|
+
end
|
320
|
+
|
321
|
+
let!(:historical_model) do
|
322
|
+
recent = Time.now.localtime - 10.days
|
323
|
+
less_recent = Time.now.localtime - 50.days
|
324
|
+
ancient = Time.now.localtime - 1.year
|
325
|
+
# these timed changes must be made in reverse chrono order to make the audits work for testing
|
326
|
+
Timecop.freeze(ancient) do
|
327
|
+
general_model.update_attributes(name: "Walrus", position: 1, audit_comment: "Some comment" )
|
328
|
+
end
|
329
|
+
Timecop.freeze(less_recent) do
|
330
|
+
general_model.update_attributes(name: "Arglebargle", settings: "IHOP", position: 2, audit_comment: "Some comment" )
|
331
|
+
end
|
332
|
+
Timecop.freeze(recent) do
|
333
|
+
general_model.update_attributes(name: "Baz", settings: "", position: nil, audit_comment: "Some comment" )
|
334
|
+
end
|
335
|
+
general_model
|
336
|
+
end
|
337
|
+
|
338
|
+
context "given valid arguments" do
|
339
|
+
|
340
|
+
it "should restore a single property from a datetime" do
|
341
|
+
result = historical_model.restore_attributes!(:name, DateTime.now - 12.days)
|
342
|
+
|
343
|
+
expect(result).to be(true)
|
344
|
+
expect(historical_model.name).to eq("Arglebargle")
|
345
|
+
end
|
346
|
+
|
347
|
+
it "should restore multiple attributes from a datetime" do
|
348
|
+
result = historical_model.restore_attributes!([:name, :settings], DateTime.now - 57.days)
|
349
|
+
|
350
|
+
expect(result).to be(true)
|
351
|
+
expect(historical_model.name).to eq("Walrus")
|
352
|
+
expect(historical_model.settings).to eq("MyText")
|
353
|
+
end
|
354
|
+
|
355
|
+
it "should return false when no restoration change is performed" do
|
356
|
+
original = historical_model
|
357
|
+
result = historical_model.restore_attributes!(:settings, DateTime.now + 5.days)
|
358
|
+
|
359
|
+
expect(original).to match(historical_model)
|
360
|
+
expect(result).to be(false)
|
361
|
+
end
|
362
|
+
|
363
|
+
end
|
364
|
+
|
365
|
+
context "given invalid arguments" do
|
366
|
+
|
367
|
+
it "should raise when called with no arguments" do
|
368
|
+
expect{ historical_model.restore_attributes! }.to raise_error(ArgumentError)
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
372
|
+
|
373
|
+
end
|
374
|
+
|
375
|
+
context "restore_to_audit" do
|
376
|
+
|
377
|
+
let!(:general_model) do
|
378
|
+
[:create, :update, :destroy].each do |c|
|
379
|
+
GeneralModel.reset_callbacks(c)
|
380
|
+
end
|
381
|
+
GeneralModel.auditable on: [:update]
|
382
|
+
FactoryGirl.create(:general_model)
|
383
|
+
end
|
384
|
+
|
385
|
+
context "given valid arguments" do
|
386
|
+
it "should restore when given an audit id" do
|
387
|
+
original_model = general_model.dup
|
388
|
+
|
389
|
+
general_model.update_attributes(name: "Ringo", settings: "Walrus")
|
390
|
+
general_model.update_attributes(settings: "Walrus", position: 7)
|
391
|
+
general_model.update_attributes(name: "Ringo", position: 3)
|
392
|
+
general_model.restore_to_audit(general_model.audits.first.id)
|
393
|
+
|
394
|
+
expect(general_model.name).to eq(original_model.name)
|
395
|
+
expect(general_model.settings).to eq(original_model.settings)
|
396
|
+
end
|
397
|
+
|
398
|
+
it "should restore when given an audit record" do
|
399
|
+
original_model = general_model.dup
|
400
|
+
|
401
|
+
general_model.update_attributes(name: "Ringo", settings: "Walrus")
|
402
|
+
general_model.update_attributes(settings: "Walrus", position: 7)
|
403
|
+
general_model.update_attributes(name: "Ringo", position: 3)
|
404
|
+
general_model.restore_to_audit(general_model.audits.first.id)
|
405
|
+
|
406
|
+
expect(general_model.name).to eq(original_model.name)
|
407
|
+
expect(general_model.settings).to eq(original_model.settings)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
context "given invalid arguments" do
|
412
|
+
|
413
|
+
let!(:other_model) do
|
414
|
+
other_model = general_model.dup
|
415
|
+
other_model.save
|
416
|
+
other_model.update_attributes(name: "Foo", settings: "Bar")
|
417
|
+
other_model
|
418
|
+
end
|
419
|
+
|
420
|
+
it "should raise when called with a valid audit id for a different model" do
|
421
|
+
expect{ general_model.restore_to_audit(other_model.audits.first.id) }.to raise_error
|
422
|
+
end
|
423
|
+
|
424
|
+
it "should raise when called with a valid audit record for a different model" do
|
425
|
+
expect{ general_model.restore_to_audit(other_model.audits.first) }.to raise_error
|
426
|
+
end
|
427
|
+
|
428
|
+
it "should raise when called with an invalid audit id" do
|
429
|
+
expect{ general_model.restore_to_audit(999999999) }.to raise_error
|
430
|
+
end
|
431
|
+
|
432
|
+
end
|
433
|
+
|
434
|
+
end
|
435
|
+
|
220
436
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -6,12 +6,14 @@ ENV["RAILS_ENV"] ||= 'test'
|
|
6
6
|
require File.expand_path("../../spec/dummy/config/environment", __FILE__)
|
7
7
|
require 'rspec/rails'
|
8
8
|
require 'rspec/autorun'
|
9
|
+
require 'rspec/collection_matchers'
|
9
10
|
|
10
11
|
require "factory_girl_rails"
|
11
12
|
require "database_cleaner"
|
12
13
|
require 'capybara'
|
13
14
|
require 'capybara/rspec'
|
14
15
|
require 'shoulda/matchers/integrations/rspec'
|
16
|
+
require 'timecop'
|
15
17
|
|
16
18
|
require "espinita"
|
17
19
|
require 'support/schema'
|
metadata
CHANGED
@@ -1,111 +1,111 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: espinita
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Michelson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '4.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '4.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: request_store
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: sqlite3
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec-rails
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - ~>
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '3.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - ~>
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: factory_girl
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: factory_girl_rails
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rspec-collection_matchers
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
@@ -126,28 +126,42 @@ dependencies:
|
|
126
126
|
name: database_cleaner
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- -
|
129
|
+
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- -
|
136
|
+
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: capybara
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
|
-
- -
|
143
|
+
- - ">="
|
144
144
|
- !ruby/object:Gem::Version
|
145
145
|
version: '0'
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- -
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: timecop
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
151
165
|
- !ruby/object:Gem::Version
|
152
166
|
version: '0'
|
153
167
|
description: Audit activerecord models like a boss
|
@@ -157,21 +171,23 @@ executables: []
|
|
157
171
|
extensions: []
|
158
172
|
extra_rdoc_files: []
|
159
173
|
files:
|
174
|
+
- MIT-LICENSE
|
175
|
+
- README.md
|
176
|
+
- Rakefile
|
160
177
|
- app/models/espinita/audit.rb
|
161
178
|
- config/database.yml
|
162
179
|
- config/routes.rb
|
163
180
|
- db/migrate/20131029200927_create_auditable_audits.rb
|
181
|
+
- lib/espinita.rb
|
164
182
|
- lib/espinita/auditor.rb
|
165
183
|
- lib/espinita/auditor_behavior.rb
|
166
184
|
- lib/espinita/auditor_request.rb
|
167
185
|
- lib/espinita/engine.rb
|
168
186
|
- lib/espinita/version.rb
|
169
|
-
- lib/espinita.rb
|
170
187
|
- lib/tasks/espinita_tasks.rake
|
171
|
-
- MIT-LICENSE
|
172
|
-
- Rakefile
|
173
|
-
- README.md
|
174
188
|
- spec/controllers/audits_controller_spec.rb
|
189
|
+
- spec/dummy/README.rdoc
|
190
|
+
- spec/dummy/Rakefile
|
175
191
|
- spec/dummy/app/assets/javascripts/application.js
|
176
192
|
- spec/dummy/app/assets/javascripts/general_controller.js
|
177
193
|
- spec/dummy/app/assets/stylesheets/application.css
|
@@ -186,6 +202,7 @@ files:
|
|
186
202
|
- spec/dummy/bin/bundle
|
187
203
|
- spec/dummy/bin/rails
|
188
204
|
- spec/dummy/bin/rake
|
205
|
+
- spec/dummy/config.ru
|
189
206
|
- spec/dummy/config/application.rb
|
190
207
|
- spec/dummy/config/boot.rb
|
191
208
|
- spec/dummy/config/database.yml
|
@@ -202,7 +219,6 @@ files:
|
|
202
219
|
- spec/dummy/config/initializers/wrap_parameters.rb
|
203
220
|
- spec/dummy/config/locales/en.yml
|
204
221
|
- spec/dummy/config/routes.rb
|
205
|
-
- spec/dummy/config.ru
|
206
222
|
- spec/dummy/db/migrate/20131029211126_create_general_models.rb
|
207
223
|
- spec/dummy/db/migrate/20131030014901_create_users.rb
|
208
224
|
- spec/dummy/db/schema.rb
|
@@ -211,8 +227,6 @@ files:
|
|
211
227
|
- spec/dummy/public/422.html
|
212
228
|
- spec/dummy/public/500.html
|
213
229
|
- spec/dummy/public/favicon.ico
|
214
|
-
- spec/dummy/Rakefile
|
215
|
-
- spec/dummy/README.rdoc
|
216
230
|
- spec/factories/auditable_audits.rb
|
217
231
|
- spec/factories/general_models.rb
|
218
232
|
- spec/factories/users.rb
|
@@ -231,17 +245,17 @@ require_paths:
|
|
231
245
|
- lib
|
232
246
|
required_ruby_version: !ruby/object:Gem::Requirement
|
233
247
|
requirements:
|
234
|
-
- -
|
248
|
+
- - ">="
|
235
249
|
- !ruby/object:Gem::Version
|
236
250
|
version: '0'
|
237
251
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
238
252
|
requirements:
|
239
|
-
- -
|
253
|
+
- - ">="
|
240
254
|
- !ruby/object:Gem::Version
|
241
255
|
version: '0'
|
242
256
|
requirements: []
|
243
257
|
rubyforge_project:
|
244
|
-
rubygems_version: 2.
|
258
|
+
rubygems_version: 2.2.2
|
245
259
|
signing_key:
|
246
260
|
specification_version: 4
|
247
261
|
summary: Auditable Rails Engine.
|