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.
Files changed (106) hide show
  1. checksums.yaml +5 -5
  2. data/.github/scripts/check-eol +95 -0
  3. data/.github/workflows/ci.yml +61 -0
  4. data/.github/workflows/eol-check.yml +30 -0
  5. data/.rspec +1 -1
  6. data/.standard.yml +3 -0
  7. data/CHANGELOG.md +186 -0
  8. data/CONTRIBUTING.md +13 -4
  9. data/Gemfile +21 -2
  10. data/LICENSE +18 -0
  11. data/README.md +99 -14
  12. data/Rakefile +11 -1
  13. data/bin/rake +2 -3
  14. data/bin/rspec +13 -3
  15. data/bin/setup +1 -4
  16. data/bin/standardrb +27 -0
  17. data/bin/yard +13 -3
  18. data/fx.gemspec +20 -27
  19. data/lib/fx/adapters/postgres/connection.rb +6 -0
  20. data/lib/fx/adapters/postgres/functions.rb +16 -28
  21. data/lib/fx/adapters/postgres/query_executor.rb +34 -0
  22. data/lib/fx/adapters/postgres/triggers.rb +14 -28
  23. data/lib/fx/adapters/postgres.rb +30 -17
  24. data/lib/fx/command_recorder.rb +104 -13
  25. data/lib/fx/configuration.rb +10 -25
  26. data/lib/fx/definition.rb +32 -10
  27. data/lib/fx/function.rb +23 -9
  28. data/lib/fx/railtie.rb +15 -0
  29. data/lib/fx/schema_dumper.rb +33 -10
  30. data/lib/fx/statements.rb +213 -11
  31. data/lib/fx/trigger.rb +5 -3
  32. data/lib/fx/version.rb +1 -1
  33. data/lib/fx.rb +40 -0
  34. data/lib/generators/fx/function/USAGE +2 -0
  35. data/lib/generators/fx/function/function_generator.rb +54 -39
  36. data/lib/generators/fx/function/templates/db/migrate/create_function.erb +1 -1
  37. data/lib/generators/fx/function/templates/db/migrate/update_function.erb +1 -1
  38. data/lib/generators/fx/migration_helper.rb +45 -0
  39. data/lib/generators/fx/name_helper.rb +33 -0
  40. data/lib/generators/fx/trigger/USAGE +2 -0
  41. data/lib/generators/fx/trigger/templates/db/migrate/create_trigger.erb +1 -1
  42. data/lib/generators/fx/trigger/templates/db/migrate/update_trigger.erb +1 -1
  43. data/lib/generators/fx/trigger/trigger_generator.rb +46 -51
  44. data/lib/generators/fx/version_helper.rb +55 -0
  45. data/spec/acceptance/user_manages_functions_spec.rb +26 -6
  46. data/spec/acceptance/user_manages_triggers_spec.rb +11 -11
  47. data/spec/acceptance_helper.rb +17 -11
  48. data/spec/dummy/Rakefile +8 -1
  49. data/spec/dummy/bin/bundle +2 -2
  50. data/spec/dummy/bin/rails +3 -3
  51. data/spec/dummy/bin/rake +2 -2
  52. data/spec/dummy/config/application.rb +2 -0
  53. data/spec/dummy/config/database.yml +2 -0
  54. data/spec/dummy/config.ru +1 -1
  55. data/spec/features/functions/migrations_spec.rb +9 -9
  56. data/spec/features/functions/revert_spec.rb +13 -13
  57. data/spec/features/triggers/migrations_spec.rb +11 -11
  58. data/spec/features/triggers/revert_spec.rb +21 -21
  59. data/spec/fx/adapters/postgres/functions_spec.rb +40 -0
  60. data/spec/fx/adapters/postgres/query_executor_spec.rb +75 -0
  61. data/spec/fx/adapters/postgres/triggers_spec.rb +48 -0
  62. data/spec/fx/adapters/postgres_spec.rb +115 -111
  63. data/spec/fx/command_recorder_spec.rb +39 -53
  64. data/spec/fx/configuration_spec.rb +20 -9
  65. data/spec/fx/definition_spec.rb +53 -38
  66. data/spec/fx/function_spec.rb +143 -0
  67. data/spec/fx/schema_dumper_spec.rb +241 -0
  68. data/spec/fx/statements_spec.rb +219 -0
  69. data/spec/fx/trigger_spec.rb +52 -0
  70. data/spec/fx_spec.rb +28 -0
  71. data/spec/generators/fx/function/function_generator_spec.rb +22 -10
  72. data/spec/generators/fx/migration_helper_spec.rb +108 -0
  73. data/spec/generators/fx/name_helper_spec.rb +114 -0
  74. data/spec/generators/fx/trigger/trigger_generator_spec.rb +55 -20
  75. data/spec/generators/fx/version_helper_spec.rb +157 -0
  76. data/spec/spec_helper.rb +16 -4
  77. data/spec/support/database_reset.rb +24 -0
  78. data/spec/support/definition_helpers.rb +5 -9
  79. data/spec/support/generator_setup.rb +46 -5
  80. data/spec/support/migration_helpers.rb +9 -1
  81. data/spec/support/warning_helper.rb +5 -0
  82. metadata +43 -215
  83. data/.ruby-version +0 -1
  84. data/.travis.yml +0 -27
  85. data/Appraisals +0 -21
  86. data/bin/appraisal +0 -17
  87. data/gemfiles/rails40.gemfile +0 -8
  88. data/gemfiles/rails40.gemfile.lock +0 -111
  89. data/gemfiles/rails41.gemfile +0 -8
  90. data/gemfiles/rails41.gemfile.lock +0 -113
  91. data/gemfiles/rails42.gemfile +0 -8
  92. data/gemfiles/rails42.gemfile.lock +0 -130
  93. data/gemfiles/rails50.gemfile +0 -8
  94. data/gemfiles/rails50.gemfile.lock +0 -126
  95. data/lib/fx/command_recorder/arguments.rb +0 -43
  96. data/lib/fx/command_recorder/function.rb +0 -30
  97. data/lib/fx/command_recorder/trigger.rb +0 -30
  98. data/lib/fx/schema_dumper/function.rb +0 -29
  99. data/lib/fx/schema_dumper/trigger.rb +0 -29
  100. data/lib/fx/statements/function.rb +0 -105
  101. data/lib/fx/statements/trigger.rb +0 -133
  102. data/spec/fx/command_recorder/arguments_spec.rb +0 -41
  103. data/spec/fx/schema_dumper/function_spec.rb +0 -22
  104. data/spec/fx/schema_dumper/trigger_spec.rb +0 -40
  105. data/spec/fx/statements/function_spec.rb +0 -103
  106. data/spec/fx/statements/trigger_spec.rb +0 -132
@@ -0,0 +1,241 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Fx::SchemaDumper, :db do
4
+ it "dumps a create_function for a function in the database" do
5
+ sql_definition = <<~SQL
6
+ CREATE OR REPLACE FUNCTION my_function()
7
+ RETURNS text AS $$
8
+ BEGIN
9
+ RETURN 'test';
10
+ END;
11
+ $$ LANGUAGE plpgsql;
12
+ SQL
13
+ connection.create_function :my_function, sql_definition: sql_definition
14
+ connection.create_table :my_table
15
+ stream = StringIO.new
16
+ output = stream.string
17
+
18
+ dump(connection: connection, stream: stream)
19
+
20
+ expect(output).to match(
21
+ /table "my_table".*function :my_function.*RETURN 'test';/m
22
+ )
23
+ end
24
+
25
+ it "dumps a create_function for a function in the database" do
26
+ Fx.configuration.dump_functions_at_beginning_of_schema = true
27
+ sql_definition = <<~SQL
28
+ CREATE OR REPLACE FUNCTION my_function()
29
+ RETURNS text AS $$
30
+ BEGIN
31
+ RETURN 'test';
32
+ END;
33
+ $$ LANGUAGE plpgsql;
34
+ SQL
35
+ connection.create_function :my_function, sql_definition: sql_definition
36
+ connection.create_table :my_table
37
+ stream = StringIO.new
38
+ output = stream.string
39
+
40
+ dump(connection: connection, stream: stream)
41
+
42
+ expect(output).to(
43
+ match(/function :my_function.*RETURN 'test';.*table "my_table"/m)
44
+ )
45
+
46
+ Fx.configuration.dump_functions_at_beginning_of_schema = false
47
+ end
48
+
49
+ it "does not dump a create_function for aggregates in the database" do
50
+ sql_definition = <<~SQL
51
+ CREATE OR REPLACE FUNCTION test(text, text)
52
+ RETURNS text AS $$
53
+ BEGIN
54
+ RETURN 'test';
55
+ END;
56
+ $$ LANGUAGE plpgsql;
57
+ SQL
58
+
59
+ aggregate_sql_definition = <<~SQL
60
+ CREATE AGGREGATE aggregate_test(text)
61
+ (
62
+ sfunc = test,
63
+ stype = text
64
+ );
65
+ SQL
66
+
67
+ connection.create_function :test, sql_definition: sql_definition
68
+ connection.execute aggregate_sql_definition
69
+ stream = StringIO.new
70
+
71
+ dump(connection: connection, stream: stream)
72
+
73
+ output = stream.string
74
+ expect(output).to include("create_function :test, sql_definition: <<-'SQL'")
75
+ expect(output).to include("RETURN 'test';")
76
+ expect(output).not_to include("aggregate_test")
77
+ end
78
+
79
+ it "dumps a create_trigger for a trigger in the database" do
80
+ connection.execute <<~SQL
81
+ CREATE TABLE users (
82
+ id int PRIMARY KEY,
83
+ name varchar(256),
84
+ upper_name varchar(256)
85
+ );
86
+ SQL
87
+ Fx.database.create_function <<~SQL
88
+ CREATE OR REPLACE FUNCTION uppercase_users_name()
89
+ RETURNS trigger AS $$
90
+ BEGIN
91
+ NEW.upper_name = UPPER(NEW.name);
92
+ RETURN NEW;
93
+ END;
94
+ $$ LANGUAGE plpgsql;
95
+ SQL
96
+ sql_definition = <<~SQL
97
+ CREATE TRIGGER uppercase_users_name
98
+ BEFORE INSERT ON users
99
+ FOR EACH ROW
100
+ EXECUTE FUNCTION uppercase_users_name();
101
+ SQL
102
+ connection.create_trigger(
103
+ :uppercase_users_name,
104
+ sql_definition: sql_definition
105
+ )
106
+ stream = StringIO.new
107
+
108
+ dump(connection: connection, stream: stream)
109
+
110
+ output = stream.string
111
+ expect(output).to include("create_trigger :uppercase_users_name")
112
+ expect(output).to include("sql_definition: <<-SQL")
113
+ expect(output).to include("EXECUTE FUNCTION uppercase_users_name()")
114
+ end
115
+
116
+ it "dumps functions and triggers for multiple schemas" do
117
+ connection.schema_search_path = "public,test_schema"
118
+ connection.create_table :my_table
119
+ connection.create_function :test1, sql_definition: <<~SQL
120
+ CREATE OR REPLACE FUNCTION test_public_func()
121
+ RETURNS TRIGGER AS $$
122
+ BEGIN
123
+ RETURN 1;
124
+ END;
125
+ $$ LANGUAGE plpgsql;
126
+ SQL
127
+ connection.create_trigger :test1_trigger, sql_definition: <<~SQL
128
+ CREATE TRIGGER test_public_trigger
129
+ BEFORE INSERT ON my_table
130
+ FOR EACH ROW
131
+ EXECUTE FUNCTION test_public_func();
132
+ SQL
133
+ connection.execute("CREATE SCHEMA test_schema;")
134
+ connection.create_table "test_schema.my_table2"
135
+ connection.execute <<~SQL
136
+ CREATE OR REPLACE FUNCTION test_schema.test_schema_func()
137
+ RETURNS TRIGGER AS $$
138
+ BEGIN
139
+ RETURN 'test_schema';
140
+ END;
141
+ $$ LANGUAGE plpgsql;
142
+ SQL
143
+ connection.execute <<~SQL
144
+ CREATE TRIGGER test_schema_trigger
145
+ BEFORE INSERT ON test_schema.my_table2
146
+ FOR EACH ROW
147
+ EXECUTE FUNCTION test_schema.test_schema_func();
148
+ SQL
149
+ stream = StringIO.new
150
+ output = stream.string
151
+
152
+ dump(connection: connection, stream: stream)
153
+
154
+ expect(output.scan("create_function :test_public_func").size).to eq(1)
155
+ expect(output.scan("create_trigger :test_public_trigger").size).to eq(1)
156
+ expect(output.scan("create_function :test_schema_func").size).to eq(1)
157
+ expect(output.scan("create_trigger :test_schema_trigger").size).to eq(1)
158
+ ensure
159
+ connection.schema_search_path = "public"
160
+ end
161
+
162
+ it "puts a blank line before each function and trigger" do
163
+ connection.create_table :users do |t|
164
+ t.string :name
165
+ t.string :upper_name
166
+ t.string :down_name
167
+ end
168
+ Fx.database.create_function <<~SQL
169
+ CREATE OR REPLACE FUNCTION uppercase_users_name()
170
+ RETURNS trigger AS $$
171
+ BEGIN
172
+ NEW.upper_name = UPPER(NEW.name);
173
+ RETURN NEW;
174
+ END;
175
+ $$ LANGUAGE plpgsql;
176
+ SQL
177
+ sql_definition = <<~SQL
178
+ CREATE TRIGGER uppercase_users_name
179
+ BEFORE INSERT ON users
180
+ FOR EACH ROW
181
+ EXECUTE FUNCTION uppercase_users_name();
182
+ SQL
183
+ connection.create_trigger(
184
+ :uppercase_users_name,
185
+ sql_definition: sql_definition
186
+ )
187
+ Fx.database.create_function <<~SQL
188
+ CREATE OR REPLACE FUNCTION downcase_users_name()
189
+ RETURNS trigger AS $$
190
+ BEGIN
191
+ NEW.down_name = LOWER(NEW.name);
192
+ RETURN NEW;
193
+ END;
194
+ $$ LANGUAGE plpgsql;
195
+ SQL
196
+ sql_definition = <<~SQL
197
+ CREATE TRIGGER downcase_users_name
198
+ BEFORE INSERT ON users
199
+ FOR EACH ROW
200
+ EXECUTE FUNCTION downcase_users_name();
201
+ SQL
202
+ connection.create_trigger(
203
+ :downcase_users_name,
204
+ sql_definition: sql_definition
205
+ )
206
+ stream = StringIO.new
207
+ output = stream.string
208
+
209
+ dump(connection: connection, stream: stream)
210
+
211
+ pattern = /(end|SQL)\n\n (create_function|create_trigger)/
212
+ # a blank line between:
213
+ # - the table and the uppercase_users_name function,
214
+ # - the uppercase_users_name function and the downcase_users_name function,
215
+ # - the downcase_users_name function and the uppercase_users_name trigger,
216
+ # - the uppercase_users_name trigger and the downcase_users_name trigger,
217
+ expect(output.scan(pattern).size).to eq(4)
218
+ end
219
+
220
+ it "does not add blank lines when there are no functions or triggers" do
221
+ connection.create_table :users do |t|
222
+ t.string :name
223
+ end
224
+ stream = StringIO.new
225
+ output = stream.string
226
+
227
+ dump(connection: connection, stream: stream)
228
+
229
+ expect(output).not_to match(/create_function/)
230
+ expect(output).not_to match(/create_trigger/)
231
+ expect(output).not_to match(/end\n\n\nend/)
232
+ end
233
+
234
+ def dump(connection:, stream:)
235
+ if Rails.version >= "7.2"
236
+ ActiveRecord::SchemaDumper.dump(connection.pool, stream)
237
+ else
238
+ ActiveRecord::SchemaDumper.dump(connection, stream)
239
+ end
240
+ end
241
+ end
@@ -0,0 +1,219 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Fx::Statements, :db do
4
+ describe "#create_function" do
5
+ it "creates a function from a file" do
6
+ database = stubbed_database
7
+ definition = stubbed_definition
8
+
9
+ connection.create_function(:test)
10
+
11
+ expect(database).to have_received(:create_function)
12
+ .with(definition.to_sql)
13
+ expect(Fx::Definition).to have_received(:function)
14
+ .with(name: :test, version: 1)
15
+ end
16
+
17
+ it "allows creating a function with a specific version" do
18
+ database = stubbed_database
19
+ definition = stubbed_definition
20
+
21
+ connection.create_function(:test, version: 2)
22
+
23
+ expect(database).to have_received(:create_function)
24
+ .with(definition.to_sql)
25
+ expect(Fx::Definition).to have_received(:function)
26
+ .with(name: :test, version: 2)
27
+ end
28
+
29
+ it "raises an error if both arguments are nil" do
30
+ expect do
31
+ connection.create_function(
32
+ :whatever,
33
+ version: nil,
34
+ sql_definition: nil
35
+ )
36
+ end.to raise_error(
37
+ ArgumentError,
38
+ /version or sql_definition must be specified/
39
+ )
40
+ end
41
+ end
42
+
43
+ describe "#drop_function" do
44
+ it "drops the function" do
45
+ database = stubbed_database
46
+
47
+ connection.drop_function(:test)
48
+
49
+ expect(database).to have_received(:drop_function).with(:test)
50
+ end
51
+ end
52
+
53
+ describe "#update_function" do
54
+ it "updates the function" do
55
+ database = stubbed_database
56
+ definition = stubbed_definition
57
+
58
+ connection.update_function(:test, version: 3)
59
+
60
+ expect(database).to have_received(:update_function)
61
+ .with(:test, definition.to_sql)
62
+ expect(Fx::Definition).to have_received(:function)
63
+ .with(name: :test, version: 3)
64
+ end
65
+
66
+ it "updates a function from a text definition" do
67
+ database = stubbed_database
68
+
69
+ connection.update_function(:test, sql_definition: "a definition")
70
+
71
+ expect(database).to have_received(:update_function)
72
+ .with(:test, "a definition")
73
+ end
74
+
75
+ it "raises an error if not supplied a version" do
76
+ expect do
77
+ connection.update_function(
78
+ :whatever,
79
+ version: nil,
80
+ sql_definition: nil
81
+ )
82
+ end.to raise_error(
83
+ ArgumentError,
84
+ /version or sql_definition must be specified/
85
+ )
86
+ end
87
+ end
88
+
89
+ describe "#create_trigger" do
90
+ it "creates a trigger from a file" do
91
+ database = stubbed_database
92
+ definition = stubbed_definition
93
+
94
+ connection.create_trigger(:test)
95
+
96
+ expect(database).to have_received(:create_trigger)
97
+ .with(definition.to_sql)
98
+ expect(Fx::Definition).to have_received(:trigger)
99
+ .with(name: :test, version: 1)
100
+ end
101
+
102
+ it "allows creating a trigger with a specific version" do
103
+ database = stubbed_database
104
+ definition = stubbed_definition
105
+
106
+ connection.create_trigger(:test, version: 2)
107
+
108
+ expect(database).to have_received(:create_trigger)
109
+ .with(definition.to_sql)
110
+ expect(Fx::Definition).to have_received(:trigger)
111
+ .with(name: :test, version: 2)
112
+ end
113
+
114
+ it "raises an error if both arguments are set" do
115
+ stubbed_database
116
+
117
+ expect do
118
+ connection.create_trigger(
119
+ :whatever,
120
+ version: 1,
121
+ sql_definition: "a definition"
122
+ )
123
+ end.to raise_error(
124
+ ArgumentError,
125
+ /cannot both be set/
126
+ )
127
+ end
128
+ end
129
+
130
+ describe "#drop_trigger" do
131
+ it "drops the trigger" do
132
+ database = stubbed_database
133
+
134
+ connection.drop_trigger(:test, on: :users)
135
+
136
+ expect(database).to have_received(:drop_trigger)
137
+ .with(:test, on: :users)
138
+ end
139
+ end
140
+
141
+ describe "#update_trigger" do
142
+ it "updates the trigger" do
143
+ database = stubbed_database
144
+ definition = stubbed_definition
145
+
146
+ connection.update_trigger(:test, on: :users, version: 3)
147
+
148
+ expect(database).to have_received(:update_trigger).with(
149
+ :test,
150
+ on: :users,
151
+ sql_definition: definition.to_sql
152
+ )
153
+ expect(Fx::Definition).to have_received(:trigger).with(
154
+ name: :test,
155
+ version: 3
156
+ )
157
+ end
158
+
159
+ it "updates a trigger from a text definition" do
160
+ database = stubbed_database
161
+
162
+ connection.update_trigger(
163
+ :test,
164
+ on: :users,
165
+ sql_definition: "a definition"
166
+ )
167
+
168
+ expect(database).to have_received(:update_trigger).with(
169
+ :test,
170
+ on: :users,
171
+ sql_definition: "a definition"
172
+ )
173
+ end
174
+
175
+ it "raises an error if not supplied a version" do
176
+ expect do
177
+ connection.update_trigger(
178
+ :whatever,
179
+ on: :users,
180
+ version: nil,
181
+ sql_definition: nil
182
+ )
183
+ end.to raise_error(
184
+ ArgumentError,
185
+ /version or sql_definition must be specified/
186
+ )
187
+ end
188
+
189
+ it "raises an error if both arguments are set" do
190
+ stubbed_database
191
+
192
+ expect do
193
+ connection.update_trigger(
194
+ :whatever,
195
+ on: :users,
196
+ version: 1,
197
+ sql_definition: "a definition"
198
+ )
199
+ end.to raise_error(
200
+ ArgumentError,
201
+ /cannot both be set/
202
+ )
203
+ end
204
+ end
205
+
206
+ def stubbed_definition
207
+ instance_double("Fx::Definition", to_sql: nil).tap do |stubbed_definition|
208
+ allow(Fx::Definition).to receive(:function).and_return(stubbed_definition)
209
+ allow(Fx::Definition).to receive(:trigger).and_return(stubbed_definition)
210
+ end
211
+ end
212
+
213
+ def stubbed_database
214
+ database = instance_spy("StubbedDatabase")
215
+ allow(Fx).to receive(:database).and_return(database)
216
+
217
+ database
218
+ end
219
+ end
@@ -0,0 +1,52 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Fx::Trigger do
4
+ describe "#<=>" do
5
+ it "delegates to `name`" do
6
+ trigger_a = Fx::Trigger.new(
7
+ "name" => "name_a",
8
+ "definition" => "some definition"
9
+ )
10
+ trigger_b = Fx::Trigger.new(
11
+ "name" => "name_b",
12
+ "definition" => "some definition"
13
+ )
14
+ trigger_c = Fx::Trigger.new(
15
+ "name" => "name_c",
16
+ "definition" => "some definition"
17
+ )
18
+
19
+ expect(trigger_b).to be_between(trigger_a, trigger_c)
20
+ end
21
+ end
22
+
23
+ describe "#==" do
24
+ it "compares `name` and `definition`" do
25
+ trigger_a = Fx::Trigger.new(
26
+ "name" => "name_a",
27
+ "definition" => "some definition"
28
+ )
29
+ trigger_b = Fx::Trigger.new(
30
+ "name" => "name_b",
31
+ "definition" => "some other definition"
32
+ )
33
+
34
+ expect(trigger_a).not_to eq(trigger_b)
35
+ end
36
+ end
37
+
38
+ describe "#to_schema" do
39
+ it "returns a schema compatible version of the trigger" do
40
+ trigger = Fx::Trigger.new(
41
+ "name" => "uppercase_users_name",
42
+ "definition" => "CREATE TRIGGER uppercase_users_name ..."
43
+ )
44
+
45
+ expect(trigger.to_schema).to eq(<<-EOS)
46
+ create_trigger :uppercase_users_name, sql_definition: <<-\SQL
47
+ CREATE TRIGGER uppercase_users_name ...
48
+ SQL
49
+ EOS
50
+ end
51
+ end
52
+ end
data/spec/fx_spec.rb ADDED
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Fx do
4
+ it "has a version number" do
5
+ expect(Fx::VERSION).to be_present
6
+ end
7
+
8
+ it "loads fx into ActiveRecord" do
9
+ expect(Fx.load).to eq(true)
10
+ expect(ActiveRecord::Migration::CommandRecorder).to include(Fx::CommandRecorder)
11
+ expect(ActiveRecord::ConnectionAdapters::AbstractAdapter).to include(Fx::Statements)
12
+ expect(ActiveRecord::SchemaDumper).to include(Fx::SchemaDumper)
13
+ end
14
+
15
+ it "allows configuration" do
16
+ adapter = double("Fx Adapter")
17
+
18
+ Fx.configure do |config|
19
+ config.database = adapter
20
+ config.dump_functions_at_beginning_of_schema = true
21
+ end
22
+
23
+ expect(Fx.configuration.database).to eq(adapter)
24
+ expect(Fx.configuration.dump_functions_at_beginning_of_schema).to eq(true)
25
+
26
+ Fx.configuration = nil
27
+ end
28
+ end
@@ -1,34 +1,46 @@
1
1
  require "spec_helper"
2
2
  require "generators/fx/function/function_generator"
3
3
 
4
- describe Fx::Generators::FunctionGenerator, :generator do
4
+ RSpec.describe Fx::Generators::FunctionGenerator, :generator do
5
5
  it "creates a function definition file, and a migration" do
6
6
  migration = file("db/migrate/create_function_test.rb")
7
7
  function_definition = file("db/functions/test_v01.sql")
8
8
 
9
- run_generator ["test"]
9
+ run_generator(described_class, ["test"])
10
10
 
11
11
  expect(function_definition).to exist
12
- expect(migration).to be_a_migration
13
- expect(migration_file(migration)).to contain "CreateFunctionTest"
12
+ expect_to_be_a_migration(migration)
13
+ expect(migration_content(migration)).to include("CreateFunctionTest")
14
+ end
15
+
16
+ context "when passed --no-migration" do
17
+ it "creates a only function definition file" do
18
+ migration = file("db/migrate/create_function_test.rb")
19
+ function_definition = file("db/functions/test_v01.sql")
20
+
21
+ run_generator(described_class, ["test"], {migration: false})
22
+
23
+ expect(function_definition).to exist
24
+ expect(migration).not_to exist
25
+ end
14
26
  end
15
27
 
16
28
  it "updates an existing function" do
17
29
  with_function_definition(
18
30
  name: "test",
19
31
  version: 1,
20
- sql_definition: "hello",
32
+ sql_definition: "hello"
21
33
  ) do
22
- allow(Dir).to receive(:entries).and_return(["test_v01.sql"])
23
34
  migration = file("db/migrate/update_function_test_to_version_2.rb")
24
35
  function_definition = file("db/functions/test_v02.sql")
25
36
 
26
- run_generator ["test"]
37
+ run_generator(described_class, ["test"])
27
38
 
28
39
  expect(function_definition).to exist
29
- expect(migration).to be_a_migration
30
- expect(migration_file(migration)).
31
- to contain("UpdateFunctionTestToVersion2")
40
+ expect_to_be_a_migration(migration)
41
+ expect(migration_content(migration)).to include(
42
+ "UpdateFunctionTestToVersion2"
43
+ )
32
44
  end
33
45
  end
34
46
  end
@@ -0,0 +1,108 @@
1
+ require "spec_helper"
2
+ require "generators/fx/migration_helper"
3
+
4
+ RSpec.describe Fx::Generators::MigrationHelper do
5
+ describe "#skip_creation?" do
6
+ it "returns false by default" do
7
+ helper = described_class.new({})
8
+
9
+ expect(helper.skip_creation?).to be(false)
10
+ end
11
+
12
+ it "returns true when migration option is false" do
13
+ helper = described_class.new(migration: false)
14
+
15
+ expect(helper.skip_creation?).to be(true)
16
+ end
17
+ end
18
+
19
+ describe "#update_migration_class_name" do
20
+ it "generates correct class name for functions" do
21
+ helper = described_class.new({})
22
+
23
+ result = helper.update_migration_class_name(
24
+ object_type: :function,
25
+ class_name: "TestFunction",
26
+ version: 3
27
+ )
28
+
29
+ expect(result).to eq("UpdateFunctionTestFunctionToVersion3")
30
+ end
31
+
32
+ it "generates correct class name for triggers" do
33
+ helper = described_class.new({})
34
+
35
+ result = helper.update_migration_class_name(
36
+ object_type: :trigger,
37
+ class_name: "TestTrigger",
38
+ version: 2
39
+ )
40
+
41
+ expect(result).to eq("UpdateTriggerTestTriggerToVersion2")
42
+ end
43
+ end
44
+
45
+ describe "#migration_template_info" do
46
+ it "returns create template info for new objects" do
47
+ helper = described_class.new({})
48
+
49
+ result = helper.migration_template_info(
50
+ object_type: :function,
51
+ file_name: "test_func",
52
+ updating_existing: false,
53
+ version: 1
54
+ )
55
+
56
+ expect(result).to eq({
57
+ template: "db/migrate/create_function.erb",
58
+ filename: "db/migrate/create_function_test_func.rb"
59
+ })
60
+ end
61
+
62
+ it "returns update template info for existing objects" do
63
+ helper = described_class.new({})
64
+
65
+ result = helper.migration_template_info(
66
+ object_type: :trigger,
67
+ file_name: "test_trigger",
68
+ updating_existing: true,
69
+ version: 3
70
+ )
71
+
72
+ expect(result).to eq({
73
+ template: "db/migrate/update_trigger.erb",
74
+ filename: "db/migrate/update_trigger_test_trigger_to_version_3.rb"
75
+ })
76
+ end
77
+
78
+ it "handles different object types correctly" do
79
+ helper = described_class.new({})
80
+
81
+ function_result = helper.migration_template_info(
82
+ object_type: :function,
83
+ file_name: "my_function",
84
+ updating_existing: true,
85
+ version: 2
86
+ )
87
+ trigger_result = helper.migration_template_info(
88
+ object_type: :trigger,
89
+ file_name: "my_trigger",
90
+ updating_existing: true,
91
+ version: 2
92
+ )
93
+
94
+ expect(function_result.fetch(:template)).to eq(
95
+ "db/migrate/update_function.erb"
96
+ )
97
+ expect(trigger_result.fetch(:template)).to eq(
98
+ "db/migrate/update_trigger.erb"
99
+ )
100
+ expect(function_result.fetch(:filename)).to eq(
101
+ "db/migrate/update_function_my_function_to_version_2.rb"
102
+ )
103
+ expect(trigger_result.fetch(:filename)).to eq(
104
+ "db/migrate/update_trigger_my_trigger_to_version_2.rb"
105
+ )
106
+ end
107
+ end
108
+ end