fx 0.9.0 → 0.10.2
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 +10 -4
- data/CHANGELOG.md +51 -1
- data/Gemfile +10 -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 +18 -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.2
|
|
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,28 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - ">="
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '7.
|
|
18
|
+
version: '7.2'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '7.
|
|
25
|
+
version: '7.2'
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: railties
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
30
29
|
requirements:
|
|
31
30
|
- - ">="
|
|
32
31
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '7.
|
|
32
|
+
version: '7.2'
|
|
34
33
|
type: :runtime
|
|
35
34
|
prerelease: false
|
|
36
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
36
|
requirements:
|
|
38
37
|
- - ">="
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '7.
|
|
39
|
+
version: '7.2'
|
|
41
40
|
description: |
|
|
42
41
|
Adds methods to ActiveRecord::Migration to create and manage database functions
|
|
43
42
|
and triggers in Rails
|
|
@@ -69,6 +68,7 @@ files:
|
|
|
69
68
|
- lib/fx/adapters/postgres.rb
|
|
70
69
|
- lib/fx/adapters/postgres/connection.rb
|
|
71
70
|
- lib/fx/adapters/postgres/functions.rb
|
|
71
|
+
- lib/fx/adapters/postgres/query_executor.rb
|
|
72
72
|
- lib/fx/adapters/postgres/triggers.rb
|
|
73
73
|
- lib/fx/command_recorder.rb
|
|
74
74
|
- lib/fx/configuration.rb
|
|
@@ -84,10 +84,13 @@ files:
|
|
|
84
84
|
- lib/generators/fx/function/function_generator.rb
|
|
85
85
|
- lib/generators/fx/function/templates/db/migrate/create_function.erb
|
|
86
86
|
- lib/generators/fx/function/templates/db/migrate/update_function.erb
|
|
87
|
+
- lib/generators/fx/migration_helper.rb
|
|
88
|
+
- lib/generators/fx/name_helper.rb
|
|
87
89
|
- lib/generators/fx/trigger/USAGE
|
|
88
90
|
- lib/generators/fx/trigger/templates/db/migrate/create_trigger.erb
|
|
89
91
|
- lib/generators/fx/trigger/templates/db/migrate/update_trigger.erb
|
|
90
92
|
- lib/generators/fx/trigger/trigger_generator.rb
|
|
93
|
+
- lib/generators/fx/version_helper.rb
|
|
91
94
|
- spec/acceptance/user_manages_functions_spec.rb
|
|
92
95
|
- spec/acceptance/user_manages_triggers_spec.rb
|
|
93
96
|
- spec/acceptance_helper.rb
|
|
@@ -107,6 +110,7 @@ files:
|
|
|
107
110
|
- spec/features/triggers/migrations_spec.rb
|
|
108
111
|
- spec/features/triggers/revert_spec.rb
|
|
109
112
|
- spec/fx/adapters/postgres/functions_spec.rb
|
|
113
|
+
- spec/fx/adapters/postgres/query_executor_spec.rb
|
|
110
114
|
- spec/fx/adapters/postgres/triggers_spec.rb
|
|
111
115
|
- spec/fx/adapters/postgres_spec.rb
|
|
112
116
|
- spec/fx/command_recorder_spec.rb
|
|
@@ -118,8 +122,12 @@ files:
|
|
|
118
122
|
- spec/fx/trigger_spec.rb
|
|
119
123
|
- spec/fx_spec.rb
|
|
120
124
|
- spec/generators/fx/function/function_generator_spec.rb
|
|
125
|
+
- spec/generators/fx/migration_helper_spec.rb
|
|
126
|
+
- spec/generators/fx/name_helper_spec.rb
|
|
121
127
|
- spec/generators/fx/trigger/trigger_generator_spec.rb
|
|
128
|
+
- spec/generators/fx/version_helper_spec.rb
|
|
122
129
|
- spec/spec_helper.rb
|
|
130
|
+
- spec/support/database_reset.rb
|
|
123
131
|
- spec/support/definition_helpers.rb
|
|
124
132
|
- spec/support/generator_setup.rb
|
|
125
133
|
- spec/support/migration_helpers.rb
|
|
@@ -129,10 +137,9 @@ licenses:
|
|
|
129
137
|
- MIT
|
|
130
138
|
metadata:
|
|
131
139
|
bug_tracker_uri: https://github.com/teoljungberg/fx/issues
|
|
132
|
-
changelog_uri: https://github.com/teoljungberg/fx/blob/v0.
|
|
140
|
+
changelog_uri: https://github.com/teoljungberg/fx/blob/v0.10.2/CHANGELOG.md
|
|
133
141
|
homepage_uri: https://github.com/teoljungberg/fx
|
|
134
142
|
source_code_uri: https://github.com/teoljungberg/fx
|
|
135
|
-
post_install_message:
|
|
136
143
|
rdoc_options: []
|
|
137
144
|
require_paths:
|
|
138
145
|
- lib
|
|
@@ -140,15 +147,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
140
147
|
requirements:
|
|
141
148
|
- - ">="
|
|
142
149
|
- !ruby/object:Gem::Version
|
|
143
|
-
version: '3.
|
|
150
|
+
version: '3.2'
|
|
144
151
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
152
|
requirements:
|
|
146
153
|
- - ">="
|
|
147
154
|
- !ruby/object:Gem::Version
|
|
148
155
|
version: '0'
|
|
149
156
|
requirements: []
|
|
150
|
-
rubygems_version:
|
|
151
|
-
signing_key:
|
|
157
|
+
rubygems_version: 4.0.6
|
|
152
158
|
specification_version: 4
|
|
153
159
|
summary: Support for database functions and triggers in Rails migrations
|
|
154
160
|
test_files: []
|