saseo 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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.saseo.standalone_migrations +6 -0
  7. data/.saseo_source.standalone_migrations +6 -0
  8. data/.travis.yml +38 -0
  9. data/Gemfile +4 -0
  10. data/LICENSE +22 -0
  11. data/README.md +38 -0
  12. data/Rakefile +12 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +7 -0
  15. data/db/saseo/migrate/20151028181502_initial_schema.rb +18 -0
  16. data/db/saseo/schema.rb +32 -0
  17. data/db/saseo_source/migrate/20151028181502_initial_schema.rb +16 -0
  18. data/db/saseo_source/schema.rb +30 -0
  19. data/exe/saseo_consumer +6 -0
  20. data/exe/saseo_publisher +6 -0
  21. data/lib/generators/saseo/install_generator.rb +35 -0
  22. data/lib/generators/saseo/templates/add_saseo_trigger.rb.erb +14 -0
  23. data/lib/generators/saseo/templates/add_saseo_trigger_function.rb +105 -0
  24. data/lib/generators/saseo/trigger_generator.rb +42 -0
  25. data/lib/saseo/config/defaults.rb +41 -0
  26. data/lib/saseo/config/saseo_database.yml +14 -0
  27. data/lib/saseo/config/saseo_source_database.yml +14 -0
  28. data/lib/saseo/config.rb +52 -0
  29. data/lib/saseo/extensions/active_record/detector.rb +17 -0
  30. data/lib/saseo/extensions/active_record/patcher.rb +32 -0
  31. data/lib/saseo/extensions/active_record/v_3/connection_adapters/postgresql_adapter.rb +26 -0
  32. data/lib/saseo/extensions/active_record/v_3.rb +11 -0
  33. data/lib/saseo/extensions/active_record/v_4/connection_adapters/postgresql/database_statements.rb +29 -0
  34. data/lib/saseo/extensions/active_record/v_4.rb +11 -0
  35. data/lib/saseo/extensions/active_record.rb +9 -0
  36. data/lib/saseo/extensions.rb +7 -0
  37. data/lib/saseo/models/base.rb +51 -0
  38. data/lib/saseo/models/source/base.rb +22 -0
  39. data/lib/saseo/models/source/version.rb +20 -0
  40. data/lib/saseo/models/version.rb +19 -0
  41. data/lib/saseo/persistence/consumer.rb +25 -0
  42. data/lib/saseo/persistence/persistor.rb +37 -0
  43. data/lib/saseo/persistence.rb +8 -0
  44. data/lib/saseo/publishing/data_change_message.rb +43 -0
  45. data/lib/saseo/publishing/publisher.rb +95 -0
  46. data/lib/saseo/publishing.rb +8 -0
  47. data/lib/saseo/version.rb +3 -0
  48. data/lib/saseo/whodunnit.rb +41 -0
  49. data/lib/saseo.rb +10 -0
  50. data/saseo.example.yml +12 -0
  51. data/saseo.gemspec +34 -0
  52. data/tasks/bump.rake +30 -0
  53. metadata +264 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 13c887bdc257323e0273ef0b9dc529e01ba99bcc
4
+ data.tar.gz: 21131a2fd553dab157facf48ba0e4e7cacb321aa
5
+ SHA512:
6
+ metadata.gz: 0eb41500a2fc709e0aab838e6f724d3922359e91c821f68735ab644d05451f7853ee14937ba328536bf4d5192569a4597cf3cee5d6087321da78774451489605
7
+ data.tar.gz: 352a0efffeeca3687497461015391efb93e4c1aaba33d781dd68970bdc35182603c2c234b1a0b998fdb8ecf2fbe10f55e8f99524e429b44a4c558229298929dd
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.ruby-version/
2
+ /.ruby-gemset/
3
+ /.bundle/
4
+ /.yardoc
5
+ /Gemfile.lock
6
+ /_yardoc/
7
+ /coverage/
8
+ /doc/
9
+ /pkg/
10
+ /spec/reports/
11
+ /tmp/
12
+ /.idea/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ saseo
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2.2
@@ -0,0 +1,6 @@
1
+ db:
2
+ seeds: db/saseo/seeds.rb
3
+ migrate: db/saseo/migrate
4
+ schema: db/saseo/schema.rb
5
+ config:
6
+ database: lib/saseo/config/saseo_database.yml
@@ -0,0 +1,6 @@
1
+ db:
2
+ seeds: db/saseo_source/seeds.rb
3
+ migrate: db/saseo_source/migrate
4
+ schema: db/saseo_source/schema.rb
5
+ config:
6
+ database: lib/saseo/config/saseo_source_database.yml
data/.travis.yml ADDED
@@ -0,0 +1,38 @@
1
+ sudo: false
2
+ language: ruby
3
+ before_install: gem install bundler -v 1.10.6
4
+ rvm:
5
+ - 2.1.5
6
+ - 2.2.0
7
+ - 2.2.1
8
+ - 2.2.2
9
+ - 2.2.3
10
+ - rbx-2
11
+ - jruby-19mode
12
+ - ruby-head
13
+ - jruby-head
14
+ script:
15
+ - bundle exec rake DATABASE=saseo_source DB=test db:create db:migrate && bundle exec rake DATABASE=saseo DB=test db:create db:migrate && DATABASE=saseo bundle exec rspec
16
+ addons:
17
+ postgresql: "9.4"
18
+ code_climate:
19
+ repo_token:
20
+ secure: UdY6NcwRikTo7j9Aj4MViFG9EHB3BUsbHVYsC76hK31CCMkx0ZGik0pEUggZCTSomwJktYQuPupcW63mp3Udyelj/1GILv8FRWnAvtCrbSW255vOBhR7HR9axh3lh9AXiShm5sfMe50JUBeCoTyC3R7G5LkDp1WtPPcvko28JYA429+01BmLayrymt37TYuuFWxhzEjO9fhjezL5ibyOHNzjCOQLBNcEWRwLO1qeIXn82fxabi4fC0ciQqwRQS8yyR2m+s/UUrCePk2Dm0FDvPDL4HSnHGLPzuWvLcvU3wI0g1zpZvBhaBGnYEIvsIfekLzMN86Ke6BbByCorno4Qgu/v08XVbJxIr//efdAeZaZhR6LPee9tM+trBI2nWAovqzFdiD7+09yDgnCYvA5JO3ls9K9YOrNl1Dt1IX/E1Wk5SQtuz+2tmc/NlkEpYAPK6qtW/oGQmw7MS9+s4/BfsB8faVb4CKoJ8sIkpmur+jNJovBDcwya3cD7U5uioV47pdLgO3X1bdFt6s8PovJnIiNVTZsCiCeiIvFXrDrrCsS19S2GVF7m7MRvfNlO1Jp82SthakQmpCsYjxfk0M7zraPvyOoYVc75vd5nUWph+xWYj/jrr8IxOFJmMU2SFTm1EMONeQP1tqkRNwTxqPFnUl1WAI3OZdeCWrpsUwTMC4=
21
+ notifications:
22
+ email:
23
+ on_success: change
24
+ on_failure: change
25
+ hipchat:
26
+ on_success: change
27
+ on_failure: change
28
+ template:
29
+ - "%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}
30
+ | Details: %{build_url} | Changes: %{compare_url}"
31
+ rooms:
32
+ secure: HE3Kx3MzyJFg+uj4EUmQLa1cs5QOLju66W3ao0zFSdfDx1XDrRXNu5sGi9cwKRxxZ2uksD4g7A9cCnnjqgfemB8ktrbyeM6AxI2LqPreUx/zep8+wnTKd3wRcsr8J7zFAZ45Rfa1qnSangUMD/ZuHaaXfI8Nvxcdc+lCiFD2vSiweo5Qt1eURY7gr1+WGw/QeTyuRAAUoSuiJJp8GP7jOxZMbdYWJXcSp7HIIjHOUIw8oaRKBaYpXYxRjdCyFfW3a+B4QnDiizIvoLxdcSyqI5qXvBxGg/5YzSkQkpDUSvNqv8nWYXfE0YgyzL2UItOWnZj77CiL2GHOEyg64bvUk1mGp9ABRxF5f56/vqG5ZzOz2Mnyduvsp4VMhe/LiMmulqdCJSFHA8/Uz9QccL30MpDnPZM13aZ9XRKj76ARDdgIhoLorxaX857xcCrlxgD4+29nx9FS1dWWBzo7r9qUsetdbeGGyp9qbcBa30wo0kxpdNQid5r05t8LnYZRbRwu51vx0oPRRxnpMMpBanBJvrrGJXPNO4LQ1wX4gLsPDuqB3UtlncgjKQvP4ES+N/+3z2pbV429tAqj3TsZ8rpiqJCBvKwTzLeOMluhW6sJBoua5eFDMHKzgQRgreW/joLLoCIsC2N3LVoF0pKktN9L7khSui2hI8r1yzO8lnJugMs=
33
+ matrix:
34
+ allow_failures:
35
+ - rvm: 2.0.0
36
+ - rvm: jruby-19mode
37
+ - rvm: jruby-head
38
+ - rvm: ruby-head
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in saseo.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Avant Credit Corporation
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 all
13
+ 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 THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # Saseo - 사서
2
+ RabbitMQ based PaperTrail replacement
3
+
4
+ [![Build Status](https://travis-ci.org/avantcredit/saseo.png?branch=master)](https://travis-ci.org/avantcredit/saseo)
5
+ [![Dependency Status](https://gemnasium.com/avantcredit/saseo.svg)](https://gemnasium.com/avantcredit/saseo)
6
+ [![Code Climate](https://codeclimate.com/github/avantcredit/saseo/badges/gpa.svg)](https://codeclimate.com/github/avantcredit/saseo)
7
+ [![Test Coverage](https://codeclimate.com/github/avantcredit/saseo/badges/coverage.svg)](https://codeclimate.com/github/avantcredit/saseo)
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'saseo'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install saseo
24
+
25
+ ## Usage
26
+
27
+ TODO: Write usage instructions here
28
+
29
+ ## Development
30
+
31
+ 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.
32
+
33
+ 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).
34
+
35
+ ## Contributing
36
+
37
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/saseo.
38
+
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'standalone_migrations'
4
+
5
+ StandaloneMigrations::Tasks.load_tasks
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task :default => :spec
10
+
11
+ Dir["tasks/**/*.rake"].each { |ext| load ext }
12
+
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "saseo"
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,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,18 @@
1
+ class InitialSchema < ActiveRecord::Migration
2
+ def change
3
+
4
+ enable_extension 'uuid-ossp'
5
+
6
+ create_table 'saseo_versions', id: :uuid, force: true do |t|
7
+ t.integer 'transaction_id', null: false, limit: 8 # bigint
8
+ t.integer 'item_id', null: false
9
+ t.uuid 'item_uuid'
10
+ t.string 'table_name', null: false
11
+ t.string 'action', null: false
12
+ t.datetime 'action_timestamp', null: false
13
+ t.string 'whodunnit', null: false
14
+ t.jsonb 'old_data'
15
+ t.jsonb 'new_data'
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,32 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended that you check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(version: 20151028181502) do
15
+
16
+ # These are extensions that must be enabled in order to support this database
17
+ enable_extension "plpgsql"
18
+ enable_extension "uuid-ossp"
19
+
20
+ create_table "saseo_versions", id: :uuid, default: "uuid_generate_v4()", force: :cascade do |t|
21
+ t.integer "transaction_id", limit: 8, null: false
22
+ t.integer "item_id", null: false
23
+ t.uuid "item_uuid"
24
+ t.string "table_name", null: false
25
+ t.string "action", null: false
26
+ t.datetime "action_timestamp", null: false
27
+ t.string "whodunnit", null: false
28
+ t.jsonb "old_data"
29
+ t.jsonb "new_data"
30
+ end
31
+
32
+ end
@@ -0,0 +1,16 @@
1
+ class InitialSchema < ActiveRecord::Migration
2
+ def change
3
+
4
+ enable_extension 'uuid-ossp'
5
+
6
+ create_table 'saseo_source_versions', id: :uuid, force: true do |t|
7
+ t.integer 'transaction_id', null: false, limit: 8 # bigint
8
+ t.string 'table_name', null: false
9
+ t.string 'action', null: false
10
+ t.datetime 'action_timestamp', null: false
11
+ t.string 'whodunnit', null: false
12
+ t.jsonb 'old_data'
13
+ t.jsonb 'new_data'
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended that you check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(version: 20151028181502) do
15
+
16
+ # These are extensions that must be enabled in order to support this database
17
+ enable_extension "plpgsql"
18
+ enable_extension "uuid-ossp"
19
+
20
+ create_table "saseo_source_versions", id: :uuid, default: "uuid_generate_v4()", force: :cascade do |t|
21
+ t.integer "transaction_id", limit: 8, null: false
22
+ t.string "table_name", null: false
23
+ t.string "action", null: false
24
+ t.datetime "action_timestamp", null: false
25
+ t.string "whodunnit", null: false
26
+ t.jsonb "old_data"
27
+ t.jsonb "new_data"
28
+ end
29
+
30
+ end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ require 'saseo/persistence/consumer'
5
+
6
+ Saseo::Persistence::Consumer.subscribe.endure
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ require 'saseo/publishing/publisher'
5
+ publisher = Saseo::Publishing::Publisher.new
6
+ publisher.run
@@ -0,0 +1,35 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/active_record'
3
+
4
+ module Saseo
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ include ::Rails::Generators::Migration
7
+
8
+ source_root File.expand_path('../templates', __FILE__)
9
+ argument :table_names, type: :array, default: [], banner: 'tables to add triggers to'
10
+
11
+
12
+ desc 'Generates (but does not run) a migration to add the trigger function.'
13
+
14
+ def create_migration_file
15
+ add_saseo_migration('add_saseo_trigger_function')
16
+ Rails::Generators.invoke('saseo:trigger', table_names) unless table_names.empty?
17
+ end
18
+
19
+ def self.next_migration_number(dirname)
20
+ ::ActiveRecord::Generators::Base.next_migration_number(dirname)
21
+ end
22
+
23
+ protected
24
+ def add_saseo_migration(template)
25
+ migration_dir = File.expand_path('db/migrate')
26
+
27
+ unless self.class.migration_exists?(migration_dir, template)
28
+ migration_template "#{template}.rb", "db/migrate/#{template}.rb"
29
+ else
30
+ warn("ALERT: Migration already exists named '#{template}'." +
31
+ " Please check your migrations directory before re-running")
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ class AddSaseoTriggerTo<%= @table_name.camelcase %> < ActiveRecord::Migration
2
+ def up
3
+ # originally copied from:
4
+ # https://wiki.postgresql.org/wiki/Audit_trigger
5
+ trigger_definition = <<SQL
6
+ CREATE TRIGGER <%= @table_name %>_saseo_trigger AFTER INSERT OR UPDATE OR DELETE ON <%= @table_name %> FOR EACH ROW EXECUTE PROCEDURE saseo_audit_func();
7
+ SQL
8
+ execute(trigger_definition)
9
+ end
10
+
11
+ def down
12
+ execute('DROP TRIGGER <%= @table_name %>_saseo_trigger ON <%= @table_name %> CASCADE;')
13
+ end
14
+ end
@@ -0,0 +1,105 @@
1
+ class AddSaseoTriggerFunction < ActiveRecord::Migration
2
+ def up
3
+
4
+ uuid_extension_sql = 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp"'
5
+
6
+ audit_table_sql = <<SQL
7
+ CREATE TABLE saseo_source_versions (
8
+ id uuid PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
9
+ transaction_id bigint NOT NULL,
10
+ table_name text NOT NULL,
11
+ action_timestamp timestamp WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
12
+ action text NOT NULL CHECK (action IN ('INSERT','DELETE','UPDATE')),
13
+ whodunnit text NOT NULL,
14
+ old_data jsonb,
15
+ new_data jsonb
16
+ )
17
+ SQL
18
+
19
+
20
+ # originally copied from:
21
+ # https://wiki.postgresql.org/wiki/Audit_trigger
22
+ #
23
+ # modified to use NOTIFY
24
+ #
25
+ # a trigger must be added to every table
26
+ # CREATE TRIGGER identities_saseo_trigger AFTER INSERT OR UPDATE OR DELETE ON identities FOR EACH ROW EXECUTE PROCEDURE saseo_audit_func();
27
+ whodunnit_sql = <<SQL
28
+ CREATE OR REPLACE FUNCTION saseo_whodunnit() RETURNS TEXT AS $body$
29
+ BEGIN
30
+ return current_setting('saseo.whodunnit');
31
+ EXCEPTION WHEN undefined_object THEN
32
+ return current_user;
33
+ END;
34
+ $body$
35
+ LANGUAGE plpgsql
36
+ SQL
37
+ audit_sql = <<SQL
38
+ CREATE OR REPLACE FUNCTION saseo_audit_func() RETURNS TRIGGER AS $body$
39
+ DECLARE
40
+ v_old_data json;
41
+ v_new_data json;
42
+ v_whodunnit text;
43
+ v_channel text;
44
+ v_audit_uuid uuid;
45
+ BEGIN
46
+ v_whodunnit := saseo_whodunnit();
47
+ v_audit_uuid := uuid_generate_v4();
48
+
49
+ v_channel := upper('SASEO' || '_' || TG_TABLE_NAME::TEXT || '_' || TG_OP || '_AUDIT');
50
+
51
+ IF (TG_OP = 'UPDATE') THEN
52
+ v_old_data := row_to_json(OLD);
53
+ v_new_data := row_to_json(NEW);
54
+
55
+ INSERT INTO saseo_source_versions VALUES(v_audit_uuid, txid_current(), TG_TABLE_NAME, DEFAULT, TG_OP, v_whodunnit, v_old_data::JSONB, v_new_data::JSONB);
56
+ PERFORM pg_notify(v_channel, v_audit_uuid::TEXT);
57
+
58
+ RETURN NEW;
59
+ ELSIF (TG_OP = 'DELETE') THEN
60
+ v_old_data := row_to_json(OLD);
61
+
62
+ INSERT INTO saseo_source_versions VALUES(v_audit_uuid, txid_current(), TG_TABLE_NAME, DEFAULT, TG_OP, v_whodunnit, v_old_data::JSONB, NULL);
63
+ PERFORM pg_notify(v_channel, v_audit_uuid::TEXT);
64
+
65
+ RETURN OLD;
66
+ ELSIF (TG_OP = 'INSERT') THEN
67
+ v_new_data := row_to_json(NEW);
68
+
69
+ INSERT INTO saseo_source_versions VALUES(v_audit_uuid, txid_current(), TG_TABLE_NAME, DEFAULT, TG_OP, v_whodunnit, NULL, v_new_data::JSONB);
70
+ PERFORM pg_notify(v_channel, v_audit_uuid::TEXT);
71
+
72
+ RETURN NEW;
73
+ ELSE
74
+ RAISE WARNING '[SASEO_AUDIT_FUNC] - Other action occurred: %, at %',TG_OP,now();
75
+ RETURN NULL;
76
+ END IF;
77
+
78
+ EXCEPTION
79
+ WHEN data_exception THEN
80
+ RAISE WARNING '[SASEO_AUDIT_FUNC] - UDF ERROR [DATA EXCEPTION] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
81
+ RETURN NULL;
82
+ WHEN unique_violation THEN
83
+ RAISE WARNING '[SASEO_AUDIT_FUNC] - UDF ERROR [UNIQUE] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
84
+ RETURN NULL;
85
+ WHEN OTHERS THEN
86
+ RAISE WARNING '[SASEO_AUDIT_FUNC] - UDF ERROR [OTHER] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
87
+ RETURN NULL;
88
+ END;
89
+ $body$
90
+ LANGUAGE plpgsql
91
+ SQL
92
+ execute(uuid_extension_sql)
93
+ execute(audit_table_sql)
94
+ execute(whodunnit_sql)
95
+ execute(audit_sql)
96
+ end
97
+
98
+ def down
99
+ execute('DROP FUNCTION IF EXISTS saseo_audit_func() CASCADE')
100
+ execute('DROP FUNCTION IF EXISTS saseo_whodunnit() CASCADE')
101
+ execute('DROP TABLE IF EXISTS saseo_source_versions CASCADE')
102
+ execute('DROP EXTENSION IF EXISTS "uuid-ossp" CASCADE')
103
+
104
+ end
105
+ end
@@ -0,0 +1,42 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/active_record'
3
+ require 'saseo/models/source/base'
4
+ require 'saseo/config'
5
+
6
+ module Saseo
7
+ class TriggerGenerator < ::Rails::Generators::Base
8
+ include ::Rails::Generators::Migration
9
+
10
+ source_root File.expand_path('../templates', __FILE__)
11
+ argument :table_names, type: :array, banner: 'tables to add triggers to'
12
+
13
+ desc 'Generates (but does not run) a migration to add the trigger.'
14
+
15
+ def create_migration_file
16
+ tables = table_names.dup
17
+ tables = Saseo::Models::Source::Base.connection.tables if tables.include? 'all'
18
+ tables -= [Saseo.config.source_table_name, Saseo.config.table_name]
19
+
20
+ tables.each do |table_name|
21
+ @table_name = table_name
22
+ add_saseo_migration("add_saseo_trigger")
23
+ end
24
+ end
25
+
26
+ def self.next_migration_number(dirname)
27
+ ::ActiveRecord::Generators::Base.next_migration_number(dirname)
28
+ end
29
+
30
+ protected
31
+ def add_saseo_migration(template)
32
+ migration_dir = File.expand_path('db/migrate')
33
+
34
+ unless self.class.migration_exists?(migration_dir, template)
35
+ migration_template "#{template}.rb.erb", "db/migrate/#{template}_to_#{@table_name}.rb"
36
+ else
37
+ warn("ALERT: Migration already exists named '#{template}'." +
38
+ " Please check your migrations directory before re-running")
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,41 @@
1
+ module Saseo
2
+ class Config
3
+ module Defaults
4
+
5
+ CHANNELS = :all
6
+ SOURCE_DATABASE_URL = nil
7
+ SOURCE_DATABASE_CONFIG_PATH = 'config/database.yml'
8
+ DATABASE_URL = nil
9
+ DATABASE_CONFIG_PATH = 'saseo/config/saseo_database.yml'
10
+ TABLE_NAME = 'saseo_versions'
11
+ SOURCE_TABLE_NAME = 'saseo_source_versions'
12
+ CONSUMER_PHILOTIC_SUBSCRIPTION = 'saseo_audit'
13
+
14
+ def defaults
15
+ @defaults ||= Hash[Saseo::Config::Defaults.constants.map do |c|
16
+ key = c.downcase.to_sym
17
+
18
+ env_key = "#{ENV_PREFIX}_#{key}".upcase
19
+
20
+ [key, ENV[env_key] || Saseo::Config::Defaults.const_get(c)]
21
+ end
22
+ ]
23
+ end
24
+
25
+ def self.included(base)
26
+ Saseo::Config::Defaults.constants.each do |c|
27
+ attr_symbol = c.downcase.to_sym
28
+ base.send(:attr_writer, attr_symbol)
29
+ base.class_eval %Q{
30
+ def #{attr_symbol}
31
+ unless defined? @#{attr_symbol}
32
+ @#{attr_symbol} = defaults[:#{attr_symbol}]
33
+ end
34
+ @#{attr_symbol}
35
+ end
36
+ }
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,14 @@
1
+ defaults: &defaults
2
+ adapter: postgresql
3
+ encoding: utf8
4
+
5
+ development:
6
+ <<: *defaults
7
+ database: saseo_dev
8
+
9
+ test:
10
+ <<: *defaults
11
+ database: saseo_test
12
+ load_seeds: true
13
+ verbosity: silent
14
+ migrate: false
@@ -0,0 +1,14 @@
1
+ defaults: &defaults
2
+ adapter: postgresql
3
+ encoding: utf8
4
+
5
+ development:
6
+ <<: *defaults
7
+ database: saseo_source_dev
8
+
9
+ test:
10
+ <<: *defaults
11
+ database: saseo_source_test
12
+ load_seeds: true
13
+ verbosity: silent
14
+ migrate: false
@@ -0,0 +1,52 @@
1
+ require 'saseo/config/defaults'
2
+ require 'oj'
3
+ require 'yaml'
4
+
5
+ module Saseo
6
+ extend self
7
+ class Config
8
+
9
+ include Defaults
10
+
11
+ ENV_PREFIX = 'SASEO'
12
+
13
+ def initialize(config={})
14
+ load_config config
15
+ end
16
+
17
+ def env
18
+ ENV['SASEO_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'
19
+ end
20
+
21
+ def load_config(config)
22
+ config.each do |k, v|
23
+ mutator = "#{k}="
24
+ send(mutator, v) if respond_to? mutator
25
+ end
26
+ end
27
+
28
+ def load_file(filename, env = 'development')
29
+ config = YAML.load_file(filename)
30
+ load_config(config[env])
31
+ end
32
+
33
+ def channels
34
+ @channels ||= _load_json_config :channels
35
+ end
36
+
37
+ def consumer_philotic_subscription
38
+ @consumer_philotic_subscription ||= _load_json_config :consumer_philotic_subscription
39
+ end
40
+
41
+ private
42
+ def _load_json_config(config)
43
+ value = defaults[config]
44
+ Oj.load(value) rescue value
45
+ end
46
+
47
+ end
48
+
49
+ def config
50
+ @config ||= Saseo::Config.new
51
+ end
52
+ end
@@ -0,0 +1,17 @@
1
+ module Saseo
2
+ module Extensions
3
+ module ActiveRecord
4
+ module Detector
5
+ extend self
6
+ def active_record_version
7
+ return nil unless (Object.const_get('ActiveRecord') rescue nil)
8
+ ::ActiveRecord::VERSION::MAJOR
9
+ end
10
+
11
+ def active_record_detected?
12
+ !!active_record_version
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end