pg_audit_log 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,5 +3,7 @@ source :rubygems
3
3
  # Specify your gem's dependencies the .gemspec
4
4
  gemspec
5
5
 
6
- gem "pg"
7
- gem "ZenTest"
6
+ group :development do
7
+ gem 'wirble'
8
+ end
9
+
data/Rakefile CHANGED
@@ -1,6 +1,12 @@
1
+ require 'rake'
2
+ require 'rspec/core'
3
+ require 'rspec/core/rake_task'
4
+
1
5
  require 'bundler'
2
6
  Bundler::GemHelper.install_tasks
3
7
 
4
- task :autotest do
5
- sh "bundle update && autotest -s rspec2"
6
- end
8
+ task :default => :spec
9
+
10
+ desc "Run all specs in spec directory (excluding plugin specs)"
11
+ RSpec::Core::RakeTask.new(:spec)
12
+
@@ -4,7 +4,7 @@ module PgAuditLog
4
4
  module Generators
5
5
  class InstallGenerator < Rails::Generators::Base
6
6
  include Rails::Generators::Migration
7
- extend ActiveRecord::Generators::Migration
7
+ extend ::ActiveRecord::Generators::Migration
8
8
 
9
9
  source_root File.expand_path('../templates', __FILE__)
10
10
 
@@ -43,7 +43,9 @@ module PgAuditLog
43
43
  END IF;
44
44
  IF TG_OP = 'DELETE' OR TG_OP = 'UPDATE' THEN
45
45
  EXECUTE 'SELECT CAST($1 . '|| column_name ||' AS TEXT)' INTO old_value USING OLD;
46
- EXECUTE 'SELECT CAST($1 . '|| primary_key_column ||' AS VARCHAR)' INTO primary_key_value USING OLD;
46
+ IF primary_key_column IS NOT NULL THEN
47
+ EXECUTE 'SELECT CAST($1 . '|| primary_key_column ||' AS VARCHAR)' INTO primary_key_value USING OLD;
48
+ END IF;
47
49
  END IF;
48
50
 
49
51
  IF TG_RELNAME = 'users' AND column_name = 'last_accessed_at' THEN
@@ -1,3 +1,3 @@
1
1
  module PgAuditLog
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
data/pg_audit_log.gemspec CHANGED
@@ -17,7 +17,8 @@ Gem::Specification.new do |s|
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
19
 
20
- s.add_dependency("rails", ">=2.3")
21
- s.add_development_dependency('rspec')
22
- s.add_development_dependency('with_model')
20
+ s.add_dependency("rails", ">= 3.0.0")
21
+ s.add_dependency("pg", ">= 0.9.0")
22
+ s.add_development_dependency('rspec-rails')
23
+ s.add_development_dependency('with_model', '>= 0.1.3')
23
24
  end
@@ -13,30 +13,37 @@ describe PgAuditLog do
13
13
  end
14
14
  end
15
15
 
16
+ with_model :audited_model_without_primary_key do
17
+ table :id => false do |t|
18
+ t.string :str
19
+ t.text :txt
20
+ t.integer :int
21
+ t.date :date
22
+ t.datetime :dt
23
+ t.boolean :bool
24
+ end
25
+ end
26
+
16
27
  before do
17
- AuditedModel.connection.execute(<<-SQL)
18
- CREATE TRIGGER audit_audited_models
19
- AFTER INSERT OR UPDATE OR DELETE
20
- ON #{AuditedModel.quoted_table_name}
21
- FOR EACH ROW
22
- EXECUTE PROCEDURE audit_changes()
23
- SQL
28
+ PgAuditLog::Triggers.create_for_table(AuditedModel.table_name)
29
+ PgAuditLog::Triggers.create_for_table(AuditedModelWithoutPrimaryKey.table_name)
24
30
  end
25
31
 
26
32
  after do
27
- AuditedModel.connection.execute("DROP TRIGGER audit_audited_models ON #{AuditedModel.quoted_table_name};")
33
+ PgAuditLog::Triggers.drop_for_table(AuditedModel.table_name)
34
+ PgAuditLog::Triggers.drop_for_table(AuditedModelWithoutPrimaryKey.table_name)
28
35
  PgAuditLog::Entry.connection.execute("TRUNCATE #{PgAuditLog::Entry.quoted_table_name}")
29
36
  end
30
37
 
31
38
  let(:attributes) { { :str => "foo", :txt => "bar", :int => 5, :date => Date.today, :dt => Time.now.midnight } }
32
39
 
33
- context "on create" do
40
+ describe "on create" do
41
+ context "the audit log record with a primary key" do
34
42
 
35
- before do
36
- AuditedModel.create!(attributes)
37
- end
43
+ before do
44
+ AuditedModel.create!(attributes)
45
+ end
38
46
 
39
- describe "the audit log record" do
40
47
  subject { PgAuditLog::Entry.last(:conditions => { :field_name => "str" }) }
41
48
 
42
49
  it { should be }
@@ -75,110 +82,150 @@ describe PgAuditLog do
75
82
  end
76
83
 
77
84
  end
78
- end
79
85
 
80
- context "on update" do
81
- before do
82
- @model = AuditedModel.create!(attributes)
83
- end
86
+ context "the audit log record without a primary key" do
87
+ before do
88
+ AuditedModelWithoutPrimaryKey.create!(attributes)
89
+ end
84
90
 
85
- context "when going from a value to a another value" do
86
- before { @model.update_attributes!(:str => "bar") }
87
91
  subject { PgAuditLog::Entry.last(:conditions => { :field_name => "str" }) }
88
92
 
89
- its(:operation) { should == "UPDATE" }
90
- its(:field_value_new) { should == "bar" }
91
- its(:field_value_old) { should == "foo" }
93
+ it { should be }
94
+ its(:field_name) { should == "str" }
95
+ its(:primary_key) { should be_nil }
92
96
  end
97
+ end
93
98
 
94
- context "when going from nil to a value" do
95
- let(:attributes) { {:txt => nil} }
96
- before { @model.update_attributes!(:txt => "baz") }
97
- subject { PgAuditLog::Entry.last(:conditions => { :field_name => "txt" }) }
99
+ describe "on update" do
100
+ context "the audit log record with a primary key" do
101
+ before do
102
+ @model = AuditedModel.create!(attributes)
103
+ end
98
104
 
99
- its(:field_value_new) { should == "baz" }
100
- its(:field_value_old) { should be_nil }
101
- end
105
+ context "when going from a value to a another value" do
106
+ before { @model.update_attributes!(:str => "bar") }
107
+ subject { PgAuditLog::Entry.last(:conditions => { :field_name => "str" }) }
102
108
 
103
- context "when going from a value to nil" do
104
- before { @model.update_attributes!(:str => nil) }
105
- subject { PgAuditLog::Entry.last(:conditions => { :field_name => "str" }) }
109
+ its(:operation) { should == "UPDATE" }
110
+ its(:field_value_new) { should == "bar" }
111
+ its(:field_value_old) { should == "foo" }
112
+ end
106
113
 
107
- its(:field_value_new) { should be_nil }
108
- its(:field_value_old) { should == "foo" }
109
- end
114
+ context "when going from nil to a value" do
115
+ let(:attributes) { {:txt => nil} }
116
+ before { @model.update_attributes!(:txt => "baz") }
117
+ subject { PgAuditLog::Entry.last(:conditions => { :field_name => "txt" }) }
110
118
 
111
- context "when the value does not change" do
112
- before { @model.update_attributes!(:str => "foo") }
113
- subject { PgAuditLog::Entry.last(:conditions => { :field_name => "str", :operation => "UPDATE" }) }
119
+ its(:field_value_new) { should == "baz" }
120
+ its(:field_value_old) { should be_nil }
121
+ end
114
122
 
115
- it { should_not be }
116
- end
123
+ context "when going from a value to nil" do
124
+ before { @model.update_attributes!(:str => nil) }
125
+ subject { PgAuditLog::Entry.last(:conditions => { :field_name => "str" }) }
117
126
 
118
- context "when the value is nil and does not change" do
119
- let(:attributes) { {:txt => nil} }
120
- before { @model.update_attributes!(:txt => nil) }
121
- subject { PgAuditLog::Entry.last(:conditions => { :field_name => "txt", :operation => "UPDATE" }) }
127
+ its(:field_value_new) { should be_nil }
128
+ its(:field_value_old) { should == "foo" }
129
+ end
122
130
 
123
- it { should_not be }
124
- end
131
+ context "when the value does not change" do
132
+ before { @model.update_attributes!(:str => "foo") }
133
+ subject { PgAuditLog::Entry.last(:conditions => { :field_name => "str", :operation => "UPDATE" }) }
125
134
 
126
- context "when the value is a boolean" do
135
+ it { should_not be }
136
+ end
127
137
 
128
- context "going from nil -> true" do
129
- before { @model.update_attributes!(:bool => true) }
130
- subject { PgAuditLog::Entry.last(:conditions => { :field_name => "bool", :operation => "UPDATE" }) }
138
+ context "when the value is nil and does not change" do
139
+ let(:attributes) { {:txt => nil} }
140
+ before { @model.update_attributes!(:txt => nil) }
141
+ subject { PgAuditLog::Entry.last(:conditions => { :field_name => "txt", :operation => "UPDATE" }) }
131
142
 
132
- its(:field_value_new) { should == "true" }
133
- its(:field_value_old) { should be_nil }
143
+ it { should_not be }
134
144
  end
135
145
 
136
- context "going from false -> true" do
137
- let(:attributes) { {:bool => false} }
138
- before do
139
- @model.update_attributes!(:bool => true)
146
+ context "when the value is a boolean" do
147
+
148
+ context "going from nil -> true" do
149
+ before { @model.update_attributes!(:bool => true) }
150
+ subject { PgAuditLog::Entry.last(:conditions => { :field_name => "bool", :operation => "UPDATE" }) }
151
+
152
+ its(:field_value_new) { should == "true" }
153
+ its(:field_value_old) { should be_nil }
140
154
  end
141
- subject { PgAuditLog::Entry.last(:conditions => { :field_name => "bool", :operation => "UPDATE" }) }
142
155
 
143
- its(:field_value_new) { should == "true" }
144
- its(:field_value_old) { should == "false" }
145
- end
156
+ context "going from false -> true" do
157
+ let(:attributes) { {:bool => false} }
158
+ before do
159
+ @model.update_attributes!(:bool => true)
160
+ end
161
+ subject { PgAuditLog::Entry.last(:conditions => { :field_name => "bool", :operation => "UPDATE" }) }
146
162
 
147
- context "going from true -> false" do
148
- let(:attributes) { {:bool => true} }
163
+ its(:field_value_new) { should == "true" }
164
+ its(:field_value_old) { should == "false" }
165
+ end
149
166
 
150
- before do
151
- @model.update_attributes!(:bool => false)
167
+ context "going from true -> false" do
168
+ let(:attributes) { {:bool => true} }
169
+
170
+ before do
171
+ @model.update_attributes!(:bool => false)
172
+ end
173
+ subject { PgAuditLog::Entry.last(:conditions => { :field_name => "bool", :operation => "UPDATE" }) }
174
+
175
+ its(:field_value_new) { should == "false" }
176
+ its(:field_value_old) { should == "true" }
152
177
  end
153
- subject { PgAuditLog::Entry.last(:conditions => { :field_name => "bool", :operation => "UPDATE" }) }
154
178
 
155
- its(:field_value_new) { should == "false" }
156
- its(:field_value_old) { should == "true" }
179
+ end
180
+ end
181
+
182
+ context "the audit log record without a primary key" do
183
+ before do
184
+ AuditedModelWithoutPrimaryKey.create!(attributes)
185
+ AuditedModelWithoutPrimaryKey.update_all(:str => "bar")
157
186
  end
158
187
 
188
+ subject { PgAuditLog::Entry.last(:conditions => { :field_name => "str" }) }
189
+
190
+ its(:primary_key) { should be_nil }
159
191
  end
192
+
160
193
  end
161
194
 
162
- context "on delete" do
163
- before do
164
- @model = AuditedModel.create!(attributes)
165
- @model.delete
166
- end
195
+ describe "on delete" do
196
+
197
+ context "the audit log record with a primary key" do
198
+ before do
199
+ model = AuditedModel.create!(attributes)
200
+ model.delete
201
+ end
167
202
 
168
- subject { PgAuditLog::Entry.last(:conditions => { :field_name => "str" }) }
203
+ subject { PgAuditLog::Entry.last(:conditions => { :field_name => "str" }) }
169
204
 
170
- its(:operation) { should == "DELETE" }
205
+ its(:operation) { should == "DELETE" }
171
206
 
172
- it "captures all new values for all fields" do
173
- attributes.each do |field_name, value|
174
- if field_name == :dt
175
- PgAuditLog::Entry.last(:conditions => { :field_name => field_name }).field_value_old.should == value.strftime("%Y-%m-%d %H:%M:%S")
176
- else
177
- PgAuditLog::Entry.last(:conditions => { :field_name => field_name }).field_value_old.should == value.to_s
207
+ it "captures all new values for all fields" do
208
+ attributes.each do |field_name, value|
209
+ if field_name == :dt
210
+ PgAuditLog::Entry.last(:conditions => { :field_name => field_name }).field_value_old.should == value.strftime("%Y-%m-%d %H:%M:%S")
211
+ else
212
+ PgAuditLog::Entry.last(:conditions => { :field_name => field_name }).field_value_old.should == value.to_s
213
+ end
214
+ PgAuditLog::Entry.last(:conditions => { :field_name => field_name }).field_value_new.should be_nil
178
215
  end
179
- PgAuditLog::Entry.last(:conditions => { :field_name => field_name }).field_value_new.should be_nil
180
216
  end
181
217
  end
218
+
219
+ context "the audit log record without a primary key" do
220
+ before do
221
+ AuditedModelWithoutPrimaryKey.create!(attributes)
222
+ AuditedModelWithoutPrimaryKey.delete_all
223
+ end
224
+
225
+ subject { PgAuditLog::Entry.last(:conditions => { :field_name => "str" }) }
226
+
227
+ its(:primary_key) { should be_nil }
228
+ end
182
229
  end
183
230
  end
184
231
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: pg_audit_log
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.2
5
+ version: 0.1.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Case Commons, LLC
@@ -21,22 +21,22 @@ dependencies:
21
21
  requirements:
22
22
  - - ">="
23
23
  - !ruby/object:Gem::Version
24
- version: "2.3"
24
+ version: 3.0.0
25
25
  type: :runtime
26
26
  version_requirements: *id001
27
27
  - !ruby/object:Gem::Dependency
28
- name: rspec
28
+ name: pg
29
29
  prerelease: false
30
30
  requirement: &id002 !ruby/object:Gem::Requirement
31
31
  none: false
32
32
  requirements:
33
33
  - - ">="
34
34
  - !ruby/object:Gem::Version
35
- version: "0"
36
- type: :development
35
+ version: 0.9.0
36
+ type: :runtime
37
37
  version_requirements: *id002
38
38
  - !ruby/object:Gem::Dependency
39
- name: with_model
39
+ name: rspec-rails
40
40
  prerelease: false
41
41
  requirement: &id003 !ruby/object:Gem::Requirement
42
42
  none: false
@@ -46,6 +46,17 @@ dependencies:
46
46
  version: "0"
47
47
  type: :development
48
48
  version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: with_model
51
+ prerelease: false
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 0.1.3
58
+ type: :development
59
+ version_requirements: *id004
49
60
  description: A completely transparent audit logging component for your application using a stored procedure and triggers. Comes with specs for your project and a rake task to generate the reverse SQL to undo changes logged
50
61
  email:
51
62
  - casecommons-dev@googlegroups.com