audit_tables 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 12b1674ebfca6a1ded9baffc0c7942980a16f13c
4
+ data.tar.gz: 7a8b3695f39e7cb194141e1f950b5477e6efa64d
5
+ SHA512:
6
+ metadata.gz: 88c840a04f5784511915c8924486700e92a340d49a57c3c262ac85a61c6cd7e47f3739f3beaa72980ecc9d3ec77c19f434edef1f2b39c1a2877ecb778d0b9882
7
+ data.tar.gz: 7727cd00aa9363086aaf1861f10b14e02da47ef50ead9dd581042c514b10da8e385de586a4e11d1328f2bdd4eedc9422be2a86ba63061f0c5350daf7cd83f4d5
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .byebug_history
11
+
12
+ # Editor Droppings #
13
+ .idea
14
+
15
+ # OS generated files #
16
+ .DS_Store
17
+ .DS_Store?
18
+ ._*
19
+ .Spotlight-V100
20
+ .Trashes
data/.pairs ADDED
@@ -0,0 +1,15 @@
1
+ # .pairs - configuration for 'git pair'
2
+ pairs:
3
+ # <initials>: <Firstname> <Lastname>[; <email-id>]
4
+ aw: Alex Wang; alexw668
5
+ cw: Conroy Whitney; conroywhitney
6
+ en: Eric Nichols; nix2k2
7
+ jh: Jesse House; house9
8
+ jl: Julio Lucero; julioalucero
9
+ tt: Todd Trask;
10
+ vb: Vitor Oliveira; vbrazo
11
+
12
+ email:
13
+ prefix: team
14
+ domain: gitpair.com
15
+ no_solo_prefix: true
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,32 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+ Exclude:
4
+ - 'bin/*'
5
+ - Gemfile
6
+ - syncordia.gemspec
7
+ DisplayCopNames: true
8
+ AmbiguousOperator:
9
+ Enabled: false
10
+ Metrics/LineLength:
11
+ Max: 120
12
+ Exclude:
13
+ - Rakefile
14
+ Style/Documentation:
15
+ Enabled: false
16
+ Style/HashSyntax:
17
+ Exclude:
18
+ - Rakefile
19
+ Style/IndentHash:
20
+ EnforcedStyle: consistent
21
+ Style/LambdaCall:
22
+ Enabled: false
23
+ Style/MultilineMethodCallIndentation:
24
+ Enabled: false
25
+ Style/Next:
26
+ Enabled: false
27
+ Style/WordArray:
28
+ Enabled: false
29
+ AmbiguousOperator:
30
+ Enabled: false
31
+ Style/ModuleFunction:
32
+ EnforcedStyle: extend_self
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in audit_tables.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Jesse House
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # AuditTables
2
+
3
+ [![CircleCI](https://circleci.com/gh/syncordiahealth/audit_tables/tree/master.svg?style=shield)](https://circleci.com/gh/syncordiahealth/audit_tables/tree/master)
4
+
5
+ The `audit_tables` gem can be used by rails applications using a [postgresql](https://www.postgresql.org/) databases.
6
+
7
+ It adds helper functions that can be used to create audit tables and database triggers for tracking `INSERT`, `UPDATE` and `DELETE` database actions.
8
+
9
+ `audit_tables` works purely at the database level and you will need to use raw sql to view audit logs.
10
+
11
+ It generates audit tables using the naming convention `audit_TABLE_NAME`, i.e. `audit_widgets`.
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'audit_tables'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install audit_tables
28
+
29
+ Optionally add an initializer file: `config/initializers/audit_tables.rb`, if you want to skip audits for some tables.
30
+
31
+ ```ruby
32
+ AuditTables.configure do |config|
33
+ config.exclude_tables << 'sessions'
34
+ end
35
+ ```
36
+
37
+ NOTE: `ar_internal_metadata` and `schema_migrations` are skipped by default, but you can audit those as well by overriding the configuation option:
38
+
39
+ ```ruby
40
+ AuditTables.configure do |config|
41
+ config.exclude_tables = []
42
+ end
43
+ ```
44
+
45
+ ## Usage
46
+
47
+ The following public methods are exposed by the `AuditTables` module:
48
+
49
+ * `create_audit_tables_for_existing_tables`
50
+ * Creates an audit table for all existing tables. You would only call this once from a migration:
51
+ * `AuditTables.create_audit_tables_for_existing_tables`
52
+ * `create_audit_table_for(table_name)`
53
+ * Create an audit table for a new table. See examples below.
54
+ * `change_audit_table_for(table_name)`
55
+ * When you make changes in your tables, you can use this method to apply the same changes to the audit tables.
56
+ * Optionally, you can modify the audit table structure using rails helper methods directly. This method is here for convience only.
57
+ * `build_audit_triggers_for(table_name)`
58
+ * create the triggers on the new table or drop and re-create the audit triggers to handle all the new columns on the table passed as a parameter
59
+ * Since the trigger uses `*` and expects your source table column order to match the audit table column order, you don't actually need to call this after making table changes, however it does not hurt.
60
+ * `check_for_audit_tables`
61
+ * You can use this method in your specs, see spec example below.
62
+
63
+ #### Example Migration
64
+
65
+ ```
66
+ class ExampleMigration < ActiveRecord::Migration[5.0]
67
+ def change
68
+ create_table :widgets do |t|
69
+ t.string :name
70
+
71
+ t.timestamps
72
+ end
73
+
74
+ AuditTables.create_audit_table_for(:widgets)
75
+ AuditTables.build_audit_triggers_for(:widgets)
76
+
77
+ add_column :widgets, :serial_number, :string
78
+ AuditTables.change_audit_table_for(:widgets)
79
+ end
80
+ end
81
+ ```
82
+
83
+ #### Spec Example
84
+
85
+ This checks the database for audit tables and errors if a developer forgot to add one to a migration:
86
+
87
+ ```
88
+ describe AuditTables do
89
+ it 'ensure audit tables' do
90
+ checks = AuditTables.check_for_audit_tables
91
+ message = "You forgot to add audit tables for these tables: #{checks}"
92
+
93
+ expect(checks).to be_empty, message
94
+ end
95
+ end
96
+ ```
97
+
98
+ ## Notes
99
+
100
+ The structure of the audit tables:
101
+
102
+ * `audit_id`, integer auto incrementing
103
+ * `audit_operation` string - `INSERT`, `UPDATE` or `DELETE`
104
+ * `audit_timestamp` datetime (when the audit record was created)
105
+ * `*` all of the columns from the source table (column order must match)
106
+
107
+ The `DELETE` trigger copies all the values from the deleted record into the audit table, but it will probably look exactly like the previous `INSERT` or `UPDATE` audit record except for the `audit_timestamp`. If you are tracking which user updated a record, the delete audit probably won't reflect the correct user unless you did an update before the delete. We recommend doing soft deletes in most cases.
108
+
109
+ ## Development
110
+
111
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
112
+
113
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
114
+
115
+ ## Contributing
116
+
117
+ Bug reports and pull requests are welcome on GitHub at https://github.com/syncordiahealth/audit_tables.
118
+
119
+
120
+ ## License
121
+
122
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
123
+
124
+ ## Change Log
125
+
126
+ * Version 1.0.0 (2017-01-20)
127
+ * Initial Release
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'audit_tables/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'audit_tables'
9
+ spec.version = AuditTables::VERSION
10
+ spec.authors = ['Syncordia Technologies']
11
+ spec.email = ['info@syncordiahealth.ie']
12
+
13
+ spec.summary = 'Adds audit tables and triggers for postgres databases'
14
+ spec.description = 'Adds audit tables and triggers for postgres databases'
15
+ spec.homepage = 'https://github.com/syncordiahealth/audit_tables'
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+
22
+ spec.bindir = 'exe'
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ['lib']
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.13'
27
+ spec.add_development_dependency 'byebug', '~> 9.0.6'
28
+ spec.add_development_dependency 'faker'
29
+ spec.add_development_dependency 'pg'
30
+ spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.add_development_dependency 'rails'
32
+ spec.add_development_dependency 'rspec', '~> 3.0'
33
+ spec.add_development_dependency 'rubocop', '= 0.42.0'
34
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "audit_tables"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/circle.yml ADDED
@@ -0,0 +1,7 @@
1
+ machine:
2
+ ruby:
3
+ version:
4
+ 2.3.1
5
+ database:
6
+ override:
7
+ - echo "NO-OP - tests handle database setup"
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ # include all of the files inside the `lib/audit_tables` folder
4
+ Gem.find_files('audit_tables/**/*.rb').each { |path| require path }
5
+
6
+ module AuditTables
7
+ class << self
8
+ attr_accessor :configuration
9
+ end
10
+
11
+ class Configuration
12
+ attr_accessor :exclude_tables
13
+
14
+ def initialize
15
+ @exclude_tables = ['ar_internal_metadata', 'schema_migrations']
16
+ end
17
+ end
18
+
19
+ def self.config
20
+ self.configuration ||= Configuration.new
21
+ end
22
+
23
+ def self.configure
24
+ self.configuration ||= Configuration.new
25
+ yield(configuration)
26
+ end
27
+
28
+ def self.all_audit_tables
29
+ tables = ActiveRecord::Base.connection.tables
30
+ tables -= config.exclude_tables
31
+
32
+ tables
33
+ end
34
+
35
+ def self.build_audit_triggers_for(table_name)
36
+ AuditTables::BuildAuditTrigger.new(table_name.to_s).build
37
+ end
38
+
39
+ def self.check_for_audit_tables
40
+ messages = []
41
+
42
+ all_audit_tables.select { |table| !table.starts_with?('audit_') }.each do |table_name|
43
+ messages << table_name unless all_audit_tables.include? "audit_#{table_name}"
44
+ end
45
+
46
+ messages
47
+ end
48
+
49
+ def self.create_audit_table_for(table_name)
50
+ AuditTables::CreateNewAuditTable.new(table_name.to_s).build
51
+ end
52
+
53
+ def self.create_audit_tables_for_existing_tables
54
+ AuditTables::CreateAuditTablesForExistingTables.new(config.exclude_tables).process
55
+ end
56
+
57
+ def self.change_audit_table_for(table_name)
58
+ AuditTables::ChangeAuditTable.new(table_name.to_s).execute
59
+ end
60
+
61
+ def self.rebuild_all_audit_triggers
62
+ all_audit_tables.select { |table| !table.starts_with?('audit_') }.each do |table_name|
63
+ build_audit_triggers_for(table_name)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+ module AuditTables
3
+ class Base < ActiveRecord::Migration[5.0]
4
+ attr_accessor :audit_table_name, :column, :klass, :table_name
5
+
6
+ def initialize(table_name)
7
+ @table_name = table_name
8
+ @audit_table_name = "audit_#{table_name}"
9
+ @klass = table_name.classify.safe_constantize
10
+ end
11
+
12
+ private
13
+
14
+ def add_new_column
15
+ if properties.empty?
16
+ add_column audit_table_name, column.name, column_type
17
+ else
18
+ add_column audit_table_name, column.name, column_type, properties
19
+ end
20
+ end
21
+
22
+ def audit_columns
23
+ columns(table_name).each do |column|
24
+ @column = column
25
+
26
+ add_new_column unless column_exists?(audit_table_name, column.name)
27
+ end
28
+ end
29
+
30
+ def sync_audit_tables
31
+ create_audit_table unless table_exists?
32
+ audit_columns
33
+ end
34
+
35
+ def column_exists?(table_name, column_name)
36
+ ActiveRecord::Base.connection.column_exists?(table_name, column_name)
37
+ end
38
+
39
+ def column_name
40
+ column.name
41
+ end
42
+
43
+ def column_type
44
+ column.type
45
+ end
46
+
47
+ def columns(table_name)
48
+ ActiveRecord::Base.connection.columns(table_name)
49
+ end
50
+
51
+ def create_audit_table
52
+ create_table audit_table_name, id: false do |t|
53
+ t.integer :audit_id, null: false
54
+ t.string :audit_operation, null: false
55
+ t.datetime :audit_timestamp, null: false
56
+ end
57
+
58
+ add_column audit_table_name, :id, klass.columns_hash['id'].type
59
+ end
60
+
61
+ def default
62
+ column.default
63
+ end
64
+
65
+ def limit
66
+ column.limit
67
+ end
68
+
69
+ def null
70
+ column.null
71
+ end
72
+
73
+ def precision
74
+ column.precision
75
+ end
76
+
77
+ def properties
78
+ elements = {}
79
+
80
+ elements[:limit] = limit unless limit.nil?
81
+ elements[:precision] = precision unless precision.nil?
82
+ elements[:scale] = scale unless scale.nil?
83
+ elements[:default] = default unless default.nil?
84
+ elements[:null] = null
85
+
86
+ elements
87
+ end
88
+
89
+ def scale
90
+ column.scale
91
+ end
92
+
93
+ def table_exists?
94
+ ActiveRecord::Base.connection.data_source_exists? audit_table_name
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+ module AuditTables
3
+ class BuildAuditTrigger < ActiveRecord::Migration
4
+ attr_reader :table_name
5
+
6
+ def initialize(table_name)
7
+ @table_name = table_name
8
+ end
9
+
10
+ # rubocop:disable Metrics/MethodLength:
11
+ def build
12
+ sequence_name = "seq_audit_#{table_name}"
13
+
14
+ execute %{
15
+ DROP TRIGGER IF EXISTS trigger_audit_#{table_name} ON #{table_name};
16
+
17
+ CREATE SEQUENCE IF NOT EXISTS #{sequence_name} START 1;
18
+
19
+ CREATE OR REPLACE FUNCTION trigger_audit_#{table_name}_func() RETURNS TRIGGER AS $body$
20
+ BEGIN
21
+ IF (TG_OP = 'INSERT') THEN
22
+ INSERT INTO audit_#{table_name}
23
+ SELECT nextval('#{sequence_name}'), 'INSERT', NOW(), *
24
+ FROM #{table_name}
25
+ WHERE id = NEW.id;
26
+ ELSIF (TG_OP = 'UPDATE') THEN
27
+ INSERT INTO audit_#{table_name}
28
+ SELECT nextval('#{sequence_name}'), 'UPDATE', NOW(), *
29
+ FROM #{table_name}
30
+ WHERE id = OLD.id;
31
+ ELSIF (TG_OP = 'DELETE') THEN
32
+ INSERT INTO audit_#{table_name}
33
+ SELECT nextval('#{sequence_name}'), 'DELETE', NOW(), OLD.*;
34
+ END IF;
35
+ RETURN NULL;
36
+ END;
37
+ $body$
38
+ LANGUAGE plpgsql
39
+ SECURITY DEFINER;
40
+
41
+ CREATE TRIGGER trigger_audit_#{table_name} AFTER INSERT OR UPDATE OR DELETE ON #{table_name}
42
+ FOR EACH ROW EXECUTE PROCEDURE trigger_audit_#{table_name}_func();
43
+ }
44
+ end
45
+ # rubocop:enable Metrics/MethodLength:
46
+ end
47
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ module AuditTables
3
+ class ChangeAuditTable < Base
4
+ attr_accessor :audit_column
5
+
6
+ def audit_changes
7
+ columns(audit_table_name).each do |audit_column|
8
+ @audit_column = audit_column
9
+
10
+ column_exists?(table_name, audit_column.name) ? change_attribute : remove_attribute
11
+ end
12
+ end
13
+
14
+ def change_attribute
15
+ change_column audit_table_name, column_name, column_type, properties_curator if properties_curator.count.positive?
16
+ end
17
+
18
+ def execute
19
+ audit_columns
20
+ audit_changes
21
+ end
22
+
23
+ def find_column(column)
24
+ columns(table_name).each { |col| @column = col if column.name == col.name }
25
+ end
26
+
27
+ # rubocop:disable Metrics/AbcSize:
28
+ def properties_curator
29
+ elements = {}
30
+ find_column(audit_column)
31
+
32
+ elements[:limit] = limit unless audit_column.limit == limit
33
+ elements[:precision] = precision unless audit_column.precision == precision
34
+ elements[:scale] = scale unless audit_column.scale == scale
35
+ elements[:null] = null unless audit_column.null == null
36
+ elements[:default] = default unless audit_column.default == default
37
+
38
+ elements
39
+ end
40
+ # rubocop:enable Metrics/AbcSize:
41
+
42
+ def remove_attribute
43
+ remove_column audit_table_name, audit_column.name unless audit_column.name.include? 'audit'
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ module AuditTables
3
+ class CreateAuditTablesForExistingTables
4
+ attr_reader :klasses
5
+
6
+ def initialize(options)
7
+ @klasses = ActiveRecord::Base.connection.tables
8
+ @klasses -= options
9
+ end
10
+
11
+ def process
12
+ klasses.each do |klass|
13
+ AuditTables::BuildAuditTrigger.new(klass).build
14
+ AuditTables::CreateNewAuditTable.new(klass).build
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ module AuditTables
3
+ class CreateNewAuditTable < Base
4
+ def build
5
+ sync_audit_tables
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module AuditTables
3
+ VERSION = '1.0.0'
4
+ end
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: audit_tables
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Syncordia Technologies
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-01-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 9.0.6
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 9.0.6
41
+ - !ruby/object:Gem::Dependency
42
+ name: faker
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pg
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '='
116
+ - !ruby/object:Gem::Version
117
+ version: 0.42.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '='
123
+ - !ruby/object:Gem::Version
124
+ version: 0.42.0
125
+ description: Adds audit tables and triggers for postgres databases
126
+ email:
127
+ - info@syncordiahealth.ie
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".pairs"
134
+ - ".rspec"
135
+ - ".rubocop.yml"
136
+ - Gemfile
137
+ - LICENSE.txt
138
+ - README.md
139
+ - Rakefile
140
+ - audit_tables.gemspec
141
+ - bin/console
142
+ - bin/setup
143
+ - circle.yml
144
+ - lib/audit_tables.rb
145
+ - lib/audit_tables/base.rb
146
+ - lib/audit_tables/build_audit_trigger.rb
147
+ - lib/audit_tables/change_audit_table.rb
148
+ - lib/audit_tables/create_audit_tables_for_existing_tables.rb
149
+ - lib/audit_tables/create_new_audit_table.rb
150
+ - lib/audit_tables/version.rb
151
+ homepage: https://github.com/syncordiahealth/audit_tables
152
+ licenses:
153
+ - MIT
154
+ metadata: {}
155
+ post_install_message:
156
+ rdoc_options: []
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ requirements: []
170
+ rubyforge_project:
171
+ rubygems_version: 2.5.1
172
+ signing_key:
173
+ specification_version: 4
174
+ summary: Adds audit tables and triggers for postgres databases
175
+ test_files: []