lazy_migrate 0.1.0 → 0.2.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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/Appraisals +9 -0
  4. data/Gemfile.lock +133 -4
  5. data/Guardfile +39 -0
  6. data/README.md +56 -6
  7. data/Rakefile +1 -3
  8. data/bin/exe/lazy_migrate +14 -1
  9. data/gemfiles/.bundle/config +2 -0
  10. data/gemfiles/rails_5_1_5.gemfile +8 -0
  11. data/gemfiles/rails_5_1_5.gemfile.lock +170 -0
  12. data/gemfiles/rails_5_2_4_3.gemfile +8 -0
  13. data/gemfiles/rails_5_2_4_3.gemfile.lock +178 -0
  14. data/github/demo.gif +0 -0
  15. data/lazy_migrate.gemspec +9 -3
  16. data/lib/lazy_migrate.rb +6 -2
  17. data/lib/lazy_migrate/client.rb +123 -0
  18. data/lib/lazy_migrate/migration.rb +14 -0
  19. data/lib/lazy_migrate/migrator_adapter.rb +144 -0
  20. data/lib/lazy_migrate/migrator_adapter_factory.rb +24 -0
  21. data/lib/lazy_migrate/new_migrator_adapter.rb +85 -0
  22. data/lib/lazy_migrate/old_migrator_adapter.rb +97 -0
  23. data/lib/lazy_migrate/version.rb +2 -1
  24. data/lib/tasks/lazy_migrate.rake +10 -0
  25. data/sorbet/config +2 -0
  26. data/sorbet/rbi/gems/actioncable.rbi +393 -0
  27. data/sorbet/rbi/gems/actionmailer.rbi +425 -0
  28. data/sorbet/rbi/gems/actionpack.rbi +3230 -0
  29. data/sorbet/rbi/gems/actionview.rbi +1153 -0
  30. data/sorbet/rbi/gems/activejob.rbi +282 -0
  31. data/sorbet/rbi/gems/activemodel.rbi +742 -0
  32. data/sorbet/rbi/gems/activerecord.rbi +4004 -0
  33. data/sorbet/rbi/gems/activestorage.rbi +174 -0
  34. data/sorbet/rbi/gems/activesupport.rbi +2300 -0
  35. data/sorbet/rbi/gems/appraisal.rbi +151 -0
  36. data/sorbet/rbi/gems/arel.rbi +1253 -0
  37. data/sorbet/rbi/gems/byebug.rbi +1041 -0
  38. data/sorbet/rbi/gems/coderay.rbi +92 -0
  39. data/sorbet/rbi/gems/concurrent-ruby.rbi +1586 -0
  40. data/sorbet/rbi/gems/crass.rbi +93 -0
  41. data/sorbet/rbi/gems/erubi.rbi +27 -0
  42. data/sorbet/rbi/gems/globalid.rbi +99 -0
  43. data/sorbet/rbi/gems/i18n.rbi +192 -0
  44. data/sorbet/rbi/gems/loofah.rbi +131 -0
  45. data/sorbet/rbi/gems/mail.rbi +1092 -0
  46. data/sorbet/rbi/gems/marcel.rbi +13 -0
  47. data/sorbet/rbi/gems/method_source.rbi +64 -0
  48. data/sorbet/rbi/gems/mini_mime.rbi +52 -0
  49. data/sorbet/rbi/gems/minitest.rbi +282 -0
  50. data/sorbet/rbi/gems/nio4r.rbi +68 -0
  51. data/sorbet/rbi/gems/nokogiri.rbi +1011 -0
  52. data/sorbet/rbi/gems/pastel.rbi +119 -0
  53. data/sorbet/rbi/gems/pry-byebug.rbi +155 -0
  54. data/sorbet/rbi/gems/pry.rbi +1949 -0
  55. data/sorbet/rbi/gems/rack-test.rbi +162 -0
  56. data/sorbet/rbi/gems/rack.rbi +525 -0
  57. data/sorbet/rbi/gems/rails-dom-testing.rbi +68 -0
  58. data/sorbet/rbi/gems/rails-html-sanitizer.rbi +92 -0
  59. data/sorbet/rbi/gems/railties.rbi +724 -0
  60. data/sorbet/rbi/gems/rake.rbi +666 -0
  61. data/sorbet/rbi/gems/rspec-core.rbi +1939 -0
  62. data/sorbet/rbi/gems/rspec-expectations.rbi +1123 -0
  63. data/sorbet/rbi/gems/rspec-mocks.rbi +1090 -0
  64. data/sorbet/rbi/gems/rspec-support.rbi +280 -0
  65. data/sorbet/rbi/gems/rspec.rbi +15 -0
  66. data/sorbet/rbi/gems/sprockets-rails.rbi +106 -0
  67. data/sorbet/rbi/gems/sprockets.rbi +755 -0
  68. data/sorbet/rbi/gems/sqlite3.rbi +354 -0
  69. data/sorbet/rbi/gems/thor.rbi +580 -0
  70. data/sorbet/rbi/gems/thread_safe.rbi +82 -0
  71. data/sorbet/rbi/gems/tty-color.rbi +44 -0
  72. data/sorbet/rbi/gems/tty-cursor.rbi +72 -0
  73. data/sorbet/rbi/gems/tty-prompt.rbi +531 -0
  74. data/sorbet/rbi/gems/tty-reader.rbi +176 -0
  75. data/sorbet/rbi/gems/tty-screen.rbi +66 -0
  76. data/sorbet/rbi/gems/tzinfo.rbi +406 -0
  77. data/sorbet/rbi/gems/websocket-driver.rbi +103 -0
  78. data/sorbet/rbi/gems/websocket-extensions.rbi +29 -0
  79. data/sorbet/rbi/gems/wisper.rbi +130 -0
  80. data/sorbet/rbi/hidden-definitions/errors.txt +7584 -0
  81. data/sorbet/rbi/hidden-definitions/hidden.rbi +13328 -0
  82. data/sorbet/rbi/sorbet-typed/lib/actionmailer/all/actionmailer.rbi +13 -0
  83. data/sorbet/rbi/sorbet-typed/lib/actionpack/all/actionpack.rbi +954 -0
  84. data/sorbet/rbi/sorbet-typed/lib/actionview/all/actionview.rbi +321 -0
  85. data/sorbet/rbi/sorbet-typed/lib/activemodel/all/activemodel.rbi +597 -0
  86. data/sorbet/rbi/sorbet-typed/lib/activerecord/<6/activerecord.rbi +13 -0
  87. data/sorbet/rbi/sorbet-typed/lib/activerecord/>=5.2/activerecord.rbi +16 -0
  88. data/sorbet/rbi/sorbet-typed/lib/activerecord/>=5/activerecord.rbi +53 -0
  89. data/sorbet/rbi/sorbet-typed/lib/activerecord/all/activerecord.rbi +1454 -0
  90. data/sorbet/rbi/sorbet-typed/lib/activerecord/all/model_schema.rbi +79 -0
  91. data/sorbet/rbi/sorbet-typed/lib/activerecord/all/sanitization.rbi +36 -0
  92. data/sorbet/rbi/sorbet-typed/lib/activerecord/~>5.2.0/activerecord.rbi +447 -0
  93. data/sorbet/rbi/sorbet-typed/lib/activestorage/<=6.1/activestorage.rbi +82 -0
  94. data/sorbet/rbi/sorbet-typed/lib/activestorage/all/activestorage.rbi +177 -0
  95. data/sorbet/rbi/sorbet-typed/lib/activesupport/all/activesupport.rbi +1431 -0
  96. data/sorbet/rbi/sorbet-typed/lib/minitest/all/minitest.rbi +108 -0
  97. data/sorbet/rbi/sorbet-typed/lib/railties/all/railties.rbi +25 -0
  98. data/sorbet/rbi/todo.rbi +18 -0
  99. data/sorbet/rbi/user-defined/activerecord.rbi +56 -0
  100. metadata +181 -7
  101. data/lib/lazy_migrate/migrator.rb +0 -186
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "5.2.4.3"
6
+ gem "sqlite3", "~> 1.4.2"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,178 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ lazy_migrate (0.1.5)
5
+ sorbet-runtime
6
+ tty-prompt (~> 0.22.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actioncable (5.2.4.3)
12
+ actionpack (= 5.2.4.3)
13
+ nio4r (~> 2.0)
14
+ websocket-driver (>= 0.6.1)
15
+ actionmailer (5.2.4.3)
16
+ actionpack (= 5.2.4.3)
17
+ actionview (= 5.2.4.3)
18
+ activejob (= 5.2.4.3)
19
+ mail (~> 2.5, >= 2.5.4)
20
+ rails-dom-testing (~> 2.0)
21
+ actionpack (5.2.4.3)
22
+ actionview (= 5.2.4.3)
23
+ activesupport (= 5.2.4.3)
24
+ rack (~> 2.0, >= 2.0.8)
25
+ rack-test (>= 0.6.3)
26
+ rails-dom-testing (~> 2.0)
27
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
28
+ actionview (5.2.4.3)
29
+ activesupport (= 5.2.4.3)
30
+ builder (~> 3.1)
31
+ erubi (~> 1.4)
32
+ rails-dom-testing (~> 2.0)
33
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
34
+ activejob (5.2.4.3)
35
+ activesupport (= 5.2.4.3)
36
+ globalid (>= 0.3.6)
37
+ activemodel (5.2.4.3)
38
+ activesupport (= 5.2.4.3)
39
+ activerecord (5.2.4.3)
40
+ activemodel (= 5.2.4.3)
41
+ activesupport (= 5.2.4.3)
42
+ arel (>= 9.0)
43
+ activestorage (5.2.4.3)
44
+ actionpack (= 5.2.4.3)
45
+ activerecord (= 5.2.4.3)
46
+ marcel (~> 0.3.1)
47
+ activesupport (5.2.4.3)
48
+ concurrent-ruby (~> 1.0, >= 1.0.2)
49
+ i18n (>= 0.7, < 2)
50
+ minitest (~> 5.1)
51
+ tzinfo (~> 1.1)
52
+ appraisal (2.3.0)
53
+ bundler
54
+ rake
55
+ thor (>= 0.14.0)
56
+ arel (9.0.0)
57
+ builder (3.2.4)
58
+ byebug (11.1.3)
59
+ coderay (1.1.3)
60
+ concurrent-ruby (1.1.6)
61
+ crass (1.0.6)
62
+ diff-lcs (1.4.4)
63
+ erubi (1.9.0)
64
+ globalid (0.4.2)
65
+ activesupport (>= 4.2.0)
66
+ i18n (1.8.5)
67
+ concurrent-ruby (~> 1.0)
68
+ loofah (2.6.0)
69
+ crass (~> 1.0.2)
70
+ nokogiri (>= 1.5.9)
71
+ mail (2.7.1)
72
+ mini_mime (>= 0.1.1)
73
+ marcel (0.3.3)
74
+ mimemagic (~> 0.3.2)
75
+ method_source (1.0.0)
76
+ mimemagic (0.3.5)
77
+ mini_mime (1.0.2)
78
+ mini_portile2 (2.4.0)
79
+ minitest (5.14.1)
80
+ nio4r (2.5.2)
81
+ nokogiri (1.10.10)
82
+ mini_portile2 (~> 2.4.0)
83
+ pastel (0.8.0)
84
+ tty-color (~> 0.5)
85
+ pry (0.13.1)
86
+ coderay (~> 1.1)
87
+ method_source (~> 1.0)
88
+ pry-byebug (3.9.0)
89
+ byebug (~> 11.0)
90
+ pry (~> 0.13.0)
91
+ rack (2.2.3)
92
+ rack-test (1.1.0)
93
+ rack (>= 1.0, < 3)
94
+ rails (5.2.4.3)
95
+ actioncable (= 5.2.4.3)
96
+ actionmailer (= 5.2.4.3)
97
+ actionpack (= 5.2.4.3)
98
+ actionview (= 5.2.4.3)
99
+ activejob (= 5.2.4.3)
100
+ activemodel (= 5.2.4.3)
101
+ activerecord (= 5.2.4.3)
102
+ activestorage (= 5.2.4.3)
103
+ activesupport (= 5.2.4.3)
104
+ bundler (>= 1.3.0)
105
+ railties (= 5.2.4.3)
106
+ sprockets-rails (>= 2.0.0)
107
+ rails-dom-testing (2.0.3)
108
+ activesupport (>= 4.2.0)
109
+ nokogiri (>= 1.6)
110
+ rails-html-sanitizer (1.3.0)
111
+ loofah (~> 2.3)
112
+ railties (5.2.4.3)
113
+ actionpack (= 5.2.4.3)
114
+ activesupport (= 5.2.4.3)
115
+ method_source
116
+ rake (>= 0.8.7)
117
+ thor (>= 0.19.0, < 2.0)
118
+ rake (13.0.1)
119
+ rspec (3.9.0)
120
+ rspec-core (~> 3.9.0)
121
+ rspec-expectations (~> 3.9.0)
122
+ rspec-mocks (~> 3.9.0)
123
+ rspec-core (3.9.2)
124
+ rspec-support (~> 3.9.3)
125
+ rspec-expectations (3.9.2)
126
+ diff-lcs (>= 1.2.0, < 2.0)
127
+ rspec-support (~> 3.9.0)
128
+ rspec-mocks (3.9.1)
129
+ diff-lcs (>= 1.2.0, < 2.0)
130
+ rspec-support (~> 3.9.0)
131
+ rspec-support (3.9.3)
132
+ sorbet (0.5.5862)
133
+ sorbet-static (= 0.5.5862)
134
+ sorbet-runtime (0.5.5862)
135
+ sorbet-static (0.5.5862-universal-darwin-18)
136
+ sprockets (4.0.2)
137
+ concurrent-ruby (~> 1.0)
138
+ rack (> 1, < 3)
139
+ sprockets-rails (3.2.1)
140
+ actionpack (>= 4.0)
141
+ activesupport (>= 4.0)
142
+ sprockets (>= 3.0.0)
143
+ sqlite3 (1.4.2)
144
+ thor (1.0.1)
145
+ thread_safe (0.3.6)
146
+ tty-color (0.5.1)
147
+ tty-cursor (0.7.1)
148
+ tty-prompt (0.22.0)
149
+ pastel (~> 0.8)
150
+ tty-reader (~> 0.8)
151
+ tty-reader (0.8.0)
152
+ tty-cursor (~> 0.7)
153
+ tty-screen (~> 0.8)
154
+ wisper (~> 2.0)
155
+ tty-screen (0.8.1)
156
+ tzinfo (1.2.7)
157
+ thread_safe (~> 0.1)
158
+ websocket-driver (0.7.3)
159
+ websocket-extensions (>= 0.1.0)
160
+ websocket-extensions (0.1.5)
161
+ wisper (2.0.1)
162
+
163
+ PLATFORMS
164
+ ruby
165
+
166
+ DEPENDENCIES
167
+ appraisal
168
+ bundler (~> 2.0)
169
+ lazy_migrate!
170
+ pry-byebug (~> 3.9.0)
171
+ rails (= 5.2.4.3)
172
+ rake (~> 13.0)
173
+ rspec (~> 3.0)
174
+ sorbet
175
+ sqlite3 (~> 1.4.2)
176
+
177
+ BUNDLED WITH
178
+ 2.0.2
Binary file
@@ -24,13 +24,19 @@ Gem::Specification.new do |spec|
24
24
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
25
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
26
  end
27
- spec.bindir = "exe"
28
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.bindir = "bin/exe"
28
+ spec.executables = ['lazy_migrate']
29
29
  spec.require_paths = ["lib"]
30
30
 
31
+ spec.add_development_dependency "appraisal"
31
32
  spec.add_development_dependency "bundler", "~> 2.0"
32
- spec.add_development_dependency "rake", "~> 10.0"
33
+ spec.add_development_dependency 'pry-byebug', '~> 3.9.0'
34
+ spec.add_development_dependency "rails", "~> 5.2.4"
35
+ spec.add_development_dependency "rake", "~> 13.0"
33
36
  spec.add_development_dependency "rspec", "~> 3.0"
37
+ spec.add_development_dependency 'sqlite3', '~> 1.4.2'
38
+ spec.add_development_dependency 'sorbet'
34
39
 
40
+ spec.add_runtime_dependency 'sorbet-runtime'
35
41
  spec.add_runtime_dependency 'tty-prompt', '~> 0.22.0'
36
42
  end
@@ -1,10 +1,14 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "lazy_migrate/version"
4
- require "lazy_migrate/migrator"
5
+ require "lazy_migrate/client"
5
6
 
6
7
  module LazyMigrate
8
+ extend T::Sig
9
+
10
+ sig { void }
7
11
  def self.run
8
- Migrator.run
12
+ Client.run
9
13
  end
10
14
  end
@@ -0,0 +1,123 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ require 'tty-prompt'
5
+ require 'active_record'
6
+ require 'rails'
7
+ require 'lazy_migrate/migrator_adapter_factory'
8
+
9
+ module LazyMigrate
10
+ class Client
11
+ class << self
12
+ MIGRATE = 'migrate'
13
+ ROLLBACK = 'rollback'
14
+ UP = 'up'
15
+ DOWN = 'down'
16
+ REDO = 'redo'
17
+ BRING_TO_TOP = 'bring to top'
18
+
19
+ def run
20
+ migrator_adapter = MigratorAdapterFactory.create_migrator_adapter
21
+
22
+ loop do
23
+ catch(:done) do
24
+ on_done = -> { throw :done }
25
+
26
+ prompt.ok("\nDatabase: #{ActiveRecord::Base.connection_config[:database]}\n")
27
+
28
+ select_migration_prompt(on_done: on_done, migrator_adapter: migrator_adapter)
29
+ end
30
+ end
31
+ rescue TTY::Reader::InputInterrupt
32
+ puts
33
+ end
34
+
35
+ private
36
+
37
+ def prompt
38
+ TTY::Prompt.new(active_color: :bright_green)
39
+ end
40
+
41
+ def select_migration_prompt(on_done:, migrator_adapter:)
42
+ prompt.select('Pick a migration') do |menu|
43
+ migrator_adapter.find_migrations.each { |migration|
44
+ name = render_migration_option(migration)
45
+
46
+ menu.choice(
47
+ name,
48
+ -> {
49
+ select_action_prompt(
50
+ on_done: on_done,
51
+ migrator_adapter: migrator_adapter,
52
+ migration: migration,
53
+ )
54
+ }
55
+ )
56
+ }
57
+ end
58
+ end
59
+
60
+ def select_action_prompt(on_done:, migrator_adapter:, migration:)
61
+ if !migration.has_file
62
+ prompt.select("\nFile not found for migration version.") do |menu|
63
+ menu.choice('remove version from version table', -> { migrator_adapter.remove_version_from_table(migration.version) })
64
+ menu.choice('cancel', -> {})
65
+ end
66
+ on_done.()
67
+ end
68
+
69
+ option_map = obtain_option_map(migrator_adapter: migrator_adapter, on_done: on_done)
70
+
71
+ prompt.select("\nWhat would you like to do for #{migration.version} #{name}?") do |menu|
72
+ option_map.each do |label, on_press|
73
+ menu.choice(label, -> {
74
+ with_unsafe_error_capture { on_press.(migration) }
75
+ migrator_adapter.dump_schema
76
+ on_done.()
77
+ })
78
+ end
79
+
80
+ menu.choice('cancel', on_done)
81
+ end
82
+ end
83
+
84
+ def obtain_option_map(migrator_adapter:, on_done:)
85
+ {
86
+ MIGRATE => ->(migration) { migrator_adapter.migrate(migration.version) },
87
+ ROLLBACK => ->(migration) { migrator_adapter.rollback(migration.version) },
88
+ UP => ->(migration) { migrator_adapter.up(migration.version) },
89
+ DOWN => ->(migration) { migrator_adapter.down(migration.version) },
90
+ REDO => ->(migration) { migrator_adapter.redo(migration.version) },
91
+ BRING_TO_TOP => ->(migration) { migrator_adapter.bring_to_top(migration: migration, ask_for_rerun: -> { ask_for_rerun(on_done) }) },
92
+ }
93
+ end
94
+
95
+ def ask_for_rerun(on_done)
96
+ prompt.select("\nMigration has been run. Would you like to `down` the migration before moving it, and then run it again after?") do |menu|
97
+ menu.choice('yes, down and re-run the migration', -> { true })
98
+ menu.choice('no, just bump the version without migrating anything', -> { false })
99
+ menu.choice('cancel', -> { on_done.() })
100
+ end
101
+ end
102
+
103
+ def render_migration_option(migration)
104
+ "#{
105
+ migration.status.ljust(6)
106
+ }#{
107
+ migration.version.to_s.ljust(16)
108
+ }#{
109
+ (migration.current ? 'current' : '').ljust(9)
110
+ }#{
111
+ migration.name
112
+ }"
113
+ end
114
+
115
+ def with_unsafe_error_capture
116
+ yield
117
+ rescue Exception => e # rubocop:disable Lint/RescueException
118
+ # I am aware you should not rescue 'Exception' exceptions but I think this is is an 'exceptional' use case
119
+ prompt.error("\n#{e.class}: #{e.message}\n#{e.backtrace.take(5).join("\n")}")
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,14 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'sorbet-runtime'
5
+
6
+ module LazyMigrate
7
+ class Migration < T::Struct
8
+ prop :status, String
9
+ const :version, Integer
10
+ const :name, String
11
+ prop :has_file, T::Boolean
12
+ prop :current, T::Boolean
13
+ end
14
+ end
@@ -0,0 +1,144 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'lazy_migrate/migration'
5
+
6
+ module LazyMigrate
7
+ class MigratorAdapter
8
+ extend T::Sig
9
+ extend T::Helpers
10
+
11
+ abstract!
12
+
13
+ sig { void }
14
+ def initialize; end
15
+
16
+ # bring_to_top updates the version of a migration to bring it to the top of the
17
+ # migration list. If the migration had already been up'd it will mark the
18
+ # new migration file as upped as well. The former version number will be
19
+ # removed from the schema_migrations table. The user chooses whether
20
+ # they want to down the migration before moving it.
21
+ sig { params(migration: LazyMigrate::Migration, ask_for_rerun: T.proc.returns(T::Boolean)).void }
22
+ def bring_to_top(migration:, ask_for_rerun:)
23
+ initial_version = migration.version
24
+ initial_status = migration.status
25
+ initial_filename = self.find_filename_for_migration(migration)
26
+
27
+ if initial_filename.nil?
28
+ raise("No file found for migration #{initial_version}")
29
+ end
30
+
31
+ re_run = initial_status == 'up' && ask_for_rerun.()
32
+
33
+ if re_run
34
+ self.down(initial_version)
35
+ end
36
+
37
+ last = self.last_version
38
+ new_version = ActiveRecord::Migration.new.next_migration_number(last ? last + 1 : 0).to_i
39
+ new_filename = replace_version_in_filename(initial_filename, new_version)
40
+ File.rename(initial_filename, new_filename)
41
+
42
+ if re_run
43
+ self.up(new_version)
44
+ elsif initial_status == 'up'
45
+ ActiveRecord::SchemaMigration.create(version: new_version)
46
+ ActiveRecord::SchemaMigration.find_by(version: initial_version)&.destroy!
47
+ end
48
+ end
49
+
50
+ sig { params(filename: String, new_version: Integer).returns(String) }
51
+ def replace_version_in_filename(filename, new_version)
52
+ basename = File.basename(filename)
53
+ dir = File.dirname(filename)
54
+ name_after_version = T.must(basename.split('_')[1..]).join('_')
55
+ new_basename = "#{new_version}_#{name_after_version}"
56
+ File.join(dir, new_basename)
57
+ end
58
+
59
+ sig { void }
60
+ def dump_schema
61
+ return if !ActiveRecord::Base.dump_schema_after_migration
62
+
63
+ # ripped from https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/railties/databases.rake
64
+ filename = ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema.rb")
65
+ File.open(filename, "w:utf-8") do |file|
66
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
67
+ end
68
+ end
69
+
70
+ sig { returns(T::Array[LazyMigrate::Migration]) }
71
+ def find_migrations
72
+ self.load_migration_paths
73
+ current_version = self.last_version
74
+
75
+ self.find_migration_tuples
76
+ .reverse
77
+ .map { |status, str_version, name|
78
+ # This depends on how rails reports a file is missing.
79
+ # This is no doubt subject to change so be wary.
80
+ has_file = name != '********** NO FILE **********'
81
+ version = str_version.to_i
82
+ current = version == current_version
83
+
84
+ LazyMigrate::Migration.new(
85
+ status: status,
86
+ version: version,
87
+ name: name,
88
+ has_file: has_file,
89
+ current: current,
90
+ )
91
+ }
92
+ end
93
+
94
+ sig { void }
95
+ def load_migration_paths
96
+ # silencing cos we might be re-initializing some constants and rails
97
+ # doesn't like that
98
+ Kernel.silence_warnings do
99
+ ActiveRecord::Migrator.migrations_paths.each do |path|
100
+ Dir[Rails.application.root.join("#{path}/**/*.rb")].each { |file| load file }
101
+ end
102
+ end
103
+ end
104
+
105
+ sig { params(arr: T::Array[Integer], value: Integer).returns(T.nilable(Integer)) }
106
+ def previous_value(arr, value)
107
+ arr.sort.select { |v| v < value }.last
108
+ end
109
+
110
+ sig { params(version: Integer).void }
111
+ def remove_version_from_table(version)
112
+ ActiveRecord::SchemaMigration.find_by!(version: version).destroy!
113
+ end
114
+
115
+ sig { abstract.params(version: Integer).void }
116
+ def up(version); end
117
+
118
+ sig { abstract.params(version: Integer).void }
119
+ def down(version); end
120
+
121
+ sig { abstract.params(version: Integer).void }
122
+ def redo(version); end
123
+
124
+ sig { abstract.params(version: Integer).void }
125
+ def migrate(version); end
126
+
127
+ sig { abstract.params(version: Integer).void }
128
+ def rollback(version); end
129
+
130
+ protected
131
+
132
+ sig { abstract.returns(T::Array[[String, String, String]]) }
133
+ def find_migration_tuples; end
134
+
135
+ sig { abstract.params(version: Integer).returns(T.nilable(Integer)) }
136
+ def find_previous_version(version); end
137
+
138
+ sig { abstract.params(migration: LazyMigrate::Migration).returns(T.nilable(String)) }
139
+ def find_filename_for_migration(migration); end
140
+
141
+ sig { abstract.returns(T.nilable(Integer)) }
142
+ def last_version; end
143
+ end
144
+ end