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.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/Appraisals +9 -0
- data/Gemfile.lock +133 -4
- data/Guardfile +39 -0
- data/README.md +56 -6
- data/Rakefile +1 -3
- data/bin/exe/lazy_migrate +14 -1
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/rails_5_1_5.gemfile +8 -0
- data/gemfiles/rails_5_1_5.gemfile.lock +170 -0
- data/gemfiles/rails_5_2_4_3.gemfile +8 -0
- data/gemfiles/rails_5_2_4_3.gemfile.lock +178 -0
- data/github/demo.gif +0 -0
- data/lazy_migrate.gemspec +9 -3
- data/lib/lazy_migrate.rb +6 -2
- data/lib/lazy_migrate/client.rb +123 -0
- data/lib/lazy_migrate/migration.rb +14 -0
- data/lib/lazy_migrate/migrator_adapter.rb +144 -0
- data/lib/lazy_migrate/migrator_adapter_factory.rb +24 -0
- data/lib/lazy_migrate/new_migrator_adapter.rb +85 -0
- data/lib/lazy_migrate/old_migrator_adapter.rb +97 -0
- data/lib/lazy_migrate/version.rb +2 -1
- data/lib/tasks/lazy_migrate.rake +10 -0
- data/sorbet/config +2 -0
- data/sorbet/rbi/gems/actioncable.rbi +393 -0
- data/sorbet/rbi/gems/actionmailer.rbi +425 -0
- data/sorbet/rbi/gems/actionpack.rbi +3230 -0
- data/sorbet/rbi/gems/actionview.rbi +1153 -0
- data/sorbet/rbi/gems/activejob.rbi +282 -0
- data/sorbet/rbi/gems/activemodel.rbi +742 -0
- data/sorbet/rbi/gems/activerecord.rbi +4004 -0
- data/sorbet/rbi/gems/activestorage.rbi +174 -0
- data/sorbet/rbi/gems/activesupport.rbi +2300 -0
- data/sorbet/rbi/gems/appraisal.rbi +151 -0
- data/sorbet/rbi/gems/arel.rbi +1253 -0
- data/sorbet/rbi/gems/byebug.rbi +1041 -0
- data/sorbet/rbi/gems/coderay.rbi +92 -0
- data/sorbet/rbi/gems/concurrent-ruby.rbi +1586 -0
- data/sorbet/rbi/gems/crass.rbi +93 -0
- data/sorbet/rbi/gems/erubi.rbi +27 -0
- data/sorbet/rbi/gems/globalid.rbi +99 -0
- data/sorbet/rbi/gems/i18n.rbi +192 -0
- data/sorbet/rbi/gems/loofah.rbi +131 -0
- data/sorbet/rbi/gems/mail.rbi +1092 -0
- data/sorbet/rbi/gems/marcel.rbi +13 -0
- data/sorbet/rbi/gems/method_source.rbi +64 -0
- data/sorbet/rbi/gems/mini_mime.rbi +52 -0
- data/sorbet/rbi/gems/minitest.rbi +282 -0
- data/sorbet/rbi/gems/nio4r.rbi +68 -0
- data/sorbet/rbi/gems/nokogiri.rbi +1011 -0
- data/sorbet/rbi/gems/pastel.rbi +119 -0
- data/sorbet/rbi/gems/pry-byebug.rbi +155 -0
- data/sorbet/rbi/gems/pry.rbi +1949 -0
- data/sorbet/rbi/gems/rack-test.rbi +162 -0
- data/sorbet/rbi/gems/rack.rbi +525 -0
- data/sorbet/rbi/gems/rails-dom-testing.rbi +68 -0
- data/sorbet/rbi/gems/rails-html-sanitizer.rbi +92 -0
- data/sorbet/rbi/gems/railties.rbi +724 -0
- data/sorbet/rbi/gems/rake.rbi +666 -0
- data/sorbet/rbi/gems/rspec-core.rbi +1939 -0
- data/sorbet/rbi/gems/rspec-expectations.rbi +1123 -0
- data/sorbet/rbi/gems/rspec-mocks.rbi +1090 -0
- data/sorbet/rbi/gems/rspec-support.rbi +280 -0
- data/sorbet/rbi/gems/rspec.rbi +15 -0
- data/sorbet/rbi/gems/sprockets-rails.rbi +106 -0
- data/sorbet/rbi/gems/sprockets.rbi +755 -0
- data/sorbet/rbi/gems/sqlite3.rbi +354 -0
- data/sorbet/rbi/gems/thor.rbi +580 -0
- data/sorbet/rbi/gems/thread_safe.rbi +82 -0
- data/sorbet/rbi/gems/tty-color.rbi +44 -0
- data/sorbet/rbi/gems/tty-cursor.rbi +72 -0
- data/sorbet/rbi/gems/tty-prompt.rbi +531 -0
- data/sorbet/rbi/gems/tty-reader.rbi +176 -0
- data/sorbet/rbi/gems/tty-screen.rbi +66 -0
- data/sorbet/rbi/gems/tzinfo.rbi +406 -0
- data/sorbet/rbi/gems/websocket-driver.rbi +103 -0
- data/sorbet/rbi/gems/websocket-extensions.rbi +29 -0
- data/sorbet/rbi/gems/wisper.rbi +130 -0
- data/sorbet/rbi/hidden-definitions/errors.txt +7584 -0
- data/sorbet/rbi/hidden-definitions/hidden.rbi +13328 -0
- data/sorbet/rbi/sorbet-typed/lib/actionmailer/all/actionmailer.rbi +13 -0
- data/sorbet/rbi/sorbet-typed/lib/actionpack/all/actionpack.rbi +954 -0
- data/sorbet/rbi/sorbet-typed/lib/actionview/all/actionview.rbi +321 -0
- data/sorbet/rbi/sorbet-typed/lib/activemodel/all/activemodel.rbi +597 -0
- data/sorbet/rbi/sorbet-typed/lib/activerecord/<6/activerecord.rbi +13 -0
- data/sorbet/rbi/sorbet-typed/lib/activerecord/>=5.2/activerecord.rbi +16 -0
- data/sorbet/rbi/sorbet-typed/lib/activerecord/>=5/activerecord.rbi +53 -0
- data/sorbet/rbi/sorbet-typed/lib/activerecord/all/activerecord.rbi +1454 -0
- data/sorbet/rbi/sorbet-typed/lib/activerecord/all/model_schema.rbi +79 -0
- data/sorbet/rbi/sorbet-typed/lib/activerecord/all/sanitization.rbi +36 -0
- data/sorbet/rbi/sorbet-typed/lib/activerecord/~>5.2.0/activerecord.rbi +447 -0
- data/sorbet/rbi/sorbet-typed/lib/activestorage/<=6.1/activestorage.rbi +82 -0
- data/sorbet/rbi/sorbet-typed/lib/activestorage/all/activestorage.rbi +177 -0
- data/sorbet/rbi/sorbet-typed/lib/activesupport/all/activesupport.rbi +1431 -0
- data/sorbet/rbi/sorbet-typed/lib/minitest/all/minitest.rbi +108 -0
- data/sorbet/rbi/sorbet-typed/lib/railties/all/railties.rbi +25 -0
- data/sorbet/rbi/todo.rbi +18 -0
- data/sorbet/rbi/user-defined/activerecord.rbi +56 -0
- metadata +181 -7
- data/lib/lazy_migrate/migrator.rb +0 -186
@@ -1,186 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'tty-prompt'
|
4
|
-
require 'active_record'
|
5
|
-
require 'rails'
|
6
|
-
|
7
|
-
module LazyMigrate
|
8
|
-
class Migrator
|
9
|
-
class << self
|
10
|
-
MIGRATE = 'migrate'
|
11
|
-
ROLLBACK = 'rollback'
|
12
|
-
UP = 'up'
|
13
|
-
DOWN = 'down'
|
14
|
-
REDO = 'redo'
|
15
|
-
BRING_TO_TOP = 'bring to top'
|
16
|
-
|
17
|
-
def run
|
18
|
-
loop do
|
19
|
-
catch(:done) do
|
20
|
-
on_done = -> { throw :done }
|
21
|
-
|
22
|
-
load_migration_paths
|
23
|
-
migrations = find_migrations
|
24
|
-
|
25
|
-
prompt = TTY::Prompt.new(active_color: :bright_green)
|
26
|
-
prompt.ok("\nDatabase: #{ActiveRecord::Base.connection_config[:database]}\n")
|
27
|
-
|
28
|
-
select_migration_prompt(prompt: prompt, migrations: migrations, on_done: on_done)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
rescue TTY::Reader::InputInterrupt
|
32
|
-
puts
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def select_migration_prompt(prompt:, migrations:, on_done:)
|
38
|
-
prompt.select('Pick a migration') do |menu|
|
39
|
-
migrations.each { |migration|
|
40
|
-
name = render_migration_option(migration)
|
41
|
-
|
42
|
-
menu.choice(
|
43
|
-
name,
|
44
|
-
-> {
|
45
|
-
select_action_prompt(
|
46
|
-
on_done: on_done,
|
47
|
-
prompt: prompt,
|
48
|
-
context: context,
|
49
|
-
migration: migration,
|
50
|
-
)
|
51
|
-
}
|
52
|
-
)
|
53
|
-
}
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def select_action_prompt(on_done:, context:, prompt:, migration:)
|
58
|
-
if !migration[:has_file]
|
59
|
-
prompt.error("\nMigration file not found for migration #{migration[:version]}")
|
60
|
-
prompt_any_key(prompt)
|
61
|
-
on_done.()
|
62
|
-
end
|
63
|
-
|
64
|
-
option_map = obtain_option_map(context: context)
|
65
|
-
|
66
|
-
prompt.select("\nWhat would you like to do for #{migration[:version]} #{name}?") do |inner_menu|
|
67
|
-
options_for_migration(status: migration[:status]).each do |option|
|
68
|
-
inner_menu.choice(option, -> {
|
69
|
-
with_unsafe_error_capture do
|
70
|
-
option_map[option].(migration)
|
71
|
-
end
|
72
|
-
prompt_any_key(prompt)
|
73
|
-
on_done.()
|
74
|
-
})
|
75
|
-
end
|
76
|
-
|
77
|
-
inner_menu.choice('cancel', on_done)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def options_for_migration(status:)
|
82
|
-
common_options = [MIGRATE, ROLLBACK, BRING_TO_TOP]
|
83
|
-
specific_options = if status == 'up'
|
84
|
-
[DOWN, REDO]
|
85
|
-
else
|
86
|
-
[UP]
|
87
|
-
end
|
88
|
-
specific_options + common_options
|
89
|
-
end
|
90
|
-
|
91
|
-
def obtain_option_map(context:)
|
92
|
-
{
|
93
|
-
UP => ->(migration) { context.run(:up, migration[:version]) },
|
94
|
-
DOWN => ->(migration) { context.run(:down, migration[:version]) },
|
95
|
-
REDO => ->(migration) {
|
96
|
-
context.run(:down, migration[:version])
|
97
|
-
context.run(:up, migration[:version])
|
98
|
-
},
|
99
|
-
MIGRATE => ->(migration) { context.up(migration[:version]) },
|
100
|
-
ROLLBACK => ->(migration) {
|
101
|
-
# for some reason in https://github.com/rails/rails/blob/5-2-stable/activerecord/lib/active_record/migration.rb#L1221
|
102
|
-
# we stop before the selected version. I have no idea why.
|
103
|
-
# I could override the logic here but it wouldn't
|
104
|
-
# work when trying to rollback the final migration.
|
105
|
-
context.down(migration[:version])
|
106
|
-
},
|
107
|
-
BRING_TO_TOP => ->(migration) { bring_to_top(migration) },
|
108
|
-
}
|
109
|
-
end
|
110
|
-
|
111
|
-
def load_migration_paths
|
112
|
-
ActiveRecord::Migrator.migrations_paths.each do |path|
|
113
|
-
Dir[Rails.application.root.join("#{path}/**/*.rb")].each { |file| load file }
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def find_migrations
|
118
|
-
context.migrations_status
|
119
|
-
.reverse
|
120
|
-
.map { |status, version, name|
|
121
|
-
# This depends on how rails reports a file is missing.
|
122
|
-
# This is no doubt subject to change so be wary.
|
123
|
-
has_file = name != '********** NO FILE **********'
|
124
|
-
|
125
|
-
{ status: status, version: version.to_i, name: name, has_file: has_file }
|
126
|
-
}
|
127
|
-
end
|
128
|
-
|
129
|
-
def render_migration_option(migration)
|
130
|
-
"#{migration[:status].ljust(6)}#{migration[:version].to_s.ljust(16)}#{migration[:name].ljust(50)}"
|
131
|
-
end
|
132
|
-
|
133
|
-
# bring_to_top updates the version of a migration to bring it to the top of the
|
134
|
-
# migration list. If the migration had already been up'd it will mark the
|
135
|
-
# new migration file as upped as well. The former version number will be
|
136
|
-
# removed from the schema_migrations table.
|
137
|
-
def bring_to_top(migration)
|
138
|
-
filename = context.migrations.find { |m| m.version == migration[:version] }&.filename
|
139
|
-
|
140
|
-
if filename.nil?
|
141
|
-
raise("No file found for migration #{migration[:version]}")
|
142
|
-
end
|
143
|
-
|
144
|
-
last = last_version
|
145
|
-
new_version = ActiveRecord::Migration.next_migration_number(last ? last + 1 : 0)
|
146
|
-
|
147
|
-
# replace the version
|
148
|
-
basename = File.basename(filename)
|
149
|
-
dir = File.dirname(filename)
|
150
|
-
new_basename = "#{new_version}_#{basename.split('_')[1..].join('_')}"
|
151
|
-
new_filename = File.join(dir, new_basename)
|
152
|
-
|
153
|
-
File.rename(filename, new_filename)
|
154
|
-
|
155
|
-
if migration[:status] == 'up'
|
156
|
-
ActiveRecord::SchemaMigration.create(version: new_version)
|
157
|
-
end
|
158
|
-
|
159
|
-
ActiveRecord::SchemaMigration.find_by(version: migration[:version])&.destroy!
|
160
|
-
end
|
161
|
-
|
162
|
-
def last_version
|
163
|
-
context.migrations.last&.version
|
164
|
-
end
|
165
|
-
|
166
|
-
def prompt_any_key(prompt)
|
167
|
-
prompt.keypress("\nPress any key to continue")
|
168
|
-
end
|
169
|
-
|
170
|
-
def with_unsafe_error_capture
|
171
|
-
yield
|
172
|
-
rescue Exception => e # rubocop:disable Lint/RescueException
|
173
|
-
# I am aware you should not rescue 'Exception' exceptions but I think this is is an 'exceptional' use case
|
174
|
-
puts "\n#{e.class}: #{e.message}\n#{e.backtrace.take(5).join("\n")}"
|
175
|
-
end
|
176
|
-
|
177
|
-
def context
|
178
|
-
ActiveRecord::MigrationContext.new(Rails.root.join('db', 'migrate'))
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
def self.run
|
184
|
-
Migrator.show
|
185
|
-
end
|
186
|
-
end
|