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,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
@@ -1,47 +1,82 @@
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")
8
8
 
9
- run_generator ["test", "table_name" => "some_table"]
9
+ run_generator(
10
+ described_class,
11
+ ["test", {"table_name" => "some_table"}]
12
+ )
10
13
 
11
14
  expect(trigger_definition).to exist
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"
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")
18
+ end
19
+
20
+ context "when passed --no-migration" do
21
+ it "creates a only trigger definition file" do
22
+ migration = file("db/migrate/create_trigger_test.rb")
23
+ trigger_definition = file("db/triggers/test_v01.sql")
24
+
25
+ run_generator(
26
+ described_class,
27
+ ["test", {"table_name" => "some_table"}],
28
+ {migration: false}
29
+ )
30
+
31
+ expect(trigger_definition).to exist
32
+ expect(migration).not_to exist
33
+ end
15
34
  end
16
35
 
17
36
  it "supports naming the table as `on` aswell as `table_name`" do
18
37
  migration = file("db/migrate/create_trigger_test.rb")
19
38
  trigger_definition = file("db/triggers/test_v01.sql")
20
39
 
21
- run_generator ["test", "on" => "some_table"]
40
+ run_generator(
41
+ described_class,
42
+ ["test", {"on" => "some_table"}]
43
+ )
22
44
 
23
45
  expect(trigger_definition).to exist
24
- expect(migration).to be_a_migration
25
- expect(migration_file(migration)).to contain "CreateTriggerTest"
26
- expect(migration_file(migration)).to contain "on: :some_table"
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")
27
49
  end
28
50
 
29
51
  it "requires `table_name` or `on` to be specified" do
30
- expect {
31
- run_generator ["test", "foo" => "some_table"]
32
- }.to raise_error ArgumentError
52
+ expect do
53
+ run_generator(
54
+ described_class,
55
+ ["test", {"foo" => "some_table"}]
56
+ )
57
+ end.to raise_error(ArgumentError)
33
58
  end
34
59
 
35
60
  it "updates an existing trigger" do
36
- allow(Dir).to receive(:entries).and_return(["test_v01.sql"])
37
- migration = file("db/migrate/update_trigger_test_to_version_2.rb")
38
- trigger_definition = file("db/triggers/test_v02.sql")
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")
39
68
 
40
- run_generator ["test", "table_name" => "some_table"]
69
+ run_generator(
70
+ described_class,
71
+ ["test", {"table_name" => "some_table"}]
72
+ )
41
73
 
42
- expect(trigger_definition).to exist
43
- expect(migration).to be_a_migration
44
- expect(migration_file(migration)).to contain "UpdateTriggerTestToVersion2"
45
- expect(migration_file(migration)).to contain "on: :some_table"
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
46
81
  end
47
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,17 +1,29 @@
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 }
6
5
 
6
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
7
+ require "fx"
8
+
7
9
  RSpec.configure do |config|
8
10
  config.order = "random"
9
- DatabaseCleaner.strategy = :transaction
11
+ config.disable_monkey_patching!
12
+
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
10
20
 
11
21
  config.around(:each, db: true) do |example|
12
- DatabaseCleaner.start
22
+ DatabaseReset.call
23
+
13
24
  example.run
14
- DatabaseCleaner.clean
25
+
26
+ DatabaseReset.call
15
27
  end
16
28
 
17
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,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
@@ -1,11 +1,52 @@
1
- require "ammeter/init"
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
- fake_rails_root = File.expand_path("../../../tmp", __FILE__)
6
- allow(Rails).to receive(:root).and_return(Pathname.new(fake_rails_root))
47
+ FileUtils.rm_rf(GeneratorSetup::RAILS_ROOT) if File.exist?(GeneratorSetup::RAILS_ROOT)
48
+ FileUtils.mkdir_p(GeneratorSetup::RAILS_ROOT)
7
49
 
8
- destination fake_rails_root
9
- prepare_destination
50
+ allow(Rails).to receive(:root).and_return(Pathname.new(GeneratorSetup::RAILS_ROOT))
10
51
  end
11
52
  end
@@ -1,12 +1,20 @@
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
7
7
  end
8
8
  end
9
9
 
10
+ def migration_class
11
+ if Rails::VERSION::MAJOR >= 5
12
+ ::ActiveRecord::Migration[5.0]
13
+ else
14
+ ::ActiveRecord::Migration
15
+ end
16
+ end
17
+
10
18
  def connection
11
19
  @_connection ||= ActiveRecord::Base.connection
12
20
  end
@@ -0,0 +1,5 @@
1
+ require "warning"
2
+
3
+ Warning.process do |_|
4
+ :raise
5
+ end