fx-jets 0.6.3s

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 (95) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.hound.yml +2 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +648 -0
  6. data/.travis.yml +60 -0
  7. data/.yardopts +4 -0
  8. data/Appraisals +45 -0
  9. data/CONTRIBUTING.md +15 -0
  10. data/Gemfile +4 -0
  11. data/LICENSE +18 -0
  12. data/README.md +1 -0
  13. data/Rakefile +23 -0
  14. data/bin/appraisal +17 -0
  15. data/bin/console +14 -0
  16. data/bin/rake +17 -0
  17. data/bin/rspec +17 -0
  18. data/bin/setup +13 -0
  19. data/bin/yard +17 -0
  20. data/fx.gemspec +39 -0
  21. data/gemfiles/rails42.gemfile +10 -0
  22. data/gemfiles/rails50.gemfile +8 -0
  23. data/gemfiles/rails51.gemfile +8 -0
  24. data/gemfiles/rails52.gemfile +8 -0
  25. data/gemfiles/rails60.gemfile +8 -0
  26. data/gemfiles/rails61.gemfile +8 -0
  27. data/gemfiles/rails_edge.gemfile +8 -0
  28. data/lib/fx/adapters/postgres/connection.rb +16 -0
  29. data/lib/fx/adapters/postgres/functions.rb +59 -0
  30. data/lib/fx/adapters/postgres/triggers.rb +57 -0
  31. data/lib/fx/adapters/postgres.rb +167 -0
  32. data/lib/fx/command_recorder/arguments.rb +43 -0
  33. data/lib/fx/command_recorder/function.rb +30 -0
  34. data/lib/fx/command_recorder/trigger.rb +30 -0
  35. data/lib/fx/command_recorder.rb +24 -0
  36. data/lib/fx/configuration.rb +48 -0
  37. data/lib/fx/definition.rb +46 -0
  38. data/lib/fx/function.rb +26 -0
  39. data/lib/fx/railtie.rb +15 -0
  40. data/lib/fx/schema_dumper/function.rb +38 -0
  41. data/lib/fx/schema_dumper/trigger.rb +29 -0
  42. data/lib/fx/schema_dumper.rb +10 -0
  43. data/lib/fx/statements/function.rb +115 -0
  44. data/lib/fx/statements/trigger.rb +146 -0
  45. data/lib/fx/statements.rb +11 -0
  46. data/lib/fx/trigger.rb +26 -0
  47. data/lib/fx/version.rb +4 -0
  48. data/lib/fx.rb +43 -0
  49. data/lib/generators/fx/function/USAGE +11 -0
  50. data/lib/generators/fx/function/function_generator.rb +120 -0
  51. data/lib/generators/fx/function/templates/db/migrate/create_function.erb +5 -0
  52. data/lib/generators/fx/function/templates/db/migrate/update_function.erb +5 -0
  53. data/lib/generators/fx/trigger/USAGE +20 -0
  54. data/lib/generators/fx/trigger/templates/db/migrate/create_trigger.erb +5 -0
  55. data/lib/generators/fx/trigger/templates/db/migrate/update_trigger.erb +5 -0
  56. data/lib/generators/fx/trigger/trigger_generator.rb +130 -0
  57. data/lib/generators.rb +11 -0
  58. data/spec/acceptance/user_manages_functions_spec.rb +57 -0
  59. data/spec/acceptance/user_manages_triggers_spec.rb +51 -0
  60. data/spec/acceptance_helper.rb +62 -0
  61. data/spec/dummy/.gitignore +16 -0
  62. data/spec/dummy/Rakefile +13 -0
  63. data/spec/dummy/bin/bundle +3 -0
  64. data/spec/dummy/bin/rails +4 -0
  65. data/spec/dummy/bin/rake +4 -0
  66. data/spec/dummy/config/application.rb +15 -0
  67. data/spec/dummy/config/boot.rb +5 -0
  68. data/spec/dummy/config/database.yml +9 -0
  69. data/spec/dummy/config/environment.rb +5 -0
  70. data/spec/dummy/config.ru +4 -0
  71. data/spec/dummy/db/migrate/.keep +0 -0
  72. data/spec/features/functions/migrations_spec.rb +65 -0
  73. data/spec/features/functions/revert_spec.rb +75 -0
  74. data/spec/features/triggers/migrations_spec.rb +56 -0
  75. data/spec/features/triggers/revert_spec.rb +95 -0
  76. data/spec/fx/adapters/postgres/functions_spec.rb +37 -0
  77. data/spec/fx/adapters/postgres/triggers_spec.rb +45 -0
  78. data/spec/fx/adapters/postgres_spec.rb +146 -0
  79. data/spec/fx/command_recorder/arguments_spec.rb +41 -0
  80. data/spec/fx/command_recorder_spec.rb +171 -0
  81. data/spec/fx/configuration_spec.rb +21 -0
  82. data/spec/fx/definition_spec.rb +134 -0
  83. data/spec/fx/function_spec.rb +68 -0
  84. data/spec/fx/schema_dumper/function_spec.rb +80 -0
  85. data/spec/fx/schema_dumper/trigger_spec.rb +40 -0
  86. data/spec/fx/statements/function_spec.rb +103 -0
  87. data/spec/fx/statements/trigger_spec.rb +132 -0
  88. data/spec/fx/trigger_spec.rb +55 -0
  89. data/spec/generators/fx/function/function_generator_spec.rb +46 -0
  90. data/spec/generators/fx/trigger/trigger_generator_spec.rb +59 -0
  91. data/spec/spec_helper.rb +21 -0
  92. data/spec/support/definition_helpers.rb +37 -0
  93. data/spec/support/generator_setup.rb +11 -0
  94. data/spec/support/migration_helpers.rb +25 -0
  95. metadata +357 -0
@@ -0,0 +1,62 @@
1
+ require "bundler"
2
+
3
+ ENV["RAILS_ENV"] = "test"
4
+
5
+ RSpec.configure do |config|
6
+ config.around(:each) do |example|
7
+ Dir.chdir("spec/dummy") do
8
+ example.run
9
+ end
10
+ end
11
+
12
+ config.before(:suite) do
13
+ Dir.chdir("spec/dummy") do
14
+ system <<-CMD
15
+ git init 1>/dev/null &&
16
+ git add -A &&
17
+ git commit --no-gpg-sign --message 'initial' 1>/dev/null
18
+ CMD
19
+ end
20
+ end
21
+
22
+ config.after(:suite) do
23
+ Dir.chdir("spec/dummy") do
24
+ ActiveRecord::Base.connection.disconnect!
25
+ system <<-CMD
26
+ echo &&
27
+ rake db:environment:set db:drop db:create &&
28
+ git add -A &&
29
+ git reset --hard HEAD 1>/dev/null &&
30
+ rm -rf .git/ 1>/dev/null
31
+ CMD
32
+ end
33
+ end
34
+
35
+ def successfully(command)
36
+ `RAILS_ENV=test #{command}`
37
+ expect($?.exitstatus).to eq(0), "'#{command}' was unsuccessful"
38
+ end
39
+
40
+ def write_function_definition(file, contents)
41
+ write_definition(file, contents, "functions")
42
+ end
43
+
44
+ def write_trigger_definition(file, contents)
45
+ write_definition(file, contents, "triggers")
46
+ end
47
+
48
+ def write_definition(file, contents, directory)
49
+ File.open("db/#{directory}/#{file}.sql", File::WRONLY) do |definition|
50
+ definition.truncate(0)
51
+ definition.write(contents)
52
+ end
53
+ end
54
+
55
+ def verify_identical_definitions(def_a, def_b)
56
+ successfully "cmp #{def_a} #{def_b}"
57
+ end
58
+
59
+ def execute(command)
60
+ ActiveRecord::Base.connection.execute(command).first
61
+ end
62
+ end
@@ -0,0 +1,16 @@
1
+ # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile '~/.gitignore_global'
6
+
7
+ # Ignore bundler config.
8
+ /.bundle
9
+
10
+ # Ignore the default SQLite database.
11
+ /db/*.sqlite3
12
+ /db/*.sqlite3-journal
13
+
14
+ # Ignore all logfiles and tempfiles.
15
+ /log/*.log
16
+ /tmp
@@ -0,0 +1,13 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Jets.application.load_tasks
7
+
8
+ unless Rake::Task.task_defined?('db:environment:set')
9
+ desc 'dummy task for rails versions where this task does not exist'
10
+ task 'db:environment:set' do
11
+ # no-op
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
+ load Gem.bin_path('bundler', 'bundle')
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
3
+ require_relative '../config/boot'
4
+ require 'rails/commands'
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../config/boot'
3
+ require 'rake'
4
+ Rake.application.run
@@ -0,0 +1,15 @@
1
+ require File.expand_path("../boot", __FILE__)
2
+
3
+ # Pick the frameworks you want:
4
+ require "active_record/railtie"
5
+
6
+ Bundler.require(*Jets.groups)
7
+ require "fx"
8
+
9
+ module Dummy
10
+ class Application < Rails::Application
11
+ config.cache_classes = true
12
+ config.eager_load = false
13
+ config.active_support.deprecation = :stderr
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ # Set up gems listed in the Gemfile.
2
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../../Gemfile", __FILE__)
3
+
4
+ require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
5
+ $LOAD_PATH.unshift File.expand_path("../../../../lib", __FILE__)
@@ -0,0 +1,9 @@
1
+ development: &default
2
+ adapter: postgresql
3
+ database: dummy_development
4
+ encoding: unicode
5
+ pool: 5
6
+
7
+ test:
8
+ <<: *default
9
+ database: dummy_test
@@ -0,0 +1,5 @@
1
+ # Load the Rails application.
2
+ require File.expand_path("../application", __FILE__)
3
+
4
+ # Initialize the Rails application.
5
+ Jets.application.initialize!
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Jets.application
File without changes
@@ -0,0 +1,65 @@
1
+ require "spec_helper"
2
+
3
+ describe "Function migrations", :db do
4
+ around do |example|
5
+ sql_definition = <<-EOS
6
+ CREATE OR REPLACE FUNCTION test()
7
+ RETURNS text AS $$
8
+ BEGIN
9
+ RETURN 'test';
10
+ END;
11
+ $$ LANGUAGE plpgsql;
12
+ EOS
13
+ with_function_definition(name: :test, sql_definition: sql_definition) do
14
+ example.run
15
+ end
16
+ end
17
+
18
+ it "can run migrations that create functions" do
19
+ migration = Class.new(migration_class) do
20
+ def up
21
+ create_function :test
22
+ end
23
+ end
24
+
25
+ expect { run_migration(migration, :up) }.not_to raise_error
26
+ end
27
+
28
+ it "can run migrations that drop functions" do
29
+ connection.create_function(:test)
30
+
31
+ migration = Class.new(migration_class) do
32
+ def up
33
+ drop_function :test
34
+ end
35
+ end
36
+
37
+ expect { run_migration(migration, :up) }.not_to raise_error
38
+ end
39
+
40
+ it "can run migrations that updates functions" do
41
+ connection.create_function(:test)
42
+
43
+ sql_definition = <<-EOS
44
+ CREATE OR REPLACE FUNCTION test()
45
+ RETURNS text AS $$
46
+ BEGIN
47
+ RETURN 'testest';
48
+ END;
49
+ $$ LANGUAGE plpgsql;
50
+ EOS
51
+ with_function_definition(
52
+ name: :test,
53
+ version: 2,
54
+ sql_definition: sql_definition,
55
+ ) do
56
+ migration = Class.new(migration_class) do
57
+ def change
58
+ update_function :test, version: 2, revert_to_version: 1
59
+ end
60
+ end
61
+
62
+ expect { run_migration(migration, :change) }.not_to raise_error
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,75 @@
1
+ require "spec_helper"
2
+
3
+ describe "Reverting migrations", :db do
4
+ around do |example|
5
+ sql_definition = <<-EOS
6
+ CREATE OR REPLACE FUNCTION test()
7
+ RETURNS text AS $$
8
+ BEGIN
9
+ RETURN 'test';
10
+ END;
11
+ $$ LANGUAGE plpgsql;
12
+ EOS
13
+ with_function_definition(name: :test, sql_definition: sql_definition) do
14
+ example.run
15
+ end
16
+ end
17
+
18
+ it "can run reversible migrations for creating functions" do
19
+ migration = Class.new(migration_class) do
20
+ def change
21
+ create_function :test
22
+ end
23
+ end
24
+
25
+ expect { run_migration(migration, [:up, :down]) }.not_to raise_error
26
+ end
27
+
28
+ it "can run reversible migrations for dropping functions" do
29
+ connection.create_function(:test)
30
+
31
+ good_migration = Class.new(migration_class) do
32
+ def change
33
+ drop_function :test, revert_to_version: 1
34
+ end
35
+ end
36
+ bad_migration = Class.new(migration_class) do
37
+ def change
38
+ drop_function :test
39
+ end
40
+ end
41
+
42
+ expect { run_migration(good_migration, [:up, :down]) }.not_to raise_error
43
+ expect { run_migration(bad_migration, [:up, :down]) }.
44
+ to raise_error(
45
+ ActiveRecord::IrreversibleMigration,
46
+ /`create_function` is reversible only if given a `revert_to_version`/,
47
+ )
48
+ end
49
+
50
+ it "can run reversible migrations for updating functions" do
51
+ connection.create_function(:test)
52
+
53
+ sql_definition = <<-EOS
54
+ CREATE OR REPLACE FUNCTION test()
55
+ RETURNS text AS $$
56
+ BEGIN
57
+ RETURN 'bar';
58
+ END;
59
+ $$ LANGUAGE plpgsql;
60
+ EOS
61
+ with_function_definition(
62
+ name: :test,
63
+ version: 2,
64
+ sql_definition: sql_definition,
65
+ ) do
66
+ migration = Class.new(migration_class) do
67
+ def change
68
+ update_function :test, version: 2, revert_to_version: 1
69
+ end
70
+ end
71
+
72
+ expect { run_migration(migration, [:up, :down]) }.not_to raise_error
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,56 @@
1
+ require "spec_helper"
2
+
3
+ describe "Trigger migrations", :db do
4
+ around do |example|
5
+ connection.execute <<-EOS
6
+ CREATE TABLE users (
7
+ id int PRIMARY KEY,
8
+ name varchar(256),
9
+ upper_name varchar(256)
10
+ );
11
+ EOS
12
+ Fx.database.create_function <<-EOS
13
+ CREATE OR REPLACE FUNCTION uppercase_users_name()
14
+ RETURNS trigger AS $$
15
+ BEGIN
16
+ NEW.upper_name = UPPER(NEW.name);
17
+ RETURN NEW;
18
+ END;
19
+ $$ LANGUAGE plpgsql;
20
+ EOS
21
+ sql_definition = <<-EOS
22
+ CREATE TRIGGER uppercase_users_name
23
+ BEFORE INSERT ON users
24
+ FOR EACH ROW
25
+ EXECUTE PROCEDURE uppercase_users_name();
26
+ EOS
27
+ with_trigger_definition(
28
+ name: :uppercase_users_name,
29
+ sql_definition: sql_definition,
30
+ ) do
31
+ example.run
32
+ end
33
+ end
34
+
35
+ it "can run migrations that create triggers" do
36
+ migration = Class.new(migration_class) do
37
+ def up
38
+ create_trigger :uppercase_users_name
39
+ end
40
+ end
41
+
42
+ expect { run_migration(migration, :up) }.not_to raise_error
43
+ end
44
+
45
+ it "can run migrations that drop triggers" do
46
+ connection.create_trigger(:uppercase_users_name)
47
+
48
+ migration = Class.new(migration_class) do
49
+ def up
50
+ drop_trigger :uppercase_users_name, on: :users
51
+ end
52
+ end
53
+
54
+ expect { run_migration(migration, :up) }.not_to raise_error
55
+ end
56
+ end
@@ -0,0 +1,95 @@
1
+ require "spec_helper"
2
+
3
+ describe "Reverting migrations", :db do
4
+ around do |example|
5
+ connection.execute <<-EOS
6
+ CREATE TABLE users (
7
+ id int PRIMARY KEY,
8
+ name varchar(256),
9
+ upper_name varchar(256)
10
+ );
11
+ EOS
12
+ Fx.database.create_function <<-EOS
13
+ CREATE OR REPLACE FUNCTION uppercase_users_name()
14
+ RETURNS trigger AS $$
15
+ BEGIN
16
+ NEW.upper_name = UPPER(NEW.name);
17
+ RETURN NEW;
18
+ END;
19
+ $$ LANGUAGE plpgsql;
20
+ EOS
21
+ sql_definition = <<-EOS
22
+ CREATE TRIGGER uppercase_users_name
23
+ BEFORE INSERT ON users
24
+ FOR EACH ROW
25
+ EXECUTE PROCEDURE uppercase_users_name();
26
+ EOS
27
+ with_trigger_definition(
28
+ name: :uppercase_users_name,
29
+ sql_definition: sql_definition,
30
+ ) do
31
+ example.run
32
+ end
33
+ end
34
+
35
+ it "can run reversible migrations for creating triggers" do
36
+ migration = Class.new(migration_class) do
37
+ def change
38
+ create_trigger :uppercase_users_name, on: :users
39
+ end
40
+ end
41
+
42
+ expect { run_migration(migration, [:up, :down]) }.not_to raise_error
43
+ end
44
+
45
+ it "can run reversible migrations for dropping triggers" do
46
+ connection.create_trigger(:uppercase_users_name, on: :users)
47
+
48
+ good_migration = Class.new(migration_class) do
49
+ def change
50
+ drop_trigger :uppercase_users_name, on: :users, revert_to_version: 1
51
+ end
52
+ end
53
+ bad_migration = Class.new(migration_class) do
54
+ def change
55
+ drop_trigger :uppercase_users_name, on: :users
56
+ end
57
+ end
58
+
59
+ expect { run_migration(good_migration, [:up, :down]) }.not_to raise_error
60
+ expect { run_migration(bad_migration, [:up, :down]) }.
61
+ to raise_error(
62
+ ActiveRecord::IrreversibleMigration,
63
+ /`create_trigger` is reversible only if given a `revert_to_version`/,
64
+ )
65
+ end
66
+
67
+ it "can run reversible migrations for updating triggers" do
68
+ connection.create_trigger(:uppercase_users_name)
69
+
70
+ sql_definition = <<-EOS
71
+ CREATE TRIGGER uppercase_users_name
72
+ BEFORE UPDATE ON users
73
+ FOR EACH ROW
74
+ EXECUTE PROCEDURE uppercase_users_name();
75
+ EOS
76
+ with_trigger_definition(
77
+ name: :uppercase_users_name,
78
+ sql_definition: sql_definition,
79
+ version: 2,
80
+ ) do
81
+ migration = Class.new(migration_class) do
82
+ def change
83
+ update_trigger(
84
+ :uppercase_users_name,
85
+ on: :users,
86
+ version: 2,
87
+ revert_to_version: 1,
88
+ )
89
+ end
90
+ end
91
+
92
+ expect { run_migration(migration, [:up, :down]) }.not_to raise_error
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,37 @@
1
+ require "spec_helper"
2
+
3
+ module Fx
4
+ module Adapters
5
+ describe Postgres::Functions, :db do
6
+ describe ".all" do
7
+ it "returns `Function` objects" do
8
+ connection = ActiveRecord::Base.connection
9
+ connection.execute <<-EOS.strip_heredoc
10
+ CREATE OR REPLACE FUNCTION test()
11
+ RETURNS text AS $$
12
+ BEGIN
13
+ RETURN 'test';
14
+ END;
15
+ $$ LANGUAGE plpgsql;
16
+ EOS
17
+
18
+ functions = Postgres::Functions.new(connection).all
19
+
20
+ first = functions.first
21
+ expect(functions.size).to eq 1
22
+ expect(first.name).to eq "test"
23
+ expect(first.definition).to eq <<-EOS.strip_heredoc
24
+ CREATE OR REPLACE FUNCTION public.test()
25
+ RETURNS text
26
+ LANGUAGE plpgsql
27
+ AS $function$
28
+ BEGIN
29
+ RETURN 'test';
30
+ END;
31
+ $function$
32
+ EOS
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,45 @@
1
+ require "spec_helper"
2
+
3
+ module Fx
4
+ module Adapters
5
+ describe Postgres::Triggers, :db do
6
+ describe ".all" do
7
+ it "returns `Trigger` objects" do
8
+ connection = ActiveRecord::Base.connection
9
+ connection.execute <<-EOS.strip_heredoc
10
+ CREATE TABLE users (
11
+ id int PRIMARY KEY,
12
+ name varchar(256),
13
+ upper_name varchar(256)
14
+ );
15
+ EOS
16
+ connection.execute <<-EOS.strip_heredoc
17
+ CREATE OR REPLACE FUNCTION uppercase_users_name()
18
+ RETURNS trigger AS $$
19
+ BEGIN
20
+ NEW.upper_name = UPPER(NEW.name);
21
+ RETURN NEW;
22
+ END;
23
+ $$ LANGUAGE plpgsql;
24
+ EOS
25
+ connection.execute <<-EOS.strip_heredoc
26
+ CREATE TRIGGER uppercase_users_name
27
+ BEFORE INSERT ON users
28
+ FOR EACH ROW
29
+ EXECUTE PROCEDURE uppercase_users_name();
30
+ EOS
31
+
32
+ triggers = Postgres::Triggers.new(connection).all
33
+
34
+ first = triggers.first
35
+ expect(triggers.size).to eq 1
36
+ expect(first.name).to eq "uppercase_users_name"
37
+ expect(first.definition).to include("BEFORE INSERT")
38
+ expect(first.definition).to match(/ON [public\.users|users]/)
39
+ expect(first.definition).to include("FOR EACH ROW")
40
+ expect(first.definition).to include("EXECUTE PROCEDURE uppercase_users_name()")
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,146 @@
1
+ require "spec_helper"
2
+
3
+ module Fx::Adapters
4
+ describe Postgres, :db do
5
+ describe "#create_function" do
6
+ it "successfully creates a function" do
7
+ adapter = Postgres.new
8
+ adapter.create_function(
9
+ <<-EOS
10
+ CREATE OR REPLACE FUNCTION test()
11
+ RETURNS text AS $$
12
+ BEGIN
13
+ RETURN 'test';
14
+ END;
15
+ $$ LANGUAGE plpgsql;
16
+ EOS
17
+ )
18
+
19
+ expect(adapter.functions.map(&:name)).to include("test")
20
+ end
21
+ end
22
+
23
+ describe "#create_trigger" do
24
+ it "successfully creates a trigger" do
25
+ connection.execute <<-EOS
26
+ CREATE TABLE users (
27
+ id int PRIMARY KEY,
28
+ name varchar(256),
29
+ upper_name varchar(256)
30
+ );
31
+ EOS
32
+ adapter = Postgres.new
33
+ adapter.create_function <<-EOS
34
+ CREATE OR REPLACE FUNCTION uppercase_users_name()
35
+ RETURNS trigger AS $$
36
+ BEGIN
37
+ NEW.upper_name = UPPER(NEW.name);
38
+ RETURN NEW;
39
+ END;
40
+ $$ LANGUAGE plpgsql;
41
+ EOS
42
+ adapter.create_trigger(
43
+ <<-EOS
44
+ CREATE TRIGGER uppercase_users_name
45
+ BEFORE INSERT ON users
46
+ FOR EACH ROW
47
+ EXECUTE PROCEDURE uppercase_users_name();
48
+ EOS
49
+ )
50
+
51
+ expect(adapter.triggers.map(&:name)).to include("uppercase_users_name")
52
+ end
53
+ end
54
+
55
+ describe "#drop_function" do
56
+ context "when the function has arguments" do
57
+ it "successfully drops a function with the entire function signature" do
58
+ adapter = Postgres.new
59
+ adapter.create_function(
60
+ <<-EOS
61
+ CREATE FUNCTION adder(x int, y int)
62
+ RETURNS int AS $$
63
+ BEGIN
64
+ RETURN $1 + $2;
65
+ END;
66
+ $$ LANGUAGE plpgsql;
67
+ EOS
68
+ )
69
+
70
+ adapter.drop_function(:adder)
71
+
72
+ expect(adapter.functions.map(&:name)).not_to include("adder")
73
+ end
74
+ end
75
+
76
+ context "when the function does not have arguments" do
77
+ it "successfully drops a function" do
78
+ adapter = Postgres.new
79
+ adapter.create_function(
80
+ <<-EOS
81
+ CREATE OR REPLACE FUNCTION test()
82
+ RETURNS text AS $$
83
+ BEGIN
84
+ RETURN 'test';
85
+ END;
86
+ $$ LANGUAGE plpgsql;
87
+ EOS
88
+ )
89
+
90
+ adapter.drop_function(:test)
91
+
92
+ expect(adapter.functions.map(&:name)).not_to include("test")
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "#functions" do
98
+ it "finds functions and builds Fx::Function objects" do
99
+ adapter = Postgres.new
100
+ adapter.create_function(
101
+ <<-EOS
102
+ CREATE OR REPLACE FUNCTION test()
103
+ RETURNS text AS $$
104
+ BEGIN
105
+ RETURN 'test';
106
+ END;
107
+ $$ LANGUAGE plpgsql;
108
+ EOS
109
+ )
110
+
111
+ expect(adapter.functions.map(&:name)).to eq ["test"]
112
+ end
113
+ end
114
+
115
+ describe "#triggers" do
116
+ it "finds triggers and builds Fx::Trigger objects" do
117
+ connection.execute <<-EOS
118
+ CREATE TABLE users (
119
+ id int PRIMARY KEY,
120
+ name varchar(256),
121
+ upper_name varchar(256)
122
+ );
123
+ EOS
124
+ adapter = Postgres.new
125
+ adapter.create_function <<-EOS
126
+ CREATE OR REPLACE FUNCTION uppercase_users_name()
127
+ RETURNS trigger AS $$
128
+ BEGIN
129
+ NEW.upper_name = UPPER(NEW.name);
130
+ RETURN NEW;
131
+ END;
132
+ $$ LANGUAGE plpgsql;
133
+ EOS
134
+ sql_definition = <<-EOS
135
+ CREATE TRIGGER uppercase_users_name
136
+ BEFORE INSERT ON users
137
+ FOR EACH ROW
138
+ EXECUTE PROCEDURE uppercase_users_name()
139
+ EOS
140
+ adapter.create_trigger(sql_definition)
141
+
142
+ expect(adapter.triggers.map(&:name)).to eq ["uppercase_users_name"]
143
+ end
144
+ end
145
+ end
146
+ end