fx 0.1.0 → 0.11.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.
- checksums.yaml +5 -5
- data/.github/scripts/check-eol +95 -0
- data/.github/workflows/ci.yml +61 -0
- data/.github/workflows/eol-check.yml +30 -0
- data/.rspec +1 -1
- data/.standard.yml +3 -0
- data/CHANGELOG.md +186 -0
- data/CONTRIBUTING.md +13 -4
- data/Gemfile +21 -2
- data/LICENSE +18 -0
- data/README.md +99 -14
- data/Rakefile +11 -1
- data/bin/rake +2 -3
- data/bin/rspec +13 -3
- data/bin/setup +1 -4
- data/bin/standardrb +27 -0
- data/bin/yard +13 -3
- data/fx.gemspec +20 -27
- data/lib/fx/adapters/postgres/connection.rb +6 -0
- data/lib/fx/adapters/postgres/functions.rb +16 -28
- data/lib/fx/adapters/postgres/query_executor.rb +34 -0
- data/lib/fx/adapters/postgres/triggers.rb +14 -28
- data/lib/fx/adapters/postgres.rb +30 -17
- data/lib/fx/command_recorder.rb +104 -13
- data/lib/fx/configuration.rb +10 -25
- data/lib/fx/definition.rb +32 -10
- data/lib/fx/function.rb +23 -9
- data/lib/fx/railtie.rb +15 -0
- data/lib/fx/schema_dumper.rb +33 -10
- data/lib/fx/statements.rb +213 -11
- data/lib/fx/trigger.rb +5 -3
- data/lib/fx/version.rb +1 -1
- data/lib/fx.rb +40 -0
- data/lib/generators/fx/function/USAGE +2 -0
- data/lib/generators/fx/function/function_generator.rb +54 -39
- data/lib/generators/fx/function/templates/db/migrate/create_function.erb +1 -1
- data/lib/generators/fx/function/templates/db/migrate/update_function.erb +1 -1
- data/lib/generators/fx/migration_helper.rb +45 -0
- data/lib/generators/fx/name_helper.rb +33 -0
- data/lib/generators/fx/trigger/USAGE +2 -0
- data/lib/generators/fx/trigger/templates/db/migrate/create_trigger.erb +1 -1
- data/lib/generators/fx/trigger/templates/db/migrate/update_trigger.erb +1 -1
- data/lib/generators/fx/trigger/trigger_generator.rb +46 -51
- data/lib/generators/fx/version_helper.rb +55 -0
- data/spec/acceptance/user_manages_functions_spec.rb +26 -6
- data/spec/acceptance/user_manages_triggers_spec.rb +11 -11
- data/spec/acceptance_helper.rb +17 -11
- data/spec/dummy/Rakefile +8 -1
- data/spec/dummy/bin/bundle +2 -2
- data/spec/dummy/bin/rails +3 -3
- data/spec/dummy/bin/rake +2 -2
- data/spec/dummy/config/application.rb +2 -0
- data/spec/dummy/config/database.yml +2 -0
- data/spec/dummy/config.ru +1 -1
- data/spec/features/functions/migrations_spec.rb +9 -9
- data/spec/features/functions/revert_spec.rb +13 -13
- data/spec/features/triggers/migrations_spec.rb +11 -11
- data/spec/features/triggers/revert_spec.rb +21 -21
- data/spec/fx/adapters/postgres/functions_spec.rb +40 -0
- data/spec/fx/adapters/postgres/query_executor_spec.rb +75 -0
- data/spec/fx/adapters/postgres/triggers_spec.rb +48 -0
- data/spec/fx/adapters/postgres_spec.rb +115 -111
- data/spec/fx/command_recorder_spec.rb +39 -53
- data/spec/fx/configuration_spec.rb +20 -9
- data/spec/fx/definition_spec.rb +53 -38
- data/spec/fx/function_spec.rb +143 -0
- data/spec/fx/schema_dumper_spec.rb +241 -0
- data/spec/fx/statements_spec.rb +219 -0
- data/spec/fx/trigger_spec.rb +52 -0
- data/spec/fx_spec.rb +28 -0
- data/spec/generators/fx/function/function_generator_spec.rb +22 -10
- data/spec/generators/fx/migration_helper_spec.rb +108 -0
- data/spec/generators/fx/name_helper_spec.rb +114 -0
- data/spec/generators/fx/trigger/trigger_generator_spec.rb +55 -20
- data/spec/generators/fx/version_helper_spec.rb +157 -0
- data/spec/spec_helper.rb +16 -4
- data/spec/support/database_reset.rb +24 -0
- data/spec/support/definition_helpers.rb +5 -9
- data/spec/support/generator_setup.rb +46 -5
- data/spec/support/migration_helpers.rb +9 -1
- data/spec/support/warning_helper.rb +5 -0
- metadata +43 -215
- data/.ruby-version +0 -1
- data/.travis.yml +0 -27
- data/Appraisals +0 -21
- data/bin/appraisal +0 -17
- data/gemfiles/rails40.gemfile +0 -8
- data/gemfiles/rails40.gemfile.lock +0 -111
- data/gemfiles/rails41.gemfile +0 -8
- data/gemfiles/rails41.gemfile.lock +0 -113
- data/gemfiles/rails42.gemfile +0 -8
- data/gemfiles/rails42.gemfile.lock +0 -130
- data/gemfiles/rails50.gemfile +0 -8
- data/gemfiles/rails50.gemfile.lock +0 -126
- data/lib/fx/command_recorder/arguments.rb +0 -43
- data/lib/fx/command_recorder/function.rb +0 -30
- data/lib/fx/command_recorder/trigger.rb +0 -30
- data/lib/fx/schema_dumper/function.rb +0 -29
- data/lib/fx/schema_dumper/trigger.rb +0 -29
- data/lib/fx/statements/function.rb +0 -105
- data/lib/fx/statements/trigger.rb +0 -133
- data/spec/fx/command_recorder/arguments_spec.rb +0 -41
- data/spec/fx/schema_dumper/function_spec.rb +0 -22
- data/spec/fx/schema_dumper/trigger_spec.rb +0 -40
- data/spec/fx/statements/function_spec.rb +0 -103
- data/spec/fx/statements/trigger_spec.rb +0 -132
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class <%= migration_class_name %> < ActiveRecord::Migration
|
|
1
|
+
class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
|
2
2
|
def change
|
|
3
3
|
update_trigger <%= formatted_name %>, on: <%= formatted_table_name %>, version: <%= version %>, revert_to_version: <%= previous_version %>
|
|
4
4
|
end
|
|
@@ -1,36 +1,43 @@
|
|
|
1
1
|
require "rails/generators"
|
|
2
2
|
require "rails/generators/active_record"
|
|
3
|
+
require "generators/fx/version_helper"
|
|
4
|
+
require "generators/fx/migration_helper"
|
|
5
|
+
require "generators/fx/name_helper"
|
|
3
6
|
|
|
4
7
|
module Fx
|
|
5
8
|
module Generators
|
|
6
9
|
# @api private
|
|
7
10
|
class TriggerGenerator < Rails::Generators::NamedBase
|
|
8
11
|
include Rails::Generators::Migration
|
|
12
|
+
|
|
9
13
|
source_root File.expand_path("../templates", __FILE__)
|
|
10
14
|
argument :table_name, type: :hash, required: true
|
|
11
15
|
|
|
16
|
+
DEFINITION_PATH = %w[db triggers].freeze
|
|
17
|
+
|
|
18
|
+
class_option :migration, type: :boolean
|
|
19
|
+
|
|
12
20
|
def create_triggers_directory
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
return if trigger_definition_path.exist?
|
|
22
|
+
|
|
23
|
+
empty_directory(trigger_definition_path)
|
|
16
24
|
end
|
|
17
25
|
|
|
18
26
|
def create_trigger_definition
|
|
19
|
-
create_file
|
|
27
|
+
create_file(definition.path)
|
|
20
28
|
end
|
|
21
29
|
|
|
22
30
|
def create_migration_file
|
|
23
|
-
if
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
end
|
|
31
|
+
return if migration_helper.skip_creation?
|
|
32
|
+
|
|
33
|
+
template_info = migration_helper.migration_template_info(
|
|
34
|
+
object_type: :trigger,
|
|
35
|
+
file_name: file_name,
|
|
36
|
+
updating_existing: version_helper.updating_existing?,
|
|
37
|
+
version: version_helper.current_version
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
migration_template(template_info[:template], template_info[:filename])
|
|
34
41
|
end
|
|
35
42
|
|
|
36
43
|
def self.next_migration_number(dir)
|
|
@@ -39,69 +46,57 @@ module Fx
|
|
|
39
46
|
|
|
40
47
|
no_tasks do
|
|
41
48
|
def previous_version
|
|
42
|
-
|
|
43
|
-
map { |name| version_regex.match(name).try(:[], "version").to_i }.
|
|
44
|
-
max
|
|
49
|
+
version_helper.previous_version
|
|
45
50
|
end
|
|
46
51
|
|
|
47
52
|
def version
|
|
48
|
-
|
|
53
|
+
version_helper.current_version
|
|
49
54
|
end
|
|
50
55
|
|
|
51
56
|
def migration_class_name
|
|
52
|
-
if
|
|
53
|
-
|
|
57
|
+
if version_helper.updating_existing?
|
|
58
|
+
migration_helper.update_migration_class_name(
|
|
59
|
+
object_type: :trigger,
|
|
60
|
+
class_name: class_name,
|
|
61
|
+
version: version
|
|
62
|
+
)
|
|
54
63
|
else
|
|
55
64
|
super
|
|
56
65
|
end
|
|
57
66
|
end
|
|
58
67
|
|
|
59
68
|
def formatted_name
|
|
60
|
-
|
|
61
|
-
"\"#{singular_name}\""
|
|
62
|
-
else
|
|
63
|
-
":#{singular_name}"
|
|
64
|
-
end
|
|
69
|
+
Fx::Generators::NameHelper.format_for_migration(singular_name)
|
|
65
70
|
end
|
|
66
71
|
|
|
67
72
|
def formatted_table_name
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if name.nil?
|
|
71
|
-
raise(
|
|
72
|
-
ArgumentError,
|
|
73
|
-
"Either `table_name:NAME` or `on:NAME` must be specified",
|
|
74
|
-
)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
if name.include?(".")
|
|
78
|
-
"\"#{name}\""
|
|
79
|
-
else
|
|
80
|
-
":#{name}"
|
|
81
|
-
end
|
|
73
|
+
Fx::Generators::NameHelper.format_table_name_from_hash(table_name)
|
|
82
74
|
end
|
|
83
75
|
end
|
|
84
76
|
|
|
85
77
|
private
|
|
86
78
|
|
|
87
|
-
def
|
|
88
|
-
|
|
79
|
+
def trigger_definition_path
|
|
80
|
+
@_trigger_definition_path ||= Rails.root.join(*DEFINITION_PATH)
|
|
89
81
|
end
|
|
90
82
|
|
|
91
|
-
def
|
|
92
|
-
|
|
83
|
+
def version_helper
|
|
84
|
+
@_version_helper ||= Fx::Generators::VersionHelper.new(
|
|
85
|
+
file_name: file_name,
|
|
86
|
+
definition_path: trigger_definition_path
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def migration_helper
|
|
91
|
+
@_migration_helper ||= Fx::Generators::MigrationHelper.new(options)
|
|
93
92
|
end
|
|
94
93
|
|
|
95
94
|
def definition
|
|
96
|
-
|
|
97
|
-
name: file_name,
|
|
98
|
-
version: version,
|
|
99
|
-
type: "trigger",
|
|
100
|
-
)
|
|
95
|
+
version_helper.definition_for_version(version: version, type: :trigger)
|
|
101
96
|
end
|
|
102
97
|
|
|
103
|
-
def
|
|
104
|
-
|
|
98
|
+
def updating_existing_trigger?
|
|
99
|
+
version_helper.updating_existing?
|
|
105
100
|
end
|
|
106
101
|
end
|
|
107
102
|
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Fx
|
|
2
|
+
module Generators
|
|
3
|
+
# @api private
|
|
4
|
+
class VersionHelper
|
|
5
|
+
def initialize(file_name:, definition_path:)
|
|
6
|
+
@file_name = file_name
|
|
7
|
+
@definition_path = definition_path
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def previous_version
|
|
11
|
+
@previous_version ||= existing_versions.max || 0
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def current_version
|
|
15
|
+
previous_version.next
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def updating_existing?
|
|
19
|
+
previous_version > 0
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def creating_new?
|
|
23
|
+
previous_version == 0
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def definition_for_version(version:, type:)
|
|
27
|
+
case type
|
|
28
|
+
when :function
|
|
29
|
+
Fx::Definition.function(name: file_name, version: version)
|
|
30
|
+
when :trigger
|
|
31
|
+
Fx::Definition.trigger(name: file_name, version: version)
|
|
32
|
+
else
|
|
33
|
+
raise(
|
|
34
|
+
ArgumentError,
|
|
35
|
+
"Unknown type: #{type}. Must be :function or :trigger"
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
VERSION_PATTERN = /v(\d+)/
|
|
43
|
+
private_constant :VERSION_PATTERN
|
|
44
|
+
|
|
45
|
+
attr_reader :file_name, :definition_path
|
|
46
|
+
|
|
47
|
+
def existing_versions
|
|
48
|
+
Dir
|
|
49
|
+
.glob("#{file_name}_v*.sql", base: definition_path)
|
|
50
|
+
.map { |file| file[VERSION_PATTERN, 1].to_i }
|
|
51
|
+
.compact
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
require "acceptance_helper"
|
|
2
2
|
|
|
3
|
-
describe "User manages functions" do
|
|
3
|
+
RSpec.describe "User manages functions" do
|
|
4
4
|
it "handles simple functions" do
|
|
5
5
|
successfully "rails generate fx:function test"
|
|
6
|
-
write_function_definition "test_v01", <<~
|
|
6
|
+
write_function_definition "test_v01", <<~SQL
|
|
7
7
|
CREATE OR REPLACE FUNCTION test()
|
|
8
8
|
RETURNS text AS $$
|
|
9
9
|
BEGIN
|
|
10
10
|
RETURN 'test';
|
|
11
11
|
END;
|
|
12
12
|
$$ LANGUAGE plpgsql;
|
|
13
|
-
|
|
13
|
+
SQL
|
|
14
14
|
successfully "rake db:migrate"
|
|
15
15
|
|
|
16
16
|
result = execute("SELECT * FROM test() AS result")
|
|
@@ -19,19 +19,39 @@ describe "User manages functions" do
|
|
|
19
19
|
successfully "rails generate fx:function test"
|
|
20
20
|
verify_identical_definitions(
|
|
21
21
|
"db/functions/test_v01.sql",
|
|
22
|
-
"db/functions/test_v02.sql"
|
|
22
|
+
"db/functions/test_v02.sql"
|
|
23
23
|
)
|
|
24
|
-
write_function_definition "test_v02", <<~
|
|
24
|
+
write_function_definition "test_v02", <<~SQL
|
|
25
25
|
CREATE OR REPLACE FUNCTION test()
|
|
26
26
|
RETURNS text AS $$
|
|
27
27
|
BEGIN
|
|
28
28
|
RETURN 'testest';
|
|
29
29
|
END;
|
|
30
30
|
$$ LANGUAGE plpgsql;
|
|
31
|
-
|
|
31
|
+
SQL
|
|
32
32
|
successfully "rake db:migrate"
|
|
33
33
|
|
|
34
34
|
result = execute("SELECT * FROM test() AS result")
|
|
35
35
|
expect(result).to eq("result" => "testest")
|
|
36
36
|
end
|
|
37
|
+
|
|
38
|
+
it "handles functions with arguments" do
|
|
39
|
+
successfully "rails generate fx:function adder"
|
|
40
|
+
write_function_definition "adder_v01", <<~SQL
|
|
41
|
+
CREATE FUNCTION adder(x int, y int)
|
|
42
|
+
RETURNS int AS $$
|
|
43
|
+
BEGIN
|
|
44
|
+
RETURN $1 + $2;
|
|
45
|
+
END;
|
|
46
|
+
$$ LANGUAGE plpgsql;
|
|
47
|
+
SQL
|
|
48
|
+
successfully "rake db:migrate"
|
|
49
|
+
|
|
50
|
+
result = execute("SELECT * FROM adder(1, 2) AS result")
|
|
51
|
+
result["result"] = result["result"].to_i
|
|
52
|
+
expect(result).to eq("result" => 3)
|
|
53
|
+
|
|
54
|
+
successfully "rails destroy fx:function adder"
|
|
55
|
+
successfully "rake db:migrate"
|
|
56
|
+
end
|
|
37
57
|
end
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
require "acceptance_helper"
|
|
2
2
|
|
|
3
|
-
describe "User manages triggers" do
|
|
3
|
+
RSpec.describe "User manages triggers" do
|
|
4
4
|
it "handles simple triggers" do
|
|
5
5
|
successfully "rails generate model user name:string upper_name:string"
|
|
6
6
|
successfully "rails generate fx:function uppercase_users_name"
|
|
7
|
-
write_function_definition "uppercase_users_name_v01", <<~
|
|
7
|
+
write_function_definition "uppercase_users_name_v01", <<~SQL
|
|
8
8
|
CREATE OR REPLACE FUNCTION uppercase_users_name()
|
|
9
9
|
RETURNS trigger AS $$
|
|
10
10
|
BEGIN
|
|
@@ -12,14 +12,14 @@ describe "User manages triggers" do
|
|
|
12
12
|
RETURN NEW;
|
|
13
13
|
END;
|
|
14
14
|
$$ LANGUAGE plpgsql;
|
|
15
|
-
|
|
15
|
+
SQL
|
|
16
16
|
successfully "rails generate fx:trigger uppercase_users_name table_name:users"
|
|
17
|
-
write_trigger_definition "uppercase_users_name_v01", <<~
|
|
17
|
+
write_trigger_definition "uppercase_users_name_v01", <<~SQL
|
|
18
18
|
CREATE TRIGGER uppercase_users_name
|
|
19
19
|
BEFORE INSERT ON users
|
|
20
20
|
FOR EACH ROW
|
|
21
|
-
EXECUTE
|
|
22
|
-
|
|
21
|
+
EXECUTE FUNCTION uppercase_users_name();
|
|
22
|
+
SQL
|
|
23
23
|
successfully "rake db:migrate"
|
|
24
24
|
|
|
25
25
|
execute <<~SQL
|
|
@@ -32,18 +32,18 @@ describe "User manages triggers" do
|
|
|
32
32
|
expect(result).to eq("upper_name" => "BOB")
|
|
33
33
|
|
|
34
34
|
successfully "rails generate fx:trigger uppercase_users_name table_name:users"
|
|
35
|
-
write_trigger_definition "uppercase_users_name_v02", <<~
|
|
35
|
+
write_trigger_definition "uppercase_users_name_v02", <<~SQL
|
|
36
36
|
CREATE TRIGGER uppercase_users_name
|
|
37
37
|
BEFORE UPDATE ON users
|
|
38
38
|
FOR EACH ROW
|
|
39
|
-
EXECUTE
|
|
40
|
-
|
|
39
|
+
EXECUTE FUNCTION uppercase_users_name();
|
|
40
|
+
SQL
|
|
41
41
|
successfully "rake db:migrate"
|
|
42
|
-
execute <<~
|
|
42
|
+
execute <<~SQL
|
|
43
43
|
UPDATE users
|
|
44
44
|
SET name = 'Alice'
|
|
45
45
|
WHERE id = 1;
|
|
46
|
-
|
|
46
|
+
SQL
|
|
47
47
|
|
|
48
48
|
result = execute("SELECT upper_name FROM users WHERE name = 'Alice';")
|
|
49
49
|
expect(result).to eq("upper_name" => "ALICE")
|
data/spec/acceptance_helper.rb
CHANGED
|
@@ -5,29 +5,35 @@ ENV["RAILS_ENV"] = "test"
|
|
|
5
5
|
RSpec.configure do |config|
|
|
6
6
|
config.around(:each) do |example|
|
|
7
7
|
Dir.chdir("spec/dummy") do
|
|
8
|
+
DatabaseReset.call
|
|
9
|
+
|
|
8
10
|
example.run
|
|
11
|
+
|
|
12
|
+
DatabaseReset.call
|
|
9
13
|
end
|
|
10
14
|
end
|
|
11
15
|
|
|
12
16
|
config.before(:suite) do
|
|
13
17
|
Dir.chdir("spec/dummy") do
|
|
14
|
-
system
|
|
15
|
-
git init 1>/dev/null
|
|
16
|
-
git
|
|
17
|
-
git
|
|
18
|
-
|
|
18
|
+
system [
|
|
19
|
+
"git init -b master 1>/dev/null",
|
|
20
|
+
"git config user.email 'fx@example.com'",
|
|
21
|
+
"git config user.name 'Fx'",
|
|
22
|
+
"git add -A",
|
|
23
|
+
"git commit --no-gpg-sign --message 'initial' 1>/dev/null"
|
|
24
|
+
].join(" && ")
|
|
19
25
|
end
|
|
20
26
|
end
|
|
21
27
|
|
|
22
28
|
config.after(:suite) do
|
|
23
29
|
Dir.chdir("spec/dummy") do
|
|
24
30
|
ActiveRecord::Base.connection.disconnect!
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
git add -A
|
|
28
|
-
git reset --hard HEAD 1>/dev/null
|
|
29
|
-
rm -rf .git/ 1>/dev/null
|
|
30
|
-
|
|
31
|
+
DatabaseReset.call
|
|
32
|
+
system [
|
|
33
|
+
"git add -A",
|
|
34
|
+
"git reset --hard HEAD 1>/dev/null",
|
|
35
|
+
"rm -rf .git/ 1>/dev/null"
|
|
36
|
+
].join(" && ")
|
|
31
37
|
end
|
|
32
38
|
end
|
|
33
39
|
|
data/spec/dummy/Rakefile
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
|
2
2
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
|
3
3
|
|
|
4
|
-
require File.expand_path(
|
|
4
|
+
require File.expand_path("../config/application", __FILE__)
|
|
5
5
|
|
|
6
6
|
Rails.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
|
data/spec/dummy/bin/bundle
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
ENV[
|
|
3
|
-
load Gem.bin_path(
|
|
2
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
|
|
3
|
+
load Gem.bin_path("bundler", "bundle")
|
data/spec/dummy/bin/rails
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
APP_PATH = File.expand_path(
|
|
3
|
-
require_relative
|
|
4
|
-
require
|
|
2
|
+
APP_PATH = File.expand_path("../../config/application", __FILE__)
|
|
3
|
+
require_relative "../config/boot"
|
|
4
|
+
require "rails/commands"
|
data/spec/dummy/bin/rake
CHANGED
data/spec/dummy/config.ru
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
|
|
3
|
-
describe "Function migrations", :db do
|
|
3
|
+
RSpec.describe "Function migrations", :db do
|
|
4
4
|
around do |example|
|
|
5
|
-
sql_definition = <<~
|
|
5
|
+
sql_definition = <<~SQL
|
|
6
6
|
CREATE OR REPLACE FUNCTION test()
|
|
7
7
|
RETURNS text AS $$
|
|
8
8
|
BEGIN
|
|
9
9
|
RETURN 'test';
|
|
10
10
|
END;
|
|
11
11
|
$$ LANGUAGE plpgsql;
|
|
12
|
-
|
|
12
|
+
SQL
|
|
13
13
|
with_function_definition(name: :test, sql_definition: sql_definition) do
|
|
14
14
|
example.run
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
it "can run migrations that create functions" do
|
|
19
|
-
migration = Class.new(
|
|
19
|
+
migration = Class.new(migration_class) do
|
|
20
20
|
def up
|
|
21
21
|
create_function :test
|
|
22
22
|
end
|
|
@@ -28,7 +28,7 @@ describe "Function migrations", :db do
|
|
|
28
28
|
it "can run migrations that drop functions" do
|
|
29
29
|
connection.create_function(:test)
|
|
30
30
|
|
|
31
|
-
migration = Class.new(
|
|
31
|
+
migration = Class.new(migration_class) do
|
|
32
32
|
def up
|
|
33
33
|
drop_function :test
|
|
34
34
|
end
|
|
@@ -40,20 +40,20 @@ describe "Function migrations", :db do
|
|
|
40
40
|
it "can run migrations that updates functions" do
|
|
41
41
|
connection.create_function(:test)
|
|
42
42
|
|
|
43
|
-
sql_definition = <<~
|
|
43
|
+
sql_definition = <<~SQL
|
|
44
44
|
CREATE OR REPLACE FUNCTION test()
|
|
45
45
|
RETURNS text AS $$
|
|
46
46
|
BEGIN
|
|
47
47
|
RETURN 'testest';
|
|
48
48
|
END;
|
|
49
49
|
$$ LANGUAGE plpgsql;
|
|
50
|
-
|
|
50
|
+
SQL
|
|
51
51
|
with_function_definition(
|
|
52
52
|
name: :test,
|
|
53
53
|
version: 2,
|
|
54
|
-
sql_definition: sql_definition
|
|
54
|
+
sql_definition: sql_definition
|
|
55
55
|
) do
|
|
56
|
-
migration = Class.new(
|
|
56
|
+
migration = Class.new(migration_class) do
|
|
57
57
|
def change
|
|
58
58
|
update_function :test, version: 2, revert_to_version: 1
|
|
59
59
|
end
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
|
|
3
|
-
describe "Reverting migrations", :db do
|
|
3
|
+
RSpec.describe "Reverting migrations", :db do
|
|
4
4
|
around do |example|
|
|
5
|
-
sql_definition = <<~
|
|
5
|
+
sql_definition = <<~SQL
|
|
6
6
|
CREATE OR REPLACE FUNCTION test()
|
|
7
7
|
RETURNS text AS $$
|
|
8
8
|
BEGIN
|
|
9
9
|
RETURN 'test';
|
|
10
10
|
END;
|
|
11
11
|
$$ LANGUAGE plpgsql;
|
|
12
|
-
|
|
12
|
+
SQL
|
|
13
13
|
with_function_definition(name: :test, sql_definition: sql_definition) do
|
|
14
14
|
example.run
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
it "can run reversible migrations for creating functions" do
|
|
19
|
-
migration = Class.new(
|
|
19
|
+
migration = Class.new(migration_class) do
|
|
20
20
|
def change
|
|
21
21
|
create_function :test
|
|
22
22
|
end
|
|
@@ -28,42 +28,42 @@ describe "Reverting migrations", :db do
|
|
|
28
28
|
it "can run reversible migrations for dropping functions" do
|
|
29
29
|
connection.create_function(:test)
|
|
30
30
|
|
|
31
|
-
good_migration = Class.new(
|
|
31
|
+
good_migration = Class.new(migration_class) do
|
|
32
32
|
def change
|
|
33
33
|
drop_function :test, revert_to_version: 1
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
|
-
bad_migration = Class.new(
|
|
36
|
+
bad_migration = Class.new(migration_class) do
|
|
37
37
|
def change
|
|
38
38
|
drop_function :test
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
expect { run_migration(good_migration, [:up, :down]) }.not_to raise_error
|
|
43
|
-
expect { run_migration(bad_migration, [:up, :down]) }
|
|
44
|
-
to raise_error(
|
|
43
|
+
expect { run_migration(bad_migration, [:up, :down]) }
|
|
44
|
+
.to raise_error(
|
|
45
45
|
ActiveRecord::IrreversibleMigration,
|
|
46
|
-
/`create_function` is reversible only if given a `revert_to_version
|
|
46
|
+
/`create_function` is reversible only if given a `revert_to_version`/
|
|
47
47
|
)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
it "can run reversible migrations for updating functions" do
|
|
51
51
|
connection.create_function(:test)
|
|
52
52
|
|
|
53
|
-
sql_definition = <<~
|
|
53
|
+
sql_definition = <<~SQL
|
|
54
54
|
CREATE OR REPLACE FUNCTION test()
|
|
55
55
|
RETURNS text AS $$
|
|
56
56
|
BEGIN
|
|
57
57
|
RETURN 'bar';
|
|
58
58
|
END;
|
|
59
59
|
$$ LANGUAGE plpgsql;
|
|
60
|
-
|
|
60
|
+
SQL
|
|
61
61
|
with_function_definition(
|
|
62
62
|
name: :test,
|
|
63
63
|
version: 2,
|
|
64
|
-
sql_definition: sql_definition
|
|
64
|
+
sql_definition: sql_definition
|
|
65
65
|
) do
|
|
66
|
-
migration = Class.new(
|
|
66
|
+
migration = Class.new(migration_class) do
|
|
67
67
|
def change
|
|
68
68
|
update_function :test, version: 2, revert_to_version: 1
|
|
69
69
|
end
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
|
|
3
|
-
describe "Trigger migrations", :db do
|
|
3
|
+
RSpec.describe "Trigger migrations", :db do
|
|
4
4
|
around do |example|
|
|
5
|
-
connection.execute <<~
|
|
5
|
+
connection.execute <<~SQL
|
|
6
6
|
CREATE TABLE users (
|
|
7
7
|
id int PRIMARY KEY,
|
|
8
8
|
name varchar(256),
|
|
9
9
|
upper_name varchar(256)
|
|
10
10
|
);
|
|
11
|
-
|
|
12
|
-
Fx.database.create_function <<~
|
|
11
|
+
SQL
|
|
12
|
+
Fx.database.create_function <<~SQL
|
|
13
13
|
CREATE OR REPLACE FUNCTION uppercase_users_name()
|
|
14
14
|
RETURNS trigger AS $$
|
|
15
15
|
BEGIN
|
|
@@ -17,23 +17,23 @@ describe "Trigger migrations", :db do
|
|
|
17
17
|
RETURN NEW;
|
|
18
18
|
END;
|
|
19
19
|
$$ LANGUAGE plpgsql;
|
|
20
|
-
|
|
21
|
-
sql_definition = <<~
|
|
20
|
+
SQL
|
|
21
|
+
sql_definition = <<~SQL
|
|
22
22
|
CREATE TRIGGER uppercase_users_name
|
|
23
23
|
BEFORE INSERT ON users
|
|
24
24
|
FOR EACH ROW
|
|
25
|
-
EXECUTE
|
|
26
|
-
|
|
25
|
+
EXECUTE FUNCTION uppercase_users_name();
|
|
26
|
+
SQL
|
|
27
27
|
with_trigger_definition(
|
|
28
28
|
name: :uppercase_users_name,
|
|
29
|
-
sql_definition: sql_definition
|
|
29
|
+
sql_definition: sql_definition
|
|
30
30
|
) do
|
|
31
31
|
example.run
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
it "can run migrations that create triggers" do
|
|
36
|
-
migration = Class.new(
|
|
36
|
+
migration = Class.new(migration_class) do
|
|
37
37
|
def up
|
|
38
38
|
create_trigger :uppercase_users_name
|
|
39
39
|
end
|
|
@@ -45,7 +45,7 @@ describe "Trigger migrations", :db do
|
|
|
45
45
|
it "can run migrations that drop triggers" do
|
|
46
46
|
connection.create_trigger(:uppercase_users_name)
|
|
47
47
|
|
|
48
|
-
migration = Class.new(
|
|
48
|
+
migration = Class.new(migration_class) do
|
|
49
49
|
def up
|
|
50
50
|
drop_trigger :uppercase_users_name, on: :users
|
|
51
51
|
end
|