fx 0.9.0 → 0.10.1
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 +4 -4
- data/.github/workflows/ci.yml +4 -4
- data/CHANGELOG.md +43 -1
- data/Gemfile +5 -2
- data/README.md +16 -0
- data/bin/rake +2 -3
- data/bin/rspec +13 -3
- data/bin/yard +13 -3
- data/fx.gemspec +3 -3
- data/lib/fx/adapters/postgres/connection.rb +12 -4
- data/lib/fx/adapters/postgres/functions.rb +11 -28
- data/lib/fx/adapters/postgres/query_executor.rb +34 -0
- data/lib/fx/adapters/postgres/triggers.rb +14 -29
- data/lib/fx/adapters/postgres.rb +13 -13
- data/lib/fx/command_recorder.rb +5 -3
- data/lib/fx/configuration.rb +2 -2
- data/lib/fx/definition.rb +7 -5
- data/lib/fx/schema_dumper.rb +5 -17
- data/lib/fx/statements.rb +61 -58
- data/lib/fx/version.rb +1 -1
- data/lib/fx.rb +1 -1
- data/lib/generators/fx/function/function_generator.rb +48 -55
- 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/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 +43 -66
- data/lib/generators/fx/version_helper.rb +55 -0
- data/spec/acceptance/user_manages_functions_spec.rb +6 -6
- data/spec/acceptance/user_manages_triggers_spec.rb +10 -10
- data/spec/acceptance_helper.rb +17 -14
- data/spec/dummy/config/application.rb +1 -5
- data/spec/features/functions/migrations_spec.rb +4 -4
- data/spec/features/functions/revert_spec.rb +4 -4
- data/spec/features/triggers/migrations_spec.rb +6 -6
- data/spec/features/triggers/revert_spec.rb +8 -8
- data/spec/fx/adapters/postgres/functions_spec.rb +12 -5
- data/spec/fx/adapters/postgres/query_executor_spec.rb +75 -0
- data/spec/fx/adapters/postgres/triggers_spec.rb +14 -7
- data/spec/fx/adapters/postgres_spec.rb +62 -20
- data/spec/fx/definition_spec.rb +6 -6
- data/spec/fx/schema_dumper_spec.rb +132 -14
- data/spec/fx_spec.rb +1 -1
- data/spec/generators/fx/function/function_generator_spec.rb +10 -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 +42 -19
- data/spec/generators/fx/version_helper_spec.rb +157 -0
- data/spec/spec_helper.rb +11 -4
- data/spec/support/database_reset.rb +24 -0
- data/spec/support/generator_setup.rb +46 -5
- metadata +30 -12
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "generators/fx/name_helper"
|
|
3
|
+
|
|
4
|
+
RSpec.describe Fx::Generators::NameHelper do
|
|
5
|
+
describe ".format_for_migration" do
|
|
6
|
+
it "returns symbol format for simple names" do
|
|
7
|
+
result = described_class.format_for_migration("simple_name")
|
|
8
|
+
|
|
9
|
+
expect(result).to eq(":simple_name")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "returns quoted string format for schema-qualified names" do
|
|
13
|
+
result = described_class.format_for_migration("schema.function_name")
|
|
14
|
+
|
|
15
|
+
expect(result).to eq("\"schema.function_name\"")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "handles names with multiple dots" do
|
|
19
|
+
result = described_class.format_for_migration("db.schema.function")
|
|
20
|
+
|
|
21
|
+
expect(result).to eq("\"db.schema.function\"")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "handles empty names" do
|
|
25
|
+
result = described_class.format_for_migration("")
|
|
26
|
+
|
|
27
|
+
expect(result).to eq(":")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe ".format_table_name_from_hash" do
|
|
32
|
+
it "formats table_name key correctly" do
|
|
33
|
+
table_hash = {"table_name" => "users"}
|
|
34
|
+
|
|
35
|
+
result = described_class.format_table_name_from_hash(table_hash)
|
|
36
|
+
|
|
37
|
+
expect(result).to eq(":users")
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "formats on key correctly" do
|
|
41
|
+
table_hash = {"on" => "posts"}
|
|
42
|
+
|
|
43
|
+
result = described_class.format_table_name_from_hash(table_hash)
|
|
44
|
+
|
|
45
|
+
expect(result).to eq(":posts")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "prefers table_name over on when both are present" do
|
|
49
|
+
table_hash = {"table_name" => "users", "on" => "posts"}
|
|
50
|
+
|
|
51
|
+
result = described_class.format_table_name_from_hash(table_hash)
|
|
52
|
+
|
|
53
|
+
expect(result).to eq(":users")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "handles schema-qualified table names" do
|
|
57
|
+
table_hash = {"table_name" => "public.users"}
|
|
58
|
+
|
|
59
|
+
result = described_class.format_table_name_from_hash(table_hash)
|
|
60
|
+
|
|
61
|
+
expect(result).to eq("\"public.users\"")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "raises error when neither key is present" do
|
|
65
|
+
table_hash = {"something_else" => "value"}
|
|
66
|
+
|
|
67
|
+
expect {
|
|
68
|
+
described_class.format_table_name_from_hash(table_hash)
|
|
69
|
+
}.to raise_error(
|
|
70
|
+
ArgumentError,
|
|
71
|
+
"Either `table_name:NAME` or `on:NAME` must be specified"
|
|
72
|
+
)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "raises error when both keys have nil values" do
|
|
76
|
+
table_hash = {"table_name" => nil, "on" => nil}
|
|
77
|
+
|
|
78
|
+
expect {
|
|
79
|
+
described_class.format_table_name_from_hash(table_hash)
|
|
80
|
+
}.to raise_error(
|
|
81
|
+
ArgumentError,
|
|
82
|
+
"Either `table_name:NAME` or `on:NAME` must be specified"
|
|
83
|
+
)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "uses on key when table_name is nil" do
|
|
87
|
+
table_hash = {"table_name" => nil, "on" => "comments"}
|
|
88
|
+
|
|
89
|
+
result = described_class.format_table_name_from_hash(table_hash)
|
|
90
|
+
|
|
91
|
+
expect(result).to eq(":comments")
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
describe ".validate_and_format" do
|
|
96
|
+
it "formats valid names correctly" do
|
|
97
|
+
result = described_class.validate_and_format("test_function")
|
|
98
|
+
|
|
99
|
+
expect(result).to eq(":test_function")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "formats schema-qualified names correctly" do
|
|
103
|
+
result = described_class.validate_and_format("schema.test")
|
|
104
|
+
|
|
105
|
+
expect(result).to eq("\"schema.test\"")
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "raises error for blank names" do
|
|
109
|
+
expect {
|
|
110
|
+
described_class.validate_and_format("")
|
|
111
|
+
}.to raise_error(ArgumentError, "Name cannot be blank")
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -6,12 +6,15 @@ RSpec.describe Fx::Generators::TriggerGenerator, :generator do
|
|
|
6
6
|
migration = file("db/migrate/create_trigger_test.rb")
|
|
7
7
|
trigger_definition = file("db/triggers/test_v01.sql")
|
|
8
8
|
|
|
9
|
-
run_generator
|
|
9
|
+
run_generator(
|
|
10
|
+
described_class,
|
|
11
|
+
["test", {"table_name" => "some_table"}]
|
|
12
|
+
)
|
|
10
13
|
|
|
11
14
|
expect(trigger_definition).to exist
|
|
12
|
-
|
|
13
|
-
expect(
|
|
14
|
-
expect(
|
|
15
|
+
expect_to_be_a_migration(migration)
|
|
16
|
+
expect(migration_content(migration)).to include("CreateTriggerTest")
|
|
17
|
+
expect(migration_content(migration)).to include("on: :some_table")
|
|
15
18
|
end
|
|
16
19
|
|
|
17
20
|
context "when passed --no-migration" do
|
|
@@ -19,10 +22,14 @@ RSpec.describe Fx::Generators::TriggerGenerator, :generator do
|
|
|
19
22
|
migration = file("db/migrate/create_trigger_test.rb")
|
|
20
23
|
trigger_definition = file("db/triggers/test_v01.sql")
|
|
21
24
|
|
|
22
|
-
run_generator
|
|
25
|
+
run_generator(
|
|
26
|
+
described_class,
|
|
27
|
+
["test", {"table_name" => "some_table"}],
|
|
28
|
+
{migration: false}
|
|
29
|
+
)
|
|
23
30
|
|
|
24
31
|
expect(trigger_definition).to exist
|
|
25
|
-
expect(
|
|
32
|
+
expect(migration).not_to exist
|
|
26
33
|
end
|
|
27
34
|
end
|
|
28
35
|
|
|
@@ -30,30 +37,46 @@ RSpec.describe Fx::Generators::TriggerGenerator, :generator do
|
|
|
30
37
|
migration = file("db/migrate/create_trigger_test.rb")
|
|
31
38
|
trigger_definition = file("db/triggers/test_v01.sql")
|
|
32
39
|
|
|
33
|
-
run_generator
|
|
40
|
+
run_generator(
|
|
41
|
+
described_class,
|
|
42
|
+
["test", {"on" => "some_table"}]
|
|
43
|
+
)
|
|
34
44
|
|
|
35
45
|
expect(trigger_definition).to exist
|
|
36
|
-
|
|
37
|
-
expect(
|
|
38
|
-
expect(
|
|
46
|
+
expect_to_be_a_migration(migration)
|
|
47
|
+
expect(migration_content(migration)).to include("CreateTriggerTest")
|
|
48
|
+
expect(migration_content(migration)).to include("on: :some_table")
|
|
39
49
|
end
|
|
40
50
|
|
|
41
51
|
it "requires `table_name` or `on` to be specified" do
|
|
42
52
|
expect do
|
|
43
|
-
run_generator
|
|
53
|
+
run_generator(
|
|
54
|
+
described_class,
|
|
55
|
+
["test", {"foo" => "some_table"}]
|
|
56
|
+
)
|
|
44
57
|
end.to raise_error(ArgumentError)
|
|
45
58
|
end
|
|
46
59
|
|
|
47
60
|
it "updates an existing trigger" do
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
with_trigger_definition(
|
|
62
|
+
name: "test",
|
|
63
|
+
version: 1,
|
|
64
|
+
sql_definition: "hello"
|
|
65
|
+
) do
|
|
66
|
+
migration = file("db/migrate/update_trigger_test_to_version_2.rb")
|
|
67
|
+
trigger_definition = file("db/triggers/test_v02.sql")
|
|
51
68
|
|
|
52
|
-
|
|
69
|
+
run_generator(
|
|
70
|
+
described_class,
|
|
71
|
+
["test", {"table_name" => "some_table"}]
|
|
72
|
+
)
|
|
53
73
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
expect(trigger_definition).to exist
|
|
75
|
+
expect_to_be_a_migration(migration)
|
|
76
|
+
expect(migration_content(migration)).to include(
|
|
77
|
+
"UpdateTriggerTestToVersion2"
|
|
78
|
+
)
|
|
79
|
+
expect(migration_content(migration)).to include("on: :some_table")
|
|
80
|
+
end
|
|
58
81
|
end
|
|
59
82
|
end
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "generators/fx/version_helper"
|
|
3
|
+
|
|
4
|
+
RSpec.describe Fx::Generators::VersionHelper do
|
|
5
|
+
describe "#previous_version" do
|
|
6
|
+
it "returns 0 when no existing versions found" do
|
|
7
|
+
with_temp_directory do |temp_dir|
|
|
8
|
+
helper = described_class.new(file_name: "test_function", definition_path: temp_dir)
|
|
9
|
+
|
|
10
|
+
expect(helper.previous_version).to eq(0)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "returns highest version number from existing files" do
|
|
15
|
+
with_temp_directory do |temp_dir|
|
|
16
|
+
create_version_file(temp_dir, "test_function", 1)
|
|
17
|
+
create_version_file(temp_dir, "test_function", 3)
|
|
18
|
+
create_version_file(temp_dir, "test_function", 2)
|
|
19
|
+
|
|
20
|
+
helper = described_class.new(file_name: "test_function", definition_path: temp_dir)
|
|
21
|
+
|
|
22
|
+
expect(helper.previous_version).to eq(3)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "ignores files that don't match the pattern" do
|
|
27
|
+
with_temp_directory do |temp_dir|
|
|
28
|
+
create_version_file(temp_dir, "test_function", 2)
|
|
29
|
+
FileUtils.touch(temp_dir.join("other_function_v3.sql"))
|
|
30
|
+
FileUtils.touch(temp_dir.join("test_function.sql"))
|
|
31
|
+
|
|
32
|
+
helper = described_class.new(file_name: "test_function", definition_path: temp_dir)
|
|
33
|
+
|
|
34
|
+
expect(helper.previous_version).to eq(2)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "#current_version" do
|
|
40
|
+
it "returns previous version + 1" do
|
|
41
|
+
with_temp_directory do |temp_dir|
|
|
42
|
+
create_version_file(temp_dir, "test_function", 5)
|
|
43
|
+
|
|
44
|
+
helper = described_class.new(file_name: "test_function", definition_path: temp_dir)
|
|
45
|
+
|
|
46
|
+
expect(helper.current_version).to eq(6)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "returns 1 when no previous versions exist" do
|
|
51
|
+
with_temp_directory do |temp_dir|
|
|
52
|
+
helper = described_class.new(file_name: "test_function", definition_path: temp_dir)
|
|
53
|
+
|
|
54
|
+
expect(helper.current_version).to eq(1)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe "#updating_existing?" do
|
|
60
|
+
it "returns false when no previous versions exist" do
|
|
61
|
+
with_temp_directory do |temp_dir|
|
|
62
|
+
helper = described_class.new(file_name: "test_function", definition_path: temp_dir)
|
|
63
|
+
|
|
64
|
+
expect(helper.updating_existing?).to be false
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "returns true when previous versions exist" do
|
|
69
|
+
with_temp_directory do |temp_dir|
|
|
70
|
+
create_version_file(temp_dir, "test_function", 1)
|
|
71
|
+
|
|
72
|
+
helper = described_class.new(file_name: "test_function", definition_path: temp_dir)
|
|
73
|
+
|
|
74
|
+
expect(helper.updating_existing?).to be true
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe "#creating_new?" do
|
|
80
|
+
it "returns true when no previous versions exist" do
|
|
81
|
+
with_temp_directory do |temp_dir|
|
|
82
|
+
helper = described_class.new(file_name: "test_function", definition_path: temp_dir)
|
|
83
|
+
|
|
84
|
+
expect(helper.creating_new?).to be true
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "returns false when previous versions exist" do
|
|
89
|
+
with_temp_directory do |temp_dir|
|
|
90
|
+
create_version_file(temp_dir, "test_function", 1)
|
|
91
|
+
|
|
92
|
+
helper = described_class.new(file_name: "test_function", definition_path: temp_dir)
|
|
93
|
+
|
|
94
|
+
expect(helper.creating_new?).to be false
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe "#definition_for_version" do
|
|
100
|
+
it "returns function definition for function type" do
|
|
101
|
+
with_temp_directory do |temp_dir|
|
|
102
|
+
helper = described_class.new(file_name: "test_function", definition_path: temp_dir)
|
|
103
|
+
allow(Fx::Definition).to receive(:function)
|
|
104
|
+
.and_return("function_definition")
|
|
105
|
+
|
|
106
|
+
result = helper.definition_for_version(version: 2, type: :function)
|
|
107
|
+
|
|
108
|
+
expect(result).to eq("function_definition")
|
|
109
|
+
expect(Fx::Definition).to have_received(:function).with(
|
|
110
|
+
name: "test_function",
|
|
111
|
+
version: 2
|
|
112
|
+
)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "returns trigger definition for trigger type" do
|
|
117
|
+
with_temp_directory do |temp_dir|
|
|
118
|
+
helper = described_class.new(file_name: "test_trigger", definition_path: temp_dir)
|
|
119
|
+
allow(Fx::Definition).to receive(:trigger)
|
|
120
|
+
.and_return("trigger_definition")
|
|
121
|
+
|
|
122
|
+
result = helper.definition_for_version(version: 3, type: :trigger)
|
|
123
|
+
|
|
124
|
+
expect(result).to eq("trigger_definition")
|
|
125
|
+
expect(Fx::Definition).to have_received(:trigger).with(
|
|
126
|
+
name: "test_trigger",
|
|
127
|
+
version: 3
|
|
128
|
+
)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "raises error for unknown type" do
|
|
133
|
+
with_temp_directory do |temp_dir|
|
|
134
|
+
helper = described_class.new(file_name: "test_function", definition_path: temp_dir)
|
|
135
|
+
|
|
136
|
+
expect {
|
|
137
|
+
helper.definition_for_version(version: 1, type: :unknown)
|
|
138
|
+
}.to raise_error(
|
|
139
|
+
ArgumentError,
|
|
140
|
+
"Unknown type: unknown. Must be :function or :trigger"
|
|
141
|
+
)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
private
|
|
147
|
+
|
|
148
|
+
def with_temp_directory
|
|
149
|
+
Dir.mktmpdir do |path|
|
|
150
|
+
yield Pathname.new(path)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def create_version_file(dir, name, version)
|
|
155
|
+
FileUtils.touch(dir.join("#{name}_v#{version}.sql"))
|
|
156
|
+
end
|
|
157
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
ENV["RAILS_ENV"] = "test"
|
|
2
|
-
require "database_cleaner"
|
|
3
2
|
|
|
4
3
|
require File.expand_path("../dummy/config/environment", __FILE__)
|
|
5
4
|
Dir["spec/support/**/*.rb"].sort.each { |file| load file }
|
|
@@ -11,12 +10,20 @@ RSpec.configure do |config|
|
|
|
11
10
|
config.order = "random"
|
|
12
11
|
config.disable_monkey_patching!
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
config.define_derived_metadata(file_path: %r{spec/(fx|features)/}) do |metadata|
|
|
14
|
+
metadata[:db] = true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
config.before(:suite) do
|
|
18
|
+
DatabaseReset.call
|
|
19
|
+
end
|
|
15
20
|
|
|
16
21
|
config.around(:each, db: true) do |example|
|
|
17
|
-
|
|
22
|
+
DatabaseReset.call
|
|
23
|
+
|
|
18
24
|
example.run
|
|
19
|
-
|
|
25
|
+
|
|
26
|
+
DatabaseReset.call
|
|
20
27
|
end
|
|
21
28
|
|
|
22
29
|
unless defined?(silence_stream)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module DatabaseReset
|
|
2
|
+
def self.call
|
|
3
|
+
connection = ActiveRecord::Base.connection
|
|
4
|
+
connection.execute("SET search_path TO DEFAULT;")
|
|
5
|
+
|
|
6
|
+
connection.execute <<~SQL
|
|
7
|
+
DO $$
|
|
8
|
+
DECLARE
|
|
9
|
+
schema_name TEXT;
|
|
10
|
+
BEGIN
|
|
11
|
+
FOR schema_name IN
|
|
12
|
+
SELECT nspname FROM pg_namespace
|
|
13
|
+
WHERE nspname NOT LIKE 'pg_%'
|
|
14
|
+
AND nspname != 'information_schema'
|
|
15
|
+
LOOP
|
|
16
|
+
EXECUTE format('DROP SCHEMA IF EXISTS %I CASCADE', schema_name);
|
|
17
|
+
END LOOP;
|
|
18
|
+
END $$;
|
|
19
|
+
SQL
|
|
20
|
+
|
|
21
|
+
connection.execute("CREATE SCHEMA public;")
|
|
22
|
+
connection.schema_search_path = "public"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -1,11 +1,52 @@
|
|
|
1
|
-
|
|
1
|
+
module GeneratorSetup
|
|
2
|
+
RAILS_ROOT = Pathname.new(File.expand_path("../../../tmp/dummy", __dir__)).freeze
|
|
3
|
+
MIGRATION_TIMESTAMP_PATTERN = /\A\d{14}_/
|
|
4
|
+
|
|
5
|
+
def run_generator(generator_class, args = [], options = {})
|
|
6
|
+
allow(Rails).to receive(:root).and_return(RAILS_ROOT)
|
|
7
|
+
generator = generator_class.new(args, options, destination_root: RAILS_ROOT)
|
|
8
|
+
|
|
9
|
+
silence_stream($stdout) do
|
|
10
|
+
generator.invoke_all
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def file(relative_path)
|
|
15
|
+
RAILS_ROOT.join(relative_path)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def migration_content(file_path)
|
|
19
|
+
migration_path = find_migration_files(file_path).first
|
|
20
|
+
return if migration_path.nil?
|
|
21
|
+
|
|
22
|
+
Pathname.new(migration_path).read
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def find_migration_files(file_path)
|
|
26
|
+
directory = File.dirname(file_path)
|
|
27
|
+
basename = File.basename(file_path, ".rb")
|
|
28
|
+
Dir.glob(File.join(directory, "*#{basename}.rb"))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def expect_to_be_a_migration(pathname)
|
|
32
|
+
migration_files = find_migration_files(pathname)
|
|
33
|
+
|
|
34
|
+
expect(migration_files).to be_present,
|
|
35
|
+
"expected #{pathname} to be a migration file"
|
|
36
|
+
first_migration = migration_files.first
|
|
37
|
+
migration_basename = File.basename(first_migration)
|
|
38
|
+
expect(migration_basename).to match(MIGRATION_TIMESTAMP_PATTERN),
|
|
39
|
+
"expected #{migration_basename} to have timestamp prefix (format: YYYYMMDDHHMMSS_)"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
2
42
|
|
|
3
43
|
RSpec.configure do |config|
|
|
44
|
+
config.include GeneratorSetup, :generator
|
|
45
|
+
|
|
4
46
|
config.before(:each, :generator) do
|
|
5
|
-
|
|
6
|
-
|
|
47
|
+
FileUtils.rm_rf(GeneratorSetup::RAILS_ROOT) if File.exist?(GeneratorSetup::RAILS_ROOT)
|
|
48
|
+
FileUtils.mkdir_p(GeneratorSetup::RAILS_ROOT)
|
|
7
49
|
|
|
8
|
-
|
|
9
|
-
prepare_destination
|
|
50
|
+
allow(Rails).to receive(:root).and_return(Pathname.new(GeneratorSetup::RAILS_ROOT))
|
|
10
51
|
end
|
|
11
52
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fx
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.10.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Teo Ljungberg
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date: 1980-01-
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: activerecord
|
|
@@ -16,28 +15,40 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - ">="
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '7.
|
|
18
|
+
version: '7.2'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '8.2'
|
|
20
22
|
type: :runtime
|
|
21
23
|
prerelease: false
|
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
25
|
requirements:
|
|
24
26
|
- - ">="
|
|
25
27
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '7.
|
|
28
|
+
version: '7.2'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '8.2'
|
|
27
32
|
- !ruby/object:Gem::Dependency
|
|
28
33
|
name: railties
|
|
29
34
|
requirement: !ruby/object:Gem::Requirement
|
|
30
35
|
requirements:
|
|
31
36
|
- - ">="
|
|
32
37
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '7.
|
|
38
|
+
version: '7.2'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '8.2'
|
|
34
42
|
type: :runtime
|
|
35
43
|
prerelease: false
|
|
36
44
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
45
|
requirements:
|
|
38
46
|
- - ">="
|
|
39
47
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '7.
|
|
48
|
+
version: '7.2'
|
|
49
|
+
- - "<"
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '8.2'
|
|
41
52
|
description: |
|
|
42
53
|
Adds methods to ActiveRecord::Migration to create and manage database functions
|
|
43
54
|
and triggers in Rails
|
|
@@ -69,6 +80,7 @@ files:
|
|
|
69
80
|
- lib/fx/adapters/postgres.rb
|
|
70
81
|
- lib/fx/adapters/postgres/connection.rb
|
|
71
82
|
- lib/fx/adapters/postgres/functions.rb
|
|
83
|
+
- lib/fx/adapters/postgres/query_executor.rb
|
|
72
84
|
- lib/fx/adapters/postgres/triggers.rb
|
|
73
85
|
- lib/fx/command_recorder.rb
|
|
74
86
|
- lib/fx/configuration.rb
|
|
@@ -84,10 +96,13 @@ files:
|
|
|
84
96
|
- lib/generators/fx/function/function_generator.rb
|
|
85
97
|
- lib/generators/fx/function/templates/db/migrate/create_function.erb
|
|
86
98
|
- lib/generators/fx/function/templates/db/migrate/update_function.erb
|
|
99
|
+
- lib/generators/fx/migration_helper.rb
|
|
100
|
+
- lib/generators/fx/name_helper.rb
|
|
87
101
|
- lib/generators/fx/trigger/USAGE
|
|
88
102
|
- lib/generators/fx/trigger/templates/db/migrate/create_trigger.erb
|
|
89
103
|
- lib/generators/fx/trigger/templates/db/migrate/update_trigger.erb
|
|
90
104
|
- lib/generators/fx/trigger/trigger_generator.rb
|
|
105
|
+
- lib/generators/fx/version_helper.rb
|
|
91
106
|
- spec/acceptance/user_manages_functions_spec.rb
|
|
92
107
|
- spec/acceptance/user_manages_triggers_spec.rb
|
|
93
108
|
- spec/acceptance_helper.rb
|
|
@@ -107,6 +122,7 @@ files:
|
|
|
107
122
|
- spec/features/triggers/migrations_spec.rb
|
|
108
123
|
- spec/features/triggers/revert_spec.rb
|
|
109
124
|
- spec/fx/adapters/postgres/functions_spec.rb
|
|
125
|
+
- spec/fx/adapters/postgres/query_executor_spec.rb
|
|
110
126
|
- spec/fx/adapters/postgres/triggers_spec.rb
|
|
111
127
|
- spec/fx/adapters/postgres_spec.rb
|
|
112
128
|
- spec/fx/command_recorder_spec.rb
|
|
@@ -118,8 +134,12 @@ files:
|
|
|
118
134
|
- spec/fx/trigger_spec.rb
|
|
119
135
|
- spec/fx_spec.rb
|
|
120
136
|
- spec/generators/fx/function/function_generator_spec.rb
|
|
137
|
+
- spec/generators/fx/migration_helper_spec.rb
|
|
138
|
+
- spec/generators/fx/name_helper_spec.rb
|
|
121
139
|
- spec/generators/fx/trigger/trigger_generator_spec.rb
|
|
140
|
+
- spec/generators/fx/version_helper_spec.rb
|
|
122
141
|
- spec/spec_helper.rb
|
|
142
|
+
- spec/support/database_reset.rb
|
|
123
143
|
- spec/support/definition_helpers.rb
|
|
124
144
|
- spec/support/generator_setup.rb
|
|
125
145
|
- spec/support/migration_helpers.rb
|
|
@@ -129,10 +149,9 @@ licenses:
|
|
|
129
149
|
- MIT
|
|
130
150
|
metadata:
|
|
131
151
|
bug_tracker_uri: https://github.com/teoljungberg/fx/issues
|
|
132
|
-
changelog_uri: https://github.com/teoljungberg/fx/blob/v0.
|
|
152
|
+
changelog_uri: https://github.com/teoljungberg/fx/blob/v0.10.1/CHANGELOG.md
|
|
133
153
|
homepage_uri: https://github.com/teoljungberg/fx
|
|
134
154
|
source_code_uri: https://github.com/teoljungberg/fx
|
|
135
|
-
post_install_message:
|
|
136
155
|
rdoc_options: []
|
|
137
156
|
require_paths:
|
|
138
157
|
- lib
|
|
@@ -140,15 +159,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
140
159
|
requirements:
|
|
141
160
|
- - ">="
|
|
142
161
|
- !ruby/object:Gem::Version
|
|
143
|
-
version: '3.
|
|
162
|
+
version: '3.2'
|
|
144
163
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
164
|
requirements:
|
|
146
165
|
- - ">="
|
|
147
166
|
- !ruby/object:Gem::Version
|
|
148
167
|
version: '0'
|
|
149
168
|
requirements: []
|
|
150
|
-
rubygems_version:
|
|
151
|
-
signing_key:
|
|
169
|
+
rubygems_version: 4.0.6
|
|
152
170
|
specification_version: 4
|
|
153
171
|
summary: Support for database functions and triggers in Rails migrations
|
|
154
172
|
test_files: []
|