fx 0.7.0 → 0.9.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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +53 -0
  3. data/.gitignore +0 -1
  4. data/.rspec +1 -1
  5. data/.standard.yml +3 -0
  6. data/CHANGELOG.md +124 -0
  7. data/CONTRIBUTING.md +13 -4
  8. data/Gemfile +13 -2
  9. data/README.md +4 -2
  10. data/Rakefile +2 -1
  11. data/bin/setup +0 -4
  12. data/bin/standardrb +27 -0
  13. data/fx.gemspec +20 -27
  14. data/lib/fx/adapters/postgres/connection.rb +12 -0
  15. data/lib/fx/adapters/postgres/functions.rb +3 -3
  16. data/lib/fx/adapters/postgres/triggers.rb +3 -3
  17. data/lib/fx/adapters/postgres.rb +6 -14
  18. data/lib/fx/command_recorder.rb +87 -6
  19. data/lib/fx/configuration.rb +0 -25
  20. data/lib/fx/definition.rb +16 -6
  21. data/lib/fx/function.rb +7 -7
  22. data/lib/fx/schema_dumper.rb +45 -5
  23. data/lib/fx/statements.rb +228 -6
  24. data/lib/fx/trigger.rb +3 -3
  25. data/lib/fx/version.rb +1 -1
  26. data/lib/fx.rb +30 -12
  27. data/lib/generators/fx/function/function_generator.rb +8 -8
  28. data/lib/generators/fx/trigger/trigger_generator.rb +6 -10
  29. data/spec/acceptance/user_manages_functions_spec.rb +5 -5
  30. data/spec/acceptance/user_manages_triggers_spec.rb +8 -8
  31. data/spec/acceptance_helper.rb +6 -4
  32. data/spec/dummy/Rakefile +4 -4
  33. data/spec/dummy/bin/bundle +2 -2
  34. data/spec/dummy/bin/rails +3 -3
  35. data/spec/dummy/bin/rake +2 -2
  36. data/spec/dummy/config/application.rb +6 -0
  37. data/spec/dummy/config/database.yml +2 -0
  38. data/spec/dummy/config.ru +1 -1
  39. data/spec/features/functions/migrations_spec.rb +4 -4
  40. data/spec/features/functions/revert_spec.rb +7 -7
  41. data/spec/features/triggers/migrations_spec.rb +6 -6
  42. data/spec/features/triggers/revert_spec.rb +13 -13
  43. data/spec/fx/adapters/postgres/functions_spec.rb +26 -30
  44. data/spec/fx/adapters/postgres/triggers_spec.rb +34 -38
  45. data/spec/fx/adapters/postgres_spec.rb +107 -109
  46. data/spec/fx/command_recorder_spec.rb +41 -39
  47. data/spec/fx/configuration_spec.rb +20 -9
  48. data/spec/fx/definition_spec.rb +30 -38
  49. data/spec/fx/function_spec.rb +45 -48
  50. data/spec/fx/schema_dumper_spec.rb +123 -0
  51. data/spec/fx/statements_spec.rb +217 -0
  52. data/spec/fx/trigger_spec.rb +37 -40
  53. data/spec/fx_spec.rb +28 -0
  54. data/spec/generators/fx/function/function_generator_spec.rb +6 -6
  55. data/spec/generators/fx/trigger/trigger_generator_spec.rb +10 -10
  56. data/spec/spec_helper.rb +5 -0
  57. data/spec/support/definition_helpers.rb +5 -9
  58. data/spec/support/generator_setup.rb +1 -1
  59. data/spec/support/migration_helpers.rb +1 -1
  60. data/spec/support/warning_helper.rb +5 -0
  61. metadata +24 -213
  62. data/.hound.yml +0 -2
  63. data/.rubocop.yml +0 -648
  64. data/.travis.yml +0 -60
  65. data/Appraisals +0 -45
  66. data/bin/appraisal +0 -17
  67. data/gemfiles/rails42.gemfile +0 -10
  68. data/gemfiles/rails50.gemfile +0 -8
  69. data/gemfiles/rails51.gemfile +0 -8
  70. data/gemfiles/rails52.gemfile +0 -8
  71. data/gemfiles/rails60.gemfile +0 -8
  72. data/gemfiles/rails61.gemfile +0 -8
  73. data/gemfiles/rails_edge.gemfile +0 -8
  74. data/lib/fx/command_recorder/arguments.rb +0 -43
  75. data/lib/fx/command_recorder/function.rb +0 -30
  76. data/lib/fx/command_recorder/trigger.rb +0 -30
  77. data/lib/fx/schema_dumper/function.rb +0 -38
  78. data/lib/fx/schema_dumper/trigger.rb +0 -29
  79. data/lib/fx/statements/function.rb +0 -115
  80. data/lib/fx/statements/trigger.rb +0 -146
  81. data/spec/fx/command_recorder/arguments_spec.rb +0 -41
  82. data/spec/fx/schema_dumper/function_spec.rb +0 -80
  83. data/spec/fx/schema_dumper/trigger_spec.rb +0 -40
  84. data/spec/fx/statements/function_spec.rb +0 -103
  85. data/spec/fx/statements/trigger_spec.rb +0 -132
@@ -0,0 +1,217 @@
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
+ version: nil,
180
+ sql_definition: nil
181
+ )
182
+ end.to raise_error(
183
+ ArgumentError,
184
+ /version or sql_definition must be specified/
185
+ )
186
+ end
187
+
188
+ it "raises an error if both arguments are set" do
189
+ stubbed_database
190
+
191
+ expect do
192
+ connection.update_trigger(
193
+ :whatever,
194
+ version: 1,
195
+ sql_definition: "a definition"
196
+ )
197
+ end.to raise_error(
198
+ ArgumentError,
199
+ /cannot both be set/
200
+ )
201
+ end
202
+ end
203
+
204
+ def stubbed_definition
205
+ instance_double("Fx::Definition", to_sql: nil).tap do |stubbed_definition|
206
+ allow(Fx::Definition).to receive(:function).and_return(stubbed_definition)
207
+ allow(Fx::Definition).to receive(:trigger).and_return(stubbed_definition)
208
+ end
209
+ end
210
+
211
+ def stubbed_database
212
+ database = instance_spy("StubbedDatabase")
213
+ allow(Fx).to receive(:database).and_return(database)
214
+
215
+ database
216
+ end
217
+ end
@@ -1,55 +1,52 @@
1
1
  require "spec_helper"
2
- require "fx/trigger"
3
2
 
4
- module Fx
5
- describe Trigger do
6
- describe "#<=>" do
7
- it "delegates to `name`" do
8
- trigger_a = Trigger.new(
9
- "name" => "name_a",
10
- "definition" => "some definition",
11
- )
12
- trigger_b = Trigger.new(
13
- "name" => "name_b",
14
- "definition" => "some definition",
15
- )
16
- trigger_c = Trigger.new(
17
- "name" => "name_c",
18
- "definition" => "some definition",
19
- )
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
+ )
20
18
 
21
- expect(trigger_b).to be_between(trigger_a, trigger_c)
22
- end
19
+ expect(trigger_b).to be_between(trigger_a, trigger_c)
23
20
  end
21
+ end
24
22
 
25
- describe "#==" do
26
- it "compares `name` and `definition`" do
27
- trigger_a = Trigger.new(
28
- "name" => "name_a",
29
- "definition" => "some definition",
30
- )
31
- trigger_b = Trigger.new(
32
- "name" => "name_b",
33
- "definition" => "some other definition",
34
- )
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
+ )
35
33
 
36
- expect(trigger_a).not_to eq(trigger_b)
37
- end
34
+ expect(trigger_a).not_to eq(trigger_b)
38
35
  end
36
+ end
39
37
 
40
- describe "#to_schema" do
41
- it "returns a schema compatible version of the trigger" do
42
- trigger = Trigger.new(
43
- "name" => "uppercase_users_name",
44
- "definition" => "CREATE TRIGGER uppercase_users_name ...",
45
- )
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
+ )
46
44
 
47
- expect(trigger.to_schema).to eq <<-EOS
45
+ expect(trigger.to_schema).to eq(<<-EOS)
48
46
  create_trigger :uppercase_users_name, sql_definition: <<-\SQL
49
47
  CREATE TRIGGER uppercase_users_name ...
50
48
  SQL
51
- EOS
52
- end
49
+ EOS
53
50
  end
54
51
  end
55
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(ActiveRecord::Migration::CommandRecorder).to include(Fx::CommandRecorder)
10
+ expect(ActiveRecord::ConnectionAdapters::AbstractAdapter).to include(Fx::Statements)
11
+ expect(ActiveRecord::SchemaDumper).to include(Fx::SchemaDumper)
12
+ expect(Fx.load).to eq(true)
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,7 +1,7 @@
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")
@@ -10,7 +10,7 @@ describe Fx::Generators::FunctionGenerator, :generator do
10
10
 
11
11
  expect(function_definition).to exist
12
12
  expect(migration).to be_a_migration
13
- expect(migration_file(migration)).to contain "CreateFunctionTest"
13
+ expect(migration_file(migration)).to contain("CreateFunctionTest")
14
14
  end
15
15
 
16
16
  context "when passed --no-migration" do
@@ -21,7 +21,7 @@ describe Fx::Generators::FunctionGenerator, :generator do
21
21
  run_generator ["test", "--no-migration"]
22
22
 
23
23
  expect(function_definition).to exist
24
- expect(migration_file(migration)).not_to exist
24
+ expect(Pathname.new(migration_file(migration))).not_to exist
25
25
  end
26
26
  end
27
27
 
@@ -29,7 +29,7 @@ describe Fx::Generators::FunctionGenerator, :generator do
29
29
  with_function_definition(
30
30
  name: "test",
31
31
  version: 1,
32
- sql_definition: "hello",
32
+ sql_definition: "hello"
33
33
  ) do
34
34
  allow(Dir).to receive(:entries).and_return(["test_v01.sql"])
35
35
  migration = file("db/migrate/update_function_test_to_version_2.rb")
@@ -39,8 +39,8 @@ describe Fx::Generators::FunctionGenerator, :generator do
39
39
 
40
40
  expect(function_definition).to exist
41
41
  expect(migration).to be_a_migration
42
- expect(migration_file(migration)).
43
- to contain("UpdateFunctionTestToVersion2")
42
+ expect(migration_file(migration))
43
+ .to contain("UpdateFunctionTestToVersion2")
44
44
  end
45
45
  end
46
46
  end
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
  require "generators/fx/trigger/trigger_generator"
3
3
 
4
- describe Fx::Generators::TriggerGenerator, :generator do
4
+ RSpec.describe Fx::Generators::TriggerGenerator, :generator do
5
5
  it "creates a trigger definition file, and a migration" do
6
6
  migration = file("db/migrate/create_trigger_test.rb")
7
7
  trigger_definition = file("db/triggers/test_v01.sql")
@@ -10,8 +10,8 @@ describe Fx::Generators::TriggerGenerator, :generator do
10
10
 
11
11
  expect(trigger_definition).to exist
12
12
  expect(migration).to be_a_migration
13
- expect(migration_file(migration)).to contain "CreateTriggerTest"
14
- expect(migration_file(migration)).to contain "on: :some_table"
13
+ expect(migration_file(migration)).to contain("CreateTriggerTest")
14
+ expect(migration_file(migration)).to contain("on: :some_table")
15
15
  end
16
16
 
17
17
  context "when passed --no-migration" do
@@ -22,7 +22,7 @@ describe Fx::Generators::TriggerGenerator, :generator do
22
22
  run_generator ["test", {"table_name" => "some_table"}, "--no-migration"]
23
23
 
24
24
  expect(trigger_definition).to exist
25
- expect(migration_file(migration)).not_to exist
25
+ expect(Pathname.new(migration_file(migration))).not_to exist
26
26
  end
27
27
  end
28
28
 
@@ -34,14 +34,14 @@ describe Fx::Generators::TriggerGenerator, :generator do
34
34
 
35
35
  expect(trigger_definition).to exist
36
36
  expect(migration).to be_a_migration
37
- expect(migration_file(migration)).to contain "CreateTriggerTest"
38
- expect(migration_file(migration)).to contain "on: :some_table"
37
+ expect(migration_file(migration)).to contain("CreateTriggerTest")
38
+ expect(migration_file(migration)).to contain("on: :some_table")
39
39
  end
40
40
 
41
41
  it "requires `table_name` or `on` to be specified" do
42
- expect {
42
+ expect do
43
43
  run_generator ["test", "foo" => "some_table"]
44
- }.to raise_error ArgumentError
44
+ end.to raise_error(ArgumentError)
45
45
  end
46
46
 
47
47
  it "updates an existing trigger" do
@@ -53,7 +53,7 @@ describe Fx::Generators::TriggerGenerator, :generator do
53
53
 
54
54
  expect(trigger_definition).to exist
55
55
  expect(migration).to be_a_migration
56
- expect(migration_file(migration)).to contain "UpdateTriggerTestToVersion2"
57
- expect(migration_file(migration)).to contain "on: :some_table"
56
+ expect(migration_file(migration)).to contain("UpdateTriggerTestToVersion2")
57
+ expect(migration_file(migration)).to contain("on: :some_table")
58
58
  end
59
59
  end
data/spec/spec_helper.rb CHANGED
@@ -4,8 +4,13 @@ require "database_cleaner"
4
4
  require File.expand_path("../dummy/config/environment", __FILE__)
5
5
  Dir["spec/support/**/*.rb"].sort.each { |file| load file }
6
6
 
7
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
8
+ require "fx"
9
+
7
10
  RSpec.configure do |config|
8
11
  config.order = "random"
12
+ config.disable_monkey_patching!
13
+
9
14
  DatabaseCleaner.strategy = :transaction
10
15
 
11
16
  config.around(:each, db: true) do |example|
@@ -1,31 +1,27 @@
1
1
  module DefinitionHelpers
2
2
  def with_function_definition(name:, sql_definition:, version: 1, &block)
3
- definition = Fx::Definition.new(name: name, version: version)
3
+ definition = Fx::Definition.function(name: name, version: version)
4
4
 
5
5
  with_definition(
6
6
  definition: definition,
7
7
  sql_definition: sql_definition,
8
- block: block,
8
+ block: block
9
9
  )
10
10
  end
11
11
 
12
12
  def with_trigger_definition(name:, sql_definition:, version: 1, &block)
13
- definition = Fx::Definition.new(
14
- name: name,
15
- version: version,
16
- type: "trigger",
17
- )
13
+ definition = Fx::Definition.trigger(name: name, version: version)
18
14
 
19
15
  with_definition(
20
16
  definition: definition,
21
17
  sql_definition: sql_definition,
22
- block: block,
18
+ block: block
23
19
  )
24
20
  end
25
21
 
26
22
  def with_definition(definition:, sql_definition:, block:)
27
23
  FileUtils.mkdir_p(File.dirname(definition.full_path))
28
- File.open(definition.full_path, "w") { |f| f.write(sql_definition) }
24
+ File.write(definition.full_path, sql_definition)
29
25
  block.call
30
26
  ensure
31
27
  File.delete definition.full_path
@@ -2,7 +2,7 @@ require "ammeter/init"
2
2
 
3
3
  RSpec.configure do |config|
4
4
  config.before(:each, :generator) do
5
- fake_rails_root = File.expand_path("../../../tmp", __FILE__)
5
+ fake_rails_root = File.expand_path("../../../tmp/dummy", __FILE__)
6
6
  allow(Rails).to receive(:root).and_return(Pathname.new(fake_rails_root))
7
7
 
8
8
  destination fake_rails_root
@@ -1,6 +1,6 @@
1
1
  module MigrationsHelper
2
2
  def run_migration(migration, directions)
3
- silence_stream(STDOUT) do
3
+ silence_stream($stdout) do
4
4
  Array.wrap(directions).each do |direction|
5
5
  migration.migrate(direction)
6
6
  end
@@ -0,0 +1,5 @@
1
+ require "warning"
2
+
3
+ Warning.process do |_|
4
+ :raise
5
+ end