pg_audit_log 0.0.2 → 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.
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