schema_plus_triggers 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6e78e81607d084ffbe2fca6564415bfa98e1044677be1869b0fb1707a2fd32d6
4
+ data.tar.gz: aaf94ee3cd40cb00d5360a1a98f702cad797f22b889d99c75a2dbf1c1184777b
5
+ SHA512:
6
+ metadata.gz: 0fd1787cae0ea894437358e3ee050763e493b3e2d8a716a76774948a6552c64cd6cdaea4faa74d21ab7629a3fed96500ae185cdb908d90e55f1954fecf05ecb6
7
+ data.tar.gz: d23458705d3ada0ad994adc492f439d75938d5bac8f82b34600cda0e054a1779a37df89d540a532bf51166c3a2e2ca71db12cc838247b122110e2490294c74c8
@@ -0,0 +1,9 @@
1
+ /coverage
2
+ /tmp
3
+ /pkg
4
+ /Gemfile.local
5
+
6
+ *.lock
7
+ *.log
8
+ *.sqlite3
9
+ !gemfiles/**/*.sqlite3
@@ -0,0 +1,16 @@
1
+ # This file was auto-generated by the schema_dev tool, based on the data in
2
+ # ./schema_dev.yml
3
+ # Please do not edit this file; any changes will be overwritten next time
4
+ # schema_dev gets run.
5
+ ---
6
+ sudo: false
7
+ rvm:
8
+ - 2.3.1
9
+ gemfile:
10
+ - gemfiles/activerecord-5.2/Gemfile.postgresql
11
+ env: POSTGRESQL_DB_USER=postgres
12
+ addons:
13
+ postgresql: '9.4'
14
+ before_script: bundle exec rake create_databases
15
+ after_script: bundle exec rake drop_databases
16
+ script: bundle exec rake travis
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gemspec
6
+
7
+ gemfile_local = File.expand_path '../Gemfile.local', __FILE__
8
+ eval File.read(gemfile_local), binding, gemfile_local if File.exist? gemfile_local
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2020 Edward Rudd
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,127 @@
1
+ [![Gem Version](https://badge.fury.io/rb/schema_plus_triggers.svg)](http://badge.fury.io/rb/schema_plus_triggers)
2
+ [![Build Status](https://secure.travis-ci.org/SchemaPlus/schema_plus_triggers.svg)](http://travis-ci.org/SchemaPlus/schema_plus_triggers)
3
+ [![Coverage Status](https://img.shields.io/coveralls/SchemaPlus/schema_plus_triggers.svg)](https://coveralls.io/r/SchemaPlus/schema_plus_triggers)
4
+ [![Dependency Status](https://gemnasium.com/SchemaPlus/schema_plus_triggers.svg)](https://gemnasium.com/SchemaPlus/schema_plus_triggers)
5
+
6
+ # SchemaPlus::Triggers
7
+
8
+ ScemaPlus::Triggers adds support for SQL triggers in ActiveRecord.
9
+
10
+ SchemaPlus::Triggers is part of the [SchemaPlus](https://github.com/SchemaPlus/) family of Ruby on Rails ActiveRecord extension gems.
11
+
12
+ ## Installation
13
+
14
+ <!-- SCHEMA_DEV: TEMPLATE INSTALLATION - begin -->
15
+ <!-- These lines are auto-inserted from a schema_dev template -->
16
+ As usual:
17
+
18
+ ```ruby
19
+ gem "schema_plus_triggers" # in a Gemfile
20
+ gem.add_dependency "schema_plus_triggers" # in a .gemspec
21
+ ```
22
+
23
+ <!-- SCHEMA_DEV: TEMPLATE INSTALLATION - end -->
24
+
25
+ ## Compatibility
26
+
27
+ SchemaPlus::Triggers is tested on:
28
+
29
+ <!-- SCHEMA_DEV: MATRIX - begin -->
30
+ <!-- These lines are auto-generated by schema_dev based on schema_dev.yml -->
31
+ * ruby **2.3.1** with activerecord **5.2**, using **postgresql**
32
+
33
+ <!-- SCHEMA_DEV: MATRIX - end -->
34
+
35
+ ## Usage
36
+
37
+ ### Note for PostgreSQL
38
+
39
+ You will need to also add the schema_plus_functions gem and define your trigger function.
40
+
41
+ create_function :my_trigger_func, '', <<-END
42
+ RETURNS trigger
43
+ LANGUAGE plpgsql
44
+ AS $$
45
+ BEGIN
46
+ BEGIN
47
+ IF (TG_OP = 'DELETE') THEN
48
+ INSERT INTO log (operation, log) VALUES ('DELETE', OLD.name);
49
+ ELSEIF (TG_OP = 'UPDATE') THEN
50
+ INSERT INTO log (operation, log) VALUES ('UPDATE', OLD.name || ' to ' || NEW.name);
51
+ ELSEIF (TG_OP = 'INSERT') THEN
52
+ INSERT INTO log (operation, log) VALUES ('INSERT', NEW.name);
53
+ END IF;
54
+ END;
55
+ END;
56
+ $$
57
+ END
58
+
59
+ ### Migrations
60
+
61
+ To declare a trigger use `create_trigger`:
62
+
63
+ create_trigger :my_table, :my_trigger, 'after insert', 'for each row execute procedure my_trigger_func()'
64
+
65
+ To drop a trigger use `drop_trigger`:
66
+
67
+ drop_trigger :my_table, :my_trigger
68
+
69
+ ### Introspection
70
+
71
+ You can query the list of triggers defined at the connection level (uncached):
72
+
73
+ connection.triggers
74
+
75
+ This will return an array of arrays. The inner array containing the table name and the trigger name.
76
+
77
+ ## History
78
+
79
+ * 0.1.0 - Initial release
80
+
81
+ ## Development & Testing
82
+
83
+ Are you interested in contributing to SchemaPlus::Triggers? Thanks! Please follow
84
+ the standard protocol: fork, feature branch, develop, push, and issue pull
85
+ request.
86
+
87
+ Some things to know about to help you develop and test:
88
+
89
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - begin -->
90
+ <!-- These lines are auto-inserted from a schema_dev template -->
91
+ * **schema_dev**: SchemaPlus::Triggers uses [schema_dev](https://github.com/SchemaPlus/schema_dev) to
92
+ facilitate running rspec tests on the matrix of ruby, activerecord, and database
93
+ versions that the gem supports, both locally and on
94
+ [travis-ci](http://travis-ci.org/SchemaPlus/schema_plus_triggers)
95
+
96
+ To to run rspec locally on the full matrix, do:
97
+
98
+ $ schema_dev bundle install
99
+ $ schema_dev rspec
100
+
101
+ You can also run on just one configuration at a time; For info, see `schema_dev --help` or the [schema_dev](https://github.com/SchemaPlus/schema_dev) README.
102
+
103
+ The matrix of configurations is specified in `schema_dev.yml` in
104
+ the project root.
105
+
106
+
107
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - end -->
108
+
109
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - begin -->
110
+ <!-- These lines are auto-inserted from a schema_dev template -->
111
+ * **schema_plus_core**: SchemaPlus::Triggers uses the SchemaPlus::Core API that
112
+ provides middleware callback stacks to make it easy to extend
113
+ ActiveRecord's behavior. If that API is missing something you need for
114
+ your contribution, please head over to
115
+ [schema_plus_core](https://github.com/SchemaPlus/schema_plus_core) and open
116
+ an issue or pull request.
117
+
118
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - end -->
119
+
120
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_MONKEY - begin -->
121
+ <!-- These lines are auto-inserted from a schema_dev template -->
122
+ * **schema_monkey**: SchemaPlus::Triggers is implemented as a
123
+ [schema_monkey](https://github.com/SchemaPlus/schema_monkey) client,
124
+ using [schema_monkey](https://github.com/SchemaPlus/schema_monkey)'s
125
+ convention-based protocols for extending ActiveRecord and using middleware stacks.
126
+
127
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_MONKEY - end -->
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'schema_dev/tasks'
7
+
8
+ task :default => :spec
9
+
10
+ require 'rspec/core/rake_task'
11
+ RSpec::Core::RakeTask.new(:spec)
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+ gemspec :path => File.expand_path('..', __FILE__)
3
+
4
+ File.exist?(gemfile_local = File.expand_path('../Gemfile.local', __FILE__)) and eval File.read(gemfile_local), binding, gemfile_local
@@ -0,0 +1,3 @@
1
+ eval File.read File.expand_path('../../Gemfile.base', __FILE__)
2
+
3
+ gem "activerecord", ">= 5.2.0.beta0", "< 5.3"
@@ -0,0 +1,10 @@
1
+ require "pathname"
2
+ eval(Pathname.new(__FILE__).dirname.join("Gemfile.base").read, binding)
3
+
4
+ platform :ruby do
5
+ gem "pg"
6
+ end
7
+
8
+ platform :jruby do
9
+ gem 'activerecord-jdbcpostgresql-adapter'
10
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'schema_plus/core'
4
+
5
+ require_relative 'triggers/version'
6
+ require_relative 'triggers/active_record/connection_adapters/abstract_adapter'
7
+ require_relative 'triggers/active_record/migration/command_recorder'
8
+ require_relative 'triggers/middleware'
9
+
10
+ module SchemaPlus::Triggers
11
+ module ActiveRecord
12
+ module ConnectionAdapters
13
+ autoload :PostgresqlAdapter, 'schema_plus/triggers/active_record/connection_adapters/postgresql_adapter'
14
+ end
15
+ end
16
+ end
17
+
18
+ SchemaMonkey.register SchemaPlus::Triggers
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SchemaPlus::Triggers
4
+ module ActiveRecord
5
+ module ConnectionAdapters
6
+ module AbstractAdapter
7
+ # Create a trigger. Valid options are :force
8
+ def create_trigger(table_name, trigger_name, triggers, definition, options = {})
9
+ SchemaMonkey::Middleware::Migration::CreateTrigger.start(connection: self, table_name: table_name, trigger_name: trigger_name, triggers: triggers, definition: definition, options: options) do |env|
10
+ table_name = env.table_name
11
+ trigger_name = env.trigger_name
12
+ triggers = env.triggers
13
+ definition = env.definition
14
+ options = env.options
15
+
16
+ definition = definition.to_sql if definition.respond_to? :to_sql
17
+ if options[:force]
18
+ drop_trigger(table_name, trigger_name, if_exists: true)
19
+ end
20
+
21
+ execute "CREATE TRIGGER #{quote_table_name(trigger_name)} #{triggers} ON #{quote_table_name(table_name)} #{definition}"
22
+ end
23
+ end
24
+
25
+ # Remove a trigger. Valid options are :if_exists
26
+ # and :cascade
27
+ #
28
+ # drop_trigger 'my_table', 'trigger_name', if_exists: true
29
+ def drop_trigger(table_name, trigger_name, options = {})
30
+ SchemaMonkey::Middleware::Migration::CreateTrigger.start(connection: self, table_name: table_name, trigger_name: trigger_name, options: options) do |env|
31
+ table_name = env.table_name
32
+ trigger_name = env.trigger_name
33
+ options = env.options
34
+
35
+ sql = "DROP TRIGGER"
36
+ sql += " IF EXISTS" if options[:if_exists]
37
+ sql += " #{quote_table_name(trigger_name)} ON #{quote_table_name(table_name)}"
38
+ sql += " CASCADE" if options[:cascade]
39
+
40
+ execute sql
41
+ end
42
+ end
43
+
44
+ #####################################################################
45
+ #
46
+ # The functions below here are abstract; each subclass should
47
+ # define them all. Defining them here only for reference.
48
+ #
49
+
50
+ # (abstract) Return the Trigger objects for triggers
51
+ def triggers(name = nil)
52
+ raise "Internal Error: Connection adapter did not override abstract function"
53
+ end
54
+
55
+ # (abstract) Return the Trigger definition
56
+ def trigger_definition(table_name, trigger_name, name = nil)
57
+ raise "Internal Error: Connection adapter did not override abstract function"
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SchemaPlus::Triggers
4
+ module ActiveRecord
5
+ module ConnectionAdapters
6
+ module PostgresqlAdapter
7
+ def triggers(name = nil) #:nodoc:
8
+ SchemaMonkey::Middleware::Schema::Triggers.start(connection: self, query_name: name, triggers: []) do |env|
9
+ sql = <<-SQL
10
+ SELECT relname as table_name, tgname as trigger_name
11
+ FROM pg_trigger T
12
+ JOIN pg_class C ON C.oid = T.tgrelid
13
+ WHERE tgisinternal = FALSE
14
+ AND relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (current_schemas(false)))
15
+ ORDER BY 1, 2
16
+ SQL
17
+
18
+ env.triggers += env.connection.query(sql, env.query_name).map { |row| [row[0], row[1]] }
19
+ end.triggers
20
+ end
21
+
22
+ def trigger_definition(table_name, trigger_name, name = nil) #:nodoc:
23
+ data = SchemaMonkey::Middleware::Schema::TriggerDefinition.start(connection: self, table_name: table_name, trigger_name: trigger_name, query_name: name) do |env|
24
+ result = env.connection.query(<<-SQL, env.query_name)
25
+ SELECT pg_get_triggerdef(T.oid)
26
+ FROM pg_trigger T
27
+ JOIN pg_class C ON C.oid = T.tgrelid
28
+ WHERE tgisinternal = FALSE
29
+ AND relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (current_schemas(false)))
30
+ AND tgname = '#{quote_string(trigger_name)}'
31
+ AND relname = '#{quote_string(table_name)}'
32
+ SQL
33
+
34
+ row = result.first
35
+ unless row.nil?
36
+ sql = row.first
37
+
38
+ m = sql.match(/CREATE.+?TRIGGER\s+"?\w+"?\s+(.+?) ON\s+[\w\."]+\s+(.+)/)
39
+
40
+ env.trigger = m[1]
41
+ env.definition = m[2]
42
+ end
43
+ end
44
+
45
+ return data.trigger, data.definition
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SchemaPlus::Triggers
4
+ module ActiveRecord
5
+ module Migration
6
+ module CommandRecorder
7
+ def create_trigger(*args, &block)
8
+ record(:create_trigger, args, &block)
9
+ end
10
+
11
+ def drop_trigger(*args, &block)
12
+ record(:drop_trigger, args, &block)
13
+ end
14
+
15
+ def invert_create_trigger(args)
16
+ [:drop_trigger, [args.first, args.second]]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SchemaPlus::Triggers
4
+ module Middleware
5
+ module Dumper
6
+ module Tables
7
+ # Dump
8
+ def after(env)
9
+ env.connection.triggers.each do |table_name, trigger_name|
10
+ next if env.dumper.ignored?(table_name)
11
+ trigger, definition = env.connection.trigger_definition(table_name, trigger_name)
12
+ heredelim = "END_TRIGGER_#{table_name.upcase}_#{trigger_name.upcase}"
13
+ statement = <<~ENDTRIGGER
14
+ create_trigger "#{table_name}", "#{trigger_name}", "#{trigger}", <<-'#{heredelim}', :force => true
15
+ #{definition}
16
+ #{heredelim}
17
+
18
+ ENDTRIGGER
19
+
20
+ env.dump.final << statement
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ module Schema
27
+ module Triggers
28
+ ENV = [:connection, :query_name, :triggers]
29
+ end
30
+
31
+ module TriggerDefinition
32
+ ENV = [:connection, :table_name, :trigger_name, :query_name, :trigger, :definition]
33
+ end
34
+ end
35
+
36
+ module Migration
37
+ module CreateTrigger
38
+ ENV = [:connection, :table_name, :trigger_name, :triggers, :definition, :options]
39
+ end
40
+
41
+ module DropTrigger
42
+ ENV = [:connection, :table_name, :trigger_name, :options]
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SchemaPlus
4
+ module Triggers
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'schema_plus/triggers'
@@ -0,0 +1,6 @@
1
+ ruby:
2
+ - 2.3.1
3
+ activerecord:
4
+ - 5.2
5
+ db:
6
+ - postgresql
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'schema_plus/triggers/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = "schema_plus_triggers"
9
+ gem.version = SchemaPlus::Triggers::VERSION
10
+ gem.authors = ["Edward Rudd"]
11
+ gem.email = ["urkle@outoforder.cc"]
12
+ gem.summary = %q{Adds support for triggers in ActiveRecord}
13
+ gem.description = %q{Adds support for triggers in ActiveRecord}
14
+ gem.homepage = "https://github.com/SchemaPlus/schema_plus_triggers"
15
+ gem.license = "MIT"
16
+
17
+ gem.files = `git ls-files -z`.split("\x0")
18
+ gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
+ gem.require_paths = ["lib"]
21
+
22
+ gem.add_dependency "activerecord", ">= 5.2", '< 5.3'
23
+ gem.add_dependency "schema_plus_core", "~> 2.2", ">= 2.2.3"
24
+
25
+ gem.add_development_dependency "bundler"
26
+ gem.add_development_dependency "rake", "~> 10.0"
27
+ gem.add_development_dependency "rspec", "~> 3.0"
28
+ gem.add_development_dependency "schema_dev", "~> 3.11", ">= 3.11.1"
29
+ gem.add_development_dependency "schema_plus_compatibility", "~> 0.2"
30
+ gem.add_development_dependency "simplecov"
31
+ gem.add_development_dependency "simplecov-gem-profile"
32
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe ActiveRecord::Migration do
6
+ before do
7
+ define_schema do
8
+ create_table :user do |t|
9
+ t.string :name, null: false
10
+ end
11
+
12
+ create_table :log do |t|
13
+ t.string :operation
14
+ t.string :log
15
+ end
16
+
17
+ # manual SQL so we do not need to depend on schema_plus_functions for testing
18
+ execute <<-SQL
19
+ CREATE OR REPLACE FUNCTION my_trigger_func() RETURNS trigger LANGUAGE plpgsql AS $$
20
+ BEGIN
21
+ IF (TG_OP = 'DELETE') THEN
22
+ INSERT INTO log (operation, log) VALUES ('DELETE', OLD.name);
23
+ ELSEIF (TG_OP = 'UPDATE') THEN
24
+ INSERT INTO log (operation, log) VALUES ('UPDATE', OLD.name || ' to ' || NEW.name);
25
+ ELSEIF (TG_OP = 'INSERT') THEN
26
+ INSERT INTO log (operation, log) VALUES ('INSERT', NEW.name);
27
+ END IF;
28
+ END;
29
+ $$
30
+ SQL
31
+ end
32
+ end
33
+
34
+ after do
35
+ apply_migration do
36
+ execute 'DROP FUNCTION my_trigger_func() CASCADE'
37
+ end
38
+ end
39
+
40
+ it "creates the trigger on the table" do
41
+ apply_migration do
42
+ create_trigger :user, :log_trigger, 'after insert or update or delete', 'for each row execute procedure my_trigger_func()'
43
+ end
44
+
45
+ expect(triggers('user')).to include(['user', 'log_trigger'])
46
+ end
47
+
48
+ protected
49
+
50
+ def triggers(table)
51
+ ActiveRecord::Base.connection.triggers.select { |(t, _)| t == table }
52
+ end
53
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'stringio'
5
+
6
+ describe "Schema dump" do
7
+ before do
8
+ define_schema do
9
+ create_table :user do |t|
10
+ t.string :name, null: false
11
+ end
12
+
13
+ create_table :log do |t|
14
+ t.string :operation
15
+ t.string :log
16
+ end
17
+
18
+ execute <<-SQL
19
+ CREATE OR REPLACE FUNCTION my_trigger_func() RETURNS trigger LANGUAGE plpgsql AS $$
20
+ BEGIN
21
+ IF (TG_OP = 'DELETE') THEN
22
+ INSERT INTO log (operation, log) VALUES ('DELETE', OLD.name);
23
+ ELSEIF (TG_OP = 'UPDATE') THEN
24
+ INSERT INTO log (operation, log) VALUES ('UPDATE', OLD.name || ' to ' || NEW.name);
25
+ ELSEIF (TG_OP = 'INSERT') THEN
26
+ INSERT INTO log (operation, log) VALUES ('INSERT', NEW.name);
27
+ END IF;
28
+ END;
29
+ $$
30
+ SQL
31
+ end
32
+ end
33
+
34
+ after do
35
+ apply_migration do
36
+ execute 'DROP FUNCTION my_trigger_func() CASCADE'
37
+ end
38
+ end
39
+
40
+ it "includes the trigger definition" do
41
+ apply_migration do
42
+ create_trigger :user, :log_trigger, 'after insert or update or delete', 'for each row execute procedure my_trigger_func()'
43
+ end
44
+
45
+ dump_schema.tap do |dump|
46
+ expect(dump).to match(/create_trigger.+user.+log_trigger.+after insert/i)
47
+
48
+ expect(dump).to match(/for each row.+my_trigger_func/i)
49
+ end
50
+
51
+ end
52
+
53
+ protected
54
+
55
+ def dump_schema(opts = {})
56
+ stream = StringIO.new
57
+
58
+ ActiveRecord::SchemaDumper.ignore_tables = Array.wrap(opts[:ignore]) || []
59
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
60
+
61
+ stream.string
62
+ end
63
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'simplecov'
4
+ require 'simplecov-gem-profile'
5
+ SimpleCov.start "gem"
6
+
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
+
10
+ require 'rspec'
11
+ require 'active_record'
12
+ require 'schema_plus_triggers'
13
+ require 'schema_plus_compatibility'
14
+ require 'schema_dev/rspec'
15
+
16
+ SchemaDev::Rspec.setup
17
+
18
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
19
+
20
+ RSpec.configure do |config|
21
+ config.warnings = true
22
+ config.around(:each) do |example|
23
+ ActiveRecord::Migration.suppress_messages do
24
+ begin
25
+ example.run
26
+ ensure
27
+ ActiveRecord::Base.connection.tables_only.each do |table|
28
+ ActiveRecord::Migration.drop_table table, force: :cascade
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def define_schema(config = {}, &block)
36
+ ActiveRecord::Migration.suppress_messages do
37
+ ActiveRecord::Schema.define do
38
+ ActiveRecord::Base.connection.tables_only.each do |table|
39
+ ActiveRecord::Migration.drop_table table, force: :cascade
40
+ end
41
+ instance_eval &block
42
+ end
43
+ end
44
+ end
45
+
46
+ def apply_migration(config = {}, &block)
47
+ ActiveRecord::Schema.define do
48
+ instance_eval &block
49
+ end
50
+ end
51
+
52
+ SimpleCov.command_name "[ruby#{RUBY_VERSION}-activerecord#{::ActiveRecord.version}-#{ActiveRecord::Base.connection.adapter_name}]"
metadata ADDED
@@ -0,0 +1,211 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: schema_plus_triggers
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Edward Rudd
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-08-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.3'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '5.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.3'
33
+ - !ruby/object:Gem::Dependency
34
+ name: schema_plus_core
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.2'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 2.2.3
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '2.2'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 2.2.3
53
+ - !ruby/object:Gem::Dependency
54
+ name: bundler
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ - !ruby/object:Gem::Dependency
68
+ name: rake
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '10.0'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '10.0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: rspec
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '3.0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '3.0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: schema_dev
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '3.11'
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: 3.11.1
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '3.11'
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: 3.11.1
115
+ - !ruby/object:Gem::Dependency
116
+ name: schema_plus_compatibility
117
+ requirement: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - "~>"
120
+ - !ruby/object:Gem::Version
121
+ version: '0.2'
122
+ type: :development
123
+ prerelease: false
124
+ version_requirements: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - "~>"
127
+ - !ruby/object:Gem::Version
128
+ version: '0.2'
129
+ - !ruby/object:Gem::Dependency
130
+ name: simplecov
131
+ requirement: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ type: :development
137
+ prerelease: false
138
+ version_requirements: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ - !ruby/object:Gem::Dependency
144
+ name: simplecov-gem-profile
145
+ requirement: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ description: Adds support for triggers in ActiveRecord
158
+ email:
159
+ - urkle@outoforder.cc
160
+ executables: []
161
+ extensions: []
162
+ extra_rdoc_files: []
163
+ files:
164
+ - ".gitignore"
165
+ - ".travis.yml"
166
+ - Gemfile
167
+ - LICENSE.txt
168
+ - README.md
169
+ - Rakefile
170
+ - gemfiles/Gemfile.base
171
+ - gemfiles/activerecord-5.2/Gemfile.base
172
+ - gemfiles/activerecord-5.2/Gemfile.postgresql
173
+ - lib/schema_plus/triggers.rb
174
+ - lib/schema_plus/triggers/active_record/connection_adapters/abstract_adapter.rb
175
+ - lib/schema_plus/triggers/active_record/connection_adapters/postgresql_adapter.rb
176
+ - lib/schema_plus/triggers/active_record/migration/command_recorder.rb
177
+ - lib/schema_plus/triggers/middleware.rb
178
+ - lib/schema_plus/triggers/version.rb
179
+ - lib/schema_plus_triggers.rb
180
+ - schema_dev.yml
181
+ - schema_plus_triggers.gemspec
182
+ - spec/migration_spec.rb
183
+ - spec/schema_dumper_spec.rb
184
+ - spec/spec_helper.rb
185
+ homepage: https://github.com/SchemaPlus/schema_plus_triggers
186
+ licenses:
187
+ - MIT
188
+ metadata: {}
189
+ post_install_message:
190
+ rdoc_options: []
191
+ require_paths:
192
+ - lib
193
+ required_ruby_version: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ required_rubygems_version: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ requirements: []
204
+ rubygems_version: 3.0.6
205
+ signing_key:
206
+ specification_version: 4
207
+ summary: Adds support for triggers in ActiveRecord
208
+ test_files:
209
+ - spec/migration_spec.rb
210
+ - spec/schema_dumper_spec.rb
211
+ - spec/spec_helper.rb