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 +4 -2
- data/Rakefile +9 -3
- data/lib/generators/pg_audit_log/install_generator.rb +1 -1
- data/lib/pg_audit_log/function.rb +3 -1
- data/lib/pg_audit_log/version.rb +1 -1
- data/pg_audit_log.gemspec +4 -3
- data/spec/pg_audit_log_spec.rb +129 -82
- metadata +17 -6
    
        data/Gemfile
    CHANGED
    
    
    
        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 : | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 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 | 
            -
                               | 
| 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
         | 
    
        data/lib/pg_audit_log/version.rb
    CHANGED
    
    
    
        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", ">= | 
| 21 | 
            -
              s. | 
| 22 | 
            -
              s.add_development_dependency(' | 
| 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
         | 
    
        data/spec/pg_audit_log_spec.rb
    CHANGED
    
    | @@ -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. | 
| 18 | 
            -
             | 
| 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 | 
            -
                   | 
| 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 | 
            -
                 | 
| 40 | 
            +
                describe "on create" do
         | 
| 41 | 
            +
                  context "the audit log record with a primary key" do
         | 
| 34 42 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 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 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 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 | 
            -
                     | 
| 90 | 
            -
                    its(: | 
| 91 | 
            -
                    its(: | 
| 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 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
                    before  | 
| 97 | 
            -
             | 
| 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 | 
            -
                     | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 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 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 109 | 
            +
                      its(:operation) { should == "UPDATE" }
         | 
| 110 | 
            +
                      its(:field_value_new) { should == "bar" }
         | 
| 111 | 
            +
                      its(:field_value_old) { should == "foo" }
         | 
| 112 | 
            +
                    end
         | 
| 106 113 |  | 
| 107 | 
            -
                     | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 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 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
                     | 
| 119 | 
            +
                      its(:field_value_new) { should == "baz" }
         | 
| 120 | 
            +
                      its(:field_value_old) { should be_nil }
         | 
| 121 | 
            +
                    end
         | 
| 114 122 |  | 
| 115 | 
            -
                     | 
| 116 | 
            -
             | 
| 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 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
                     | 
| 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 | 
            -
                     | 
| 124 | 
            -
             | 
| 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 | 
            -
             | 
| 135 | 
            +
                      it { should_not be }
         | 
| 136 | 
            +
                    end
         | 
| 127 137 |  | 
| 128 | 
            -
                    context " | 
| 129 | 
            -
                       | 
| 130 | 
            -
                       | 
| 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 | 
            -
                       | 
| 133 | 
            -
                      its(:field_value_old) { should be_nil }
         | 
| 143 | 
            +
                      it { should_not be }
         | 
| 134 144 | 
             
                    end
         | 
| 135 145 |  | 
| 136 | 
            -
                    context " | 
| 137 | 
            -
             | 
| 138 | 
            -
                       | 
| 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 | 
            -
                       | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 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 | 
            -
             | 
| 148 | 
            -
             | 
| 163 | 
            +
                        its(:field_value_new) { should == "true" }
         | 
| 164 | 
            +
                        its(:field_value_old) { should == "false" }
         | 
| 165 | 
            +
                      end
         | 
| 149 166 |  | 
| 150 | 
            -
                       | 
| 151 | 
            -
                         | 
| 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 | 
            -
             | 
| 156 | 
            -
             | 
| 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 | 
            -
                 | 
| 163 | 
            -
             | 
| 164 | 
            -
             | 
| 165 | 
            -
                     | 
| 166 | 
            -
             | 
| 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 | 
            -
             | 
| 203 | 
            +
                    subject { PgAuditLog::Entry.last(:conditions => { :field_name => "str" }) }
         | 
| 169 204 |  | 
| 170 | 
            -
             | 
| 205 | 
            +
                    its(:operation) { should == "DELETE" }
         | 
| 171 206 |  | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 174 | 
            -
             | 
| 175 | 
            -
             | 
| 176 | 
            -
             | 
| 177 | 
            -
             | 
| 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 | 
| 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:  | 
| 24 | 
            +
                    version: 3.0.0
         | 
| 25 25 | 
             
              type: :runtime
         | 
| 26 26 | 
             
              version_requirements: *id001
         | 
| 27 27 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| 28 | 
            -
              name:  | 
| 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:  | 
| 36 | 
            -
              type: : | 
| 35 | 
            +
                    version: 0.9.0
         | 
| 36 | 
            +
              type: :runtime
         | 
| 37 37 | 
             
              version_requirements: *id002
         | 
| 38 38 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| 39 | 
            -
              name:  | 
| 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
         |