auditing 0.0.2
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.
- data/.bundle/config +2 -0
- data/.document +5 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +38 -0
- data/LICENSE +20 -0
- data/README.rdoc +64 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/auditing.gemspec +64 -0
- data/lib/auditing/auditing.rb +51 -0
- data/lib/auditing/auditor.rb +25 -0
- data/lib/auditing.rb +5 -0
- data/spec/auditing/auditing_spec.rb +131 -0
- data/spec/auditing/auditor_spec.rb +43 -0
- data/spec/schema.rb +24 -0
- data/spec/spec_helper.rb +24 -0
- metadata +99 -0
data/.bundle/config
ADDED
data/.document
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (3.0.0.rc2)
|
5
|
+
activesupport (= 3.0.0.rc2)
|
6
|
+
builder (~> 2.1.2)
|
7
|
+
i18n (~> 0.4.1)
|
8
|
+
activerecord (3.0.0.rc2)
|
9
|
+
activemodel (= 3.0.0.rc2)
|
10
|
+
activesupport (= 3.0.0.rc2)
|
11
|
+
arel (~> 1.0.0.rc1)
|
12
|
+
tzinfo (~> 0.3.23)
|
13
|
+
activesupport (3.0.0.rc2)
|
14
|
+
arel (1.0.0.rc1)
|
15
|
+
activesupport (>= 3.0.0.beta)
|
16
|
+
builder (2.1.2)
|
17
|
+
diff-lcs (1.1.2)
|
18
|
+
i18n (0.4.1)
|
19
|
+
rspec (2.0.0.beta.20)
|
20
|
+
rspec-core (= 2.0.0.beta.20)
|
21
|
+
rspec-expectations (= 2.0.0.beta.20)
|
22
|
+
rspec-mocks (= 2.0.0.beta.20)
|
23
|
+
rspec-core (2.0.0.beta.20)
|
24
|
+
rspec-expectations (2.0.0.beta.20)
|
25
|
+
diff-lcs (>= 1.1.2)
|
26
|
+
rspec-mocks (2.0.0.beta.20)
|
27
|
+
rspec-rails (2.0.0.beta.20)
|
28
|
+
rspec (= 2.0.0.beta.20)
|
29
|
+
sqlite3-ruby (1.3.1)
|
30
|
+
tzinfo (0.3.23)
|
31
|
+
|
32
|
+
PLATFORMS
|
33
|
+
ruby
|
34
|
+
|
35
|
+
DEPENDENCIES
|
36
|
+
activerecord (~> 3.0.0.rc2)
|
37
|
+
rspec-rails (~> 2.0.0.beta.20)
|
38
|
+
sqlite3-ruby (~> 1.3)
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Brad
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
= auditing (currently in development, no gem has been created yet)
|
2
|
+
|
3
|
+
Auditing is a simple way to track and rollback changes to a record.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
gem install auditing # NOTE: gem has not been created yet.
|
8
|
+
|
9
|
+
You will have to supply a model named Audit in your rails application with the following migration
|
10
|
+
|
11
|
+
create_table :audits, :force => true do |t|
|
12
|
+
t.string :action
|
13
|
+
t.string :auditable_type
|
14
|
+
t.integer :auditable_id
|
15
|
+
t.string :association_type
|
16
|
+
t.integer :association_id
|
17
|
+
t.string :field_name
|
18
|
+
t.string :old_value
|
19
|
+
t.string :new_value
|
20
|
+
# t.integer :user_id
|
21
|
+
t.boolean :undoable, :default => true
|
22
|
+
t.timestamps
|
23
|
+
end
|
24
|
+
|
25
|
+
If you want to track the user, uncomment the t.integer :user_id above.
|
26
|
+
TODO: more to follow about tracking the user
|
27
|
+
|
28
|
+
class Audit < ActiveRecord::Base
|
29
|
+
include Auditing::Auditor
|
30
|
+
belongs_to :auditable, :polymorphic => true
|
31
|
+
belongs_to :association, :polymorphic => true
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
== Basic Usage
|
36
|
+
|
37
|
+
To add auditing to all attributes on a model, simply add auditing to the model.
|
38
|
+
|
39
|
+
class School < ActiveRecord::Base
|
40
|
+
auditing
|
41
|
+
end
|
42
|
+
|
43
|
+
If you want more control over which attributes are audited, you can define them
|
44
|
+
by supplying a fields hash
|
45
|
+
|
46
|
+
class School < ActiveRecord::Base
|
47
|
+
auditing :fields => [:name, :established_on]
|
48
|
+
end
|
49
|
+
|
50
|
+
Auditing will not track "id", "created_at", or "updated_at" by default
|
51
|
+
|
52
|
+
== Note on Patches/Pull Requests
|
53
|
+
|
54
|
+
* Fork the project.
|
55
|
+
* Make your feature addition or bug fix.
|
56
|
+
* Add tests for it. This is important so I don't break it in a
|
57
|
+
future version unintentionally.
|
58
|
+
* Commit, do not mess with rakefile, version, or history.
|
59
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
60
|
+
* Send me a pull request. Bonus points for topic branches.
|
61
|
+
|
62
|
+
== Copyright
|
63
|
+
|
64
|
+
Copyright (c) 2010 Brad Cantin. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "auditing"
|
8
|
+
gem.summary = %Q{A gem to keep track of audit hisory of a record}
|
9
|
+
gem.description = %Q{acts_as_versioned is good. This allows an attribute level rollback instead}
|
10
|
+
gem.email = "brad.cantin@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/bcantin/auditing"
|
12
|
+
gem.authors = ["Brad"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'spec/rake/spectask'
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
end
|
32
|
+
|
33
|
+
task :spec => :check_dependencies
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
+
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = "auditing #{version}"
|
43
|
+
rdoc.rdoc_files.include('README*')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.2
|
data/auditing.gemspec
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{auditing}
|
8
|
+
s.version = "0.0.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Brad"]
|
12
|
+
s.date = %q{2010-08-29}
|
13
|
+
s.description = %q{acts_as_versioned is good. This allows an attribute level rollback instead}
|
14
|
+
s.email = %q{brad.cantin@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".bundle/config",
|
21
|
+
".document",
|
22
|
+
".gitignore",
|
23
|
+
".rspec",
|
24
|
+
"Gemfile",
|
25
|
+
"Gemfile.lock",
|
26
|
+
"LICENSE",
|
27
|
+
"README.rdoc",
|
28
|
+
"Rakefile",
|
29
|
+
"VERSION",
|
30
|
+
"auditing.gemspec",
|
31
|
+
"lib/auditing.rb",
|
32
|
+
"lib/auditing/auditing.rb",
|
33
|
+
"lib/auditing/auditor.rb",
|
34
|
+
"spec/auditing/auditing_spec.rb",
|
35
|
+
"spec/auditing/auditor_spec.rb",
|
36
|
+
"spec/schema.rb",
|
37
|
+
"spec/spec_helper.rb"
|
38
|
+
]
|
39
|
+
s.homepage = %q{http://github.com/bcantin/auditing}
|
40
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
41
|
+
s.require_paths = ["lib"]
|
42
|
+
s.rubygems_version = %q{1.3.7}
|
43
|
+
s.summary = %q{A gem to keep track of audit hisory of a record}
|
44
|
+
s.test_files = [
|
45
|
+
"spec/auditing/auditing_spec.rb",
|
46
|
+
"spec/auditing/auditor_spec.rb",
|
47
|
+
"spec/schema.rb",
|
48
|
+
"spec/spec_helper.rb"
|
49
|
+
]
|
50
|
+
|
51
|
+
if s.respond_to? :specification_version then
|
52
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
53
|
+
s.specification_version = 3
|
54
|
+
|
55
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
56
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
57
|
+
else
|
58
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
59
|
+
end
|
60
|
+
else
|
61
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Auditing
|
2
|
+
|
3
|
+
# Auditing creates audit objects for a record.
|
4
|
+
#
|
5
|
+
# @examples
|
6
|
+
# class School < ActiveRecord::Base
|
7
|
+
# auditing
|
8
|
+
# end
|
9
|
+
# class School < ActiveRecord::Base
|
10
|
+
# auditing :fields => [:name, :established_on]
|
11
|
+
# end
|
12
|
+
def auditing(opts={})
|
13
|
+
include InstanceMethods
|
14
|
+
class_inheritable_accessor :auditing_fields
|
15
|
+
|
16
|
+
has_many :audits, :as => :auditable, :order => 'created_at DESC, id DESC'
|
17
|
+
|
18
|
+
self.auditing_fields = gather_fields_for_auditing(opts[:fields])
|
19
|
+
|
20
|
+
after_create :log_creation
|
21
|
+
after_update :log_update
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def gather_fields_for_auditing(fields=nil)
|
26
|
+
return self.column_names - ["id", "created_at", "updated_at"] unless fields
|
27
|
+
fields.is_a?(Array) ? fields.map {|f| f.to_s} : [fields.to_s]
|
28
|
+
end
|
29
|
+
|
30
|
+
module InstanceMethods
|
31
|
+
def log_creation
|
32
|
+
add_audit(:action => 'created', :undoable => false)
|
33
|
+
end
|
34
|
+
|
35
|
+
def log_update
|
36
|
+
if changed?
|
37
|
+
changes.each.select {|k,v| auditing_fields.include?(k)}.each do |field, change|
|
38
|
+
next if change[0].to_s == change[1].to_s
|
39
|
+
add_audit(:action => 'updated', :field_name => field,
|
40
|
+
:old_value => change[0], :new_value => change[1])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
def add_audit(hash={})
|
47
|
+
Audit.create!({:auditable => self}.merge(hash))
|
48
|
+
end
|
49
|
+
end # Auditing::InstanceMethods
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Auditing
|
2
|
+
module Auditor
|
3
|
+
|
4
|
+
def reversable?
|
5
|
+
%w[updated].include?(action)
|
6
|
+
end
|
7
|
+
|
8
|
+
def show_action
|
9
|
+
action
|
10
|
+
end
|
11
|
+
|
12
|
+
def rollback
|
13
|
+
return unless reversable?
|
14
|
+
|
15
|
+
if association.blank?
|
16
|
+
auditable.update_attribute(field_name.to_sym, old_value)
|
17
|
+
else
|
18
|
+
# TODO
|
19
|
+
# association.class.find(association_id).update_attribute(field_name.to_sym, old_value)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end # end Auditing::Auditor
|
25
|
+
end
|
data/lib/auditing.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Auditing" do
|
4
|
+
|
5
|
+
describe "auditing default values" do
|
6
|
+
before do
|
7
|
+
class School < ActiveRecord::Base
|
8
|
+
auditing
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it "responds to auditing when auditing is added to an AR object" do
|
13
|
+
School.should respond_to(:auditing)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "responds to @auditing_fields" do
|
17
|
+
School.should respond_to(:auditing_fields)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "has default values when no fields are passed in" do
|
21
|
+
School.stub!(:column_names).and_return(["id", "name", "established_on", "created_at", "updated_at"])
|
22
|
+
School.gather_fields_for_auditing.should == ["name", "established_on"]
|
23
|
+
end
|
24
|
+
end # auditing default values
|
25
|
+
|
26
|
+
describe "auditing :fields => [:foo,:bar]" do
|
27
|
+
it "accepts a single valude as a symbol" do
|
28
|
+
class School < ActiveRecord::Base
|
29
|
+
auditing :fields => :name
|
30
|
+
end
|
31
|
+
School.auditing_fields.should == ['name']
|
32
|
+
end
|
33
|
+
|
34
|
+
it "accepts a single value as a string" do
|
35
|
+
class School < ActiveRecord::Base
|
36
|
+
auditing :fields => 'name'
|
37
|
+
end
|
38
|
+
School.auditing_fields.should == ['name']
|
39
|
+
end
|
40
|
+
|
41
|
+
it "accepts an array of symbols" do
|
42
|
+
class School < ActiveRecord::Base
|
43
|
+
auditing :fields => [:name, :established_on]
|
44
|
+
end
|
45
|
+
School.auditing_fields.should == ['name', 'established_on']
|
46
|
+
end
|
47
|
+
|
48
|
+
it "accepts an array of strings" do
|
49
|
+
class School < ActiveRecord::Base
|
50
|
+
auditing :fields => ['name', 'established_on']
|
51
|
+
end
|
52
|
+
School.auditing_fields.should == ['name', 'established_on']
|
53
|
+
end
|
54
|
+
end # auditing :fields => [:foo,:bar]
|
55
|
+
|
56
|
+
describe "creating a new instance" do
|
57
|
+
before do
|
58
|
+
class School < ActiveRecord::Base
|
59
|
+
auditing
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it "creates an audit" do
|
64
|
+
lambda { School.create(:name => 'PS118') }.should change { Audit.count }.by(1)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "the first audit has an action of 'created'" do
|
68
|
+
school = School.create(:name => 'PS118')
|
69
|
+
school.audits.first.action.should == 'created'
|
70
|
+
end
|
71
|
+
|
72
|
+
it "the first audit should not be reversable" do
|
73
|
+
school = School.create(:name => 'PS118')
|
74
|
+
school.audits.first.reversable?.should == false
|
75
|
+
end
|
76
|
+
|
77
|
+
it "the audit.auditable should be the object that created the audit" do
|
78
|
+
school = School.create(:name => 'PS118')
|
79
|
+
school.audits.first.auditable.should == school
|
80
|
+
end
|
81
|
+
end # creating a new instance
|
82
|
+
|
83
|
+
describe "updating an existing record" do
|
84
|
+
before do
|
85
|
+
class School < ActiveRecord::Base
|
86
|
+
auditing :fields => 'name'
|
87
|
+
end
|
88
|
+
@school = School.create(:name => 'PS118')
|
89
|
+
end
|
90
|
+
|
91
|
+
it "creates an audit" do
|
92
|
+
lambda { @school.update_attributes(:name => 'PS99') }.should change { Audit.count }.by(1)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "the first audit has an action of 'updated" do
|
96
|
+
@school.update_attributes(:name => 'PS99')
|
97
|
+
@school.audits.first.action.should == 'updated'
|
98
|
+
end
|
99
|
+
|
100
|
+
it "the first audit should be reversable" do
|
101
|
+
@school.update_attributes(:name => 'PS99')
|
102
|
+
@school.audits.first.reversable?.should == true
|
103
|
+
end
|
104
|
+
|
105
|
+
it "the first audit stored the new value" do
|
106
|
+
@school.update_attributes(:name => 'PS99')
|
107
|
+
@school.audits.first.new_value.should == 'PS99'
|
108
|
+
end
|
109
|
+
|
110
|
+
it "the first audit stored the old value" do
|
111
|
+
@school.update_attributes(:name => 'PS99')
|
112
|
+
@school.audits.first.old_value.should == 'PS118'
|
113
|
+
end
|
114
|
+
|
115
|
+
it "the audit.auditable should be the object that created the audit" do
|
116
|
+
@school.update_attributes(:name => 'PS99')
|
117
|
+
@school.audits.first.auditable.should == @school
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "does not create an audit when" do
|
121
|
+
it "a value did not change" do
|
122
|
+
lambda { @school.update_attributes(:name => 'PS118') }.should_not change { Audit.count }
|
123
|
+
end
|
124
|
+
|
125
|
+
it "a value is not part of auditing_fields" do
|
126
|
+
lambda { @school.update_attributes(:established_on => Time.now) }.should_not change { Audit.count }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end # updating an existing record
|
130
|
+
|
131
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
# require 'timecop'
|
3
|
+
|
4
|
+
describe "Auditor" do
|
5
|
+
it 'adds the Auditable::Auditor module to the Audit class' do
|
6
|
+
Audit.new.should respond_to(:show_action)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#rollback" do
|
10
|
+
before do
|
11
|
+
class School < ActiveRecord::Base
|
12
|
+
auditing
|
13
|
+
end
|
14
|
+
@school = School.create(:name => 'PS118')
|
15
|
+
@school.update_attributes(:name => 'PS99')
|
16
|
+
@audit = @school.audits.first
|
17
|
+
end
|
18
|
+
|
19
|
+
it "the first audit should be the audit we want to rollback" do
|
20
|
+
@audit.action.should == 'updated'
|
21
|
+
@audit.new_value.should == 'PS99'
|
22
|
+
@audit.old_value.should == 'PS118'
|
23
|
+
@audit.association.should == nil
|
24
|
+
end
|
25
|
+
|
26
|
+
it "performs the rollback" do
|
27
|
+
@audit.rollback
|
28
|
+
@school.reload
|
29
|
+
@school.name.should == 'PS118'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "creates an audit when a rollback is performed" do
|
33
|
+
lambda { @audit.rollback }.should change { Audit.count }.by(1)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "the first audit after a rollback should contain the changed values" do
|
37
|
+
@audit.rollback
|
38
|
+
@school.reload
|
39
|
+
@school.audits.first.old_value.should == 'PS99'
|
40
|
+
@school.audits.first.new_value.should == 'PS118'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/spec/schema.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 0) do
|
2
|
+
|
3
|
+
create_table :audits, :force => true do |t|
|
4
|
+
t.string :action
|
5
|
+
t.string :auditable_type
|
6
|
+
t.integer :auditable_id
|
7
|
+
t.string :association_type
|
8
|
+
t.integer :association_id
|
9
|
+
t.string :field_name
|
10
|
+
t.string :old_value
|
11
|
+
t.string :new_value
|
12
|
+
# t.integer :user_id
|
13
|
+
t.boolean :undoable, :default => true
|
14
|
+
t.timestamps
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
create_table :schools, :force => true do |t|
|
19
|
+
t.string :name
|
20
|
+
t.datetime :established_on
|
21
|
+
t.timestamps
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
|
4
|
+
require 'active_record'
|
5
|
+
require 'auditing'
|
6
|
+
require 'rspec'
|
7
|
+
# require 'spec/autorun'
|
8
|
+
|
9
|
+
# our test database
|
10
|
+
TEST_DB = File.join(File.dirname(__FILE__), '..', 'test.sqlite3')
|
11
|
+
File.unlink(TEST_DB) if File.exist?(TEST_DB)
|
12
|
+
ActiveRecord::Base.establish_connection(
|
13
|
+
:adapter => "sqlite3",
|
14
|
+
:database => TEST_DB
|
15
|
+
)
|
16
|
+
|
17
|
+
# our schema
|
18
|
+
load(File.dirname(__FILE__) + '/schema.rb')
|
19
|
+
|
20
|
+
class Audit < ActiveRecord::Base
|
21
|
+
include Auditing::Auditor
|
22
|
+
belongs_to :auditable, :polymorphic => true
|
23
|
+
belongs_to :association, :polymorphic => true
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: auditing
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Brad
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-08-29 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 1
|
30
|
+
- 2
|
31
|
+
- 9
|
32
|
+
version: 1.2.9
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
description: acts_as_versioned is good. This allows an attribute level rollback instead
|
36
|
+
email: brad.cantin@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- LICENSE
|
43
|
+
- README.rdoc
|
44
|
+
files:
|
45
|
+
- .bundle/config
|
46
|
+
- .document
|
47
|
+
- .gitignore
|
48
|
+
- .rspec
|
49
|
+
- Gemfile
|
50
|
+
- Gemfile.lock
|
51
|
+
- LICENSE
|
52
|
+
- README.rdoc
|
53
|
+
- Rakefile
|
54
|
+
- VERSION
|
55
|
+
- auditing.gemspec
|
56
|
+
- lib/auditing.rb
|
57
|
+
- lib/auditing/auditing.rb
|
58
|
+
- lib/auditing/auditor.rb
|
59
|
+
- spec/auditing/auditing_spec.rb
|
60
|
+
- spec/auditing/auditor_spec.rb
|
61
|
+
- spec/schema.rb
|
62
|
+
- spec/spec_helper.rb
|
63
|
+
has_rdoc: true
|
64
|
+
homepage: http://github.com/bcantin/auditing
|
65
|
+
licenses: []
|
66
|
+
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options:
|
69
|
+
- --charset=UTF-8
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
version: "0"
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 1.3.7
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: A gem to keep track of audit hisory of a record
|
95
|
+
test_files:
|
96
|
+
- spec/auditing/auditing_spec.rb
|
97
|
+
- spec/auditing/auditor_spec.rb
|
98
|
+
- spec/schema.rb
|
99
|
+
- spec/spec_helper.rb
|