data_migrate 10.0.0.rc1 → 11.0.0.rc

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +4 -4
  3. data/.github/workflows/gempush.yml +6 -8
  4. data/.gitignore +3 -2
  5. data/Appraisals +10 -5
  6. data/Changelog.md +51 -2
  7. data/Gemfile +0 -1
  8. data/Gemfile.lock +188 -0
  9. data/README.md +17 -6
  10. data/data_migrate.gemspec +2 -2
  11. data/gemfiles/rails_6.1.gemfile +0 -1
  12. data/gemfiles/rails_6.1.gemfile.lock +233 -0
  13. data/gemfiles/rails_7.0.gemfile +1 -2
  14. data/gemfiles/rails_7.0.gemfile.lock +234 -0
  15. data/gemfiles/{rails_6.0.gemfile → rails_7.1.gemfile} +1 -2
  16. data/gemfiles/rails_7.1.gemfile.lock +266 -0
  17. data/gemfiles/rails_7.2.gemfile +7 -0
  18. data/gemfiles/rails_7.2.gemfile.lock +265 -0
  19. data/lib/data_migrate/data_migrator.rb +15 -23
  20. data/lib/data_migrate/data_schema.rb +2 -2
  21. data/lib/data_migrate/data_schema_migration.rb +24 -7
  22. data/lib/data_migrate/database_configurations_wrapper.rb +11 -0
  23. data/lib/data_migrate/database_tasks.rb +194 -48
  24. data/lib/data_migrate/migration_context.rb +11 -8
  25. data/lib/data_migrate/rails_helper.rb +90 -0
  26. data/lib/data_migrate/schema_dumper.rb +1 -1
  27. data/lib/data_migrate/schema_migration.rb +5 -4
  28. data/lib/data_migrate/status_service.rb +4 -4
  29. data/lib/data_migrate/tasks/data_migrate_tasks.rb +14 -15
  30. data/lib/data_migrate/test.rb +14 -0
  31. data/lib/data_migrate/version.rb +1 -1
  32. data/lib/data_migrate.rb +2 -1
  33. data/spec/data_migrate/data_migrator_spec.rb +17 -14
  34. data/spec/data_migrate/data_schema_migration_spec.rb +25 -8
  35. data/spec/data_migrate/data_spec.rb +1 -1
  36. data/spec/data_migrate/database_tasks_spec.rb +34 -19
  37. data/spec/data_migrate/migration_context_spec.rb +25 -9
  38. data/spec/data_migrate/schema_dumper_spec.rb +6 -3
  39. data/spec/data_migrate/schema_migration_spec.rb +13 -6
  40. data/spec/data_migrate/status_service_spec.rb +7 -4
  41. data/spec/data_migrate/tasks/data_migrate_tasks_spec.rb +13 -14
  42. data/spec/db/data/20091231235959_some_name.rb +1 -1
  43. data/spec/db/data/20171231235959_super_update.rb +1 -1
  44. data/spec/db/migrate/20131111111111_late_migration.rb +1 -1
  45. data/spec/db/migrate/20202020202011_db_migration.rb +1 -1
  46. data/tasks/databases.rake +25 -83
  47. metadata +21 -17
  48. data/.ruby-version +0 -1
  49. data/.travis.yml +0 -14
  50. data/Gemfile.rails6.1 +0 -11
  51. data/lib/data_migrate/legacy_migrator.rb +0 -22
  52. data/spec/data_migrate/legacy_migrator_spec.rb +0 -38
@@ -0,0 +1,265 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ data_migrate (11.0.0.rc)
5
+ activerecord (>= 6.1)
6
+ railties (>= 6.1)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ actioncable (7.2.0)
12
+ actionpack (= 7.2.0)
13
+ activesupport (= 7.2.0)
14
+ nio4r (~> 2.0)
15
+ websocket-driver (>= 0.6.1)
16
+ zeitwerk (~> 2.6)
17
+ actionmailbox (7.2.0)
18
+ actionpack (= 7.2.0)
19
+ activejob (= 7.2.0)
20
+ activerecord (= 7.2.0)
21
+ activestorage (= 7.2.0)
22
+ activesupport (= 7.2.0)
23
+ mail (>= 2.8.0)
24
+ actionmailer (7.2.0)
25
+ actionpack (= 7.2.0)
26
+ actionview (= 7.2.0)
27
+ activejob (= 7.2.0)
28
+ activesupport (= 7.2.0)
29
+ mail (>= 2.8.0)
30
+ rails-dom-testing (~> 2.2)
31
+ actionpack (7.2.0)
32
+ actionview (= 7.2.0)
33
+ activesupport (= 7.2.0)
34
+ nokogiri (>= 1.8.5)
35
+ racc
36
+ rack (>= 2.2.4, < 3.2)
37
+ rack-session (>= 1.0.1)
38
+ rack-test (>= 0.6.3)
39
+ rails-dom-testing (~> 2.2)
40
+ rails-html-sanitizer (~> 1.6)
41
+ useragent (~> 0.16)
42
+ actiontext (7.2.0)
43
+ actionpack (= 7.2.0)
44
+ activerecord (= 7.2.0)
45
+ activestorage (= 7.2.0)
46
+ activesupport (= 7.2.0)
47
+ globalid (>= 0.6.0)
48
+ nokogiri (>= 1.8.5)
49
+ actionview (7.2.0)
50
+ activesupport (= 7.2.0)
51
+ builder (~> 3.1)
52
+ erubi (~> 1.11)
53
+ rails-dom-testing (~> 2.2)
54
+ rails-html-sanitizer (~> 1.6)
55
+ activejob (7.2.0)
56
+ activesupport (= 7.2.0)
57
+ globalid (>= 0.3.6)
58
+ activemodel (7.2.0)
59
+ activesupport (= 7.2.0)
60
+ activerecord (7.2.0)
61
+ activemodel (= 7.2.0)
62
+ activesupport (= 7.2.0)
63
+ timeout (>= 0.4.0)
64
+ activestorage (7.2.0)
65
+ actionpack (= 7.2.0)
66
+ activejob (= 7.2.0)
67
+ activerecord (= 7.2.0)
68
+ activesupport (= 7.2.0)
69
+ marcel (~> 1.0)
70
+ activesupport (7.2.0)
71
+ base64
72
+ bigdecimal
73
+ concurrent-ruby (~> 1.0, >= 1.3.1)
74
+ connection_pool (>= 2.2.5)
75
+ drb
76
+ i18n (>= 1.6, < 2)
77
+ logger (>= 1.4.2)
78
+ minitest (>= 5.1)
79
+ securerandom (>= 0.3)
80
+ tzinfo (~> 2.0, >= 2.0.5)
81
+ appraisal (2.5.0)
82
+ bundler
83
+ rake
84
+ thor (>= 0.14.0)
85
+ ast (2.4.2)
86
+ base64 (0.2.0)
87
+ bigdecimal (3.1.8)
88
+ builder (3.3.0)
89
+ childprocess (5.0.0)
90
+ coderay (1.1.3)
91
+ concurrent-ruby (1.3.4)
92
+ connection_pool (2.4.1)
93
+ crass (1.0.6)
94
+ date (3.3.4)
95
+ diff-lcs (1.5.1)
96
+ drb (2.2.1)
97
+ erubi (1.13.0)
98
+ globalid (1.2.1)
99
+ activesupport (>= 6.1)
100
+ i18n (1.14.5)
101
+ concurrent-ruby (~> 1.0)
102
+ iniparse (1.5.0)
103
+ io-console (0.7.2)
104
+ irb (1.14.0)
105
+ rdoc (>= 4.0.0)
106
+ reline (>= 0.4.2)
107
+ json (2.7.2)
108
+ language_server-protocol (3.17.0.3)
109
+ logger (1.6.0)
110
+ loofah (2.22.0)
111
+ crass (~> 1.0.2)
112
+ nokogiri (>= 1.12.0)
113
+ mail (2.8.1)
114
+ mini_mime (>= 0.1.1)
115
+ net-imap
116
+ net-pop
117
+ net-smtp
118
+ marcel (1.0.4)
119
+ method_source (1.1.0)
120
+ mini_mime (1.1.5)
121
+ minitest (5.25.1)
122
+ net-imap (0.4.14)
123
+ date
124
+ net-protocol
125
+ net-pop (0.1.2)
126
+ net-protocol
127
+ net-protocol (0.2.2)
128
+ timeout
129
+ net-smtp (0.5.0)
130
+ net-protocol
131
+ nio4r (2.7.3)
132
+ nokogiri (1.16.7-aarch64-linux)
133
+ racc (~> 1.4)
134
+ nokogiri (1.16.7-arm64-darwin)
135
+ racc (~> 1.4)
136
+ nokogiri (1.16.7-x86_64-linux)
137
+ racc (~> 1.4)
138
+ overcommit (0.63.0)
139
+ childprocess (>= 0.6.3, < 6)
140
+ iniparse (~> 1.4)
141
+ rexml (~> 3.2)
142
+ parallel (1.24.0)
143
+ parser (3.3.1.0)
144
+ ast (~> 2.4.1)
145
+ racc
146
+ pry (0.14.2)
147
+ coderay (~> 1.1)
148
+ method_source (~> 1.0)
149
+ psych (5.1.2)
150
+ stringio
151
+ racc (1.8.1)
152
+ rack (3.1.7)
153
+ rack-session (2.0.0)
154
+ rack (>= 3.0.0)
155
+ rack-test (2.1.0)
156
+ rack (>= 1.3)
157
+ rackup (2.1.0)
158
+ rack (>= 3)
159
+ webrick (~> 1.8)
160
+ rails (7.2.0)
161
+ actioncable (= 7.2.0)
162
+ actionmailbox (= 7.2.0)
163
+ actionmailer (= 7.2.0)
164
+ actionpack (= 7.2.0)
165
+ actiontext (= 7.2.0)
166
+ actionview (= 7.2.0)
167
+ activejob (= 7.2.0)
168
+ activemodel (= 7.2.0)
169
+ activerecord (= 7.2.0)
170
+ activestorage (= 7.2.0)
171
+ activesupport (= 7.2.0)
172
+ bundler (>= 1.15.0)
173
+ railties (= 7.2.0)
174
+ rails-dom-testing (2.2.0)
175
+ activesupport (>= 5.0.0)
176
+ minitest
177
+ nokogiri (>= 1.6)
178
+ rails-html-sanitizer (1.6.0)
179
+ loofah (~> 2.21)
180
+ nokogiri (~> 1.14)
181
+ railties (7.2.0)
182
+ actionpack (= 7.2.0)
183
+ activesupport (= 7.2.0)
184
+ irb (~> 1.13)
185
+ rackup (>= 1.0.0)
186
+ rake (>= 12.2)
187
+ thor (~> 1.0, >= 1.2.2)
188
+ zeitwerk (~> 2.6)
189
+ rainbow (3.1.1)
190
+ rake (13.2.1)
191
+ rb-readline (0.5.5)
192
+ rdoc (6.7.0)
193
+ psych (>= 4.0.0)
194
+ regexp_parser (2.9.2)
195
+ reline (0.5.9)
196
+ io-console (~> 0.5)
197
+ rexml (3.2.8)
198
+ strscan (>= 3.0.9)
199
+ rspec (3.13.0)
200
+ rspec-core (~> 3.13.0)
201
+ rspec-expectations (~> 3.13.0)
202
+ rspec-mocks (~> 3.13.0)
203
+ rspec-core (3.13.0)
204
+ rspec-support (~> 3.13.0)
205
+ rspec-expectations (3.13.0)
206
+ diff-lcs (>= 1.2.0, < 2.0)
207
+ rspec-support (~> 3.13.0)
208
+ rspec-mocks (3.13.1)
209
+ diff-lcs (>= 1.2.0, < 2.0)
210
+ rspec-support (~> 3.13.0)
211
+ rspec-support (3.13.1)
212
+ rubocop (1.64.0)
213
+ json (~> 2.3)
214
+ language_server-protocol (>= 3.17.0)
215
+ parallel (~> 1.10)
216
+ parser (>= 3.3.0.2)
217
+ rainbow (>= 2.2.2, < 4.0)
218
+ regexp_parser (>= 1.8, < 3.0)
219
+ rexml (>= 3.2.5, < 4.0)
220
+ rubocop-ast (>= 1.31.1, < 2.0)
221
+ ruby-progressbar (~> 1.7)
222
+ unicode-display_width (>= 2.4.0, < 3.0)
223
+ rubocop-ast (1.31.3)
224
+ parser (>= 3.3.1.0)
225
+ ruby-progressbar (1.13.0)
226
+ securerandom (0.3.1)
227
+ sqlite3 (2.0.2-aarch64-linux-gnu)
228
+ sqlite3 (2.0.2-arm64-darwin)
229
+ sqlite3 (2.0.2-x86_64-linux-gnu)
230
+ stringio (3.1.1)
231
+ strscan (3.1.0)
232
+ thor (1.3.1)
233
+ timecop (0.9.8)
234
+ timeout (0.4.1)
235
+ tzinfo (2.0.6)
236
+ concurrent-ruby (~> 1.0)
237
+ unicode-display_width (2.5.0)
238
+ useragent (0.16.10)
239
+ webrick (1.8.1)
240
+ websocket-driver (0.7.6)
241
+ websocket-extensions (>= 0.1.0)
242
+ websocket-extensions (0.1.5)
243
+ zeitwerk (2.6.17)
244
+
245
+ PLATFORMS
246
+ aarch64-linux
247
+ arm64-darwin-23
248
+ x86_64-linux
249
+
250
+ DEPENDENCIES
251
+ appraisal
252
+ data_migrate!
253
+ overcommit
254
+ pry
255
+ rails (~> 7.2.0)
256
+ rake
257
+ rb-readline
258
+ rspec
259
+ rspec-core
260
+ rubocop
261
+ sqlite3
262
+ timecop
263
+
264
+ BUNDLED WITH
265
+ 2.4.17
@@ -5,32 +5,20 @@ require "data_migrate/config"
5
5
 
6
6
  module DataMigrate
7
7
  class DataMigrator < ActiveRecord::Migrator
8
- def self.migrations_paths
9
- [DataMigrate.config.data_migrations_path]
10
- end
11
-
12
- def self.assure_data_schema_table
13
- DataMigrate::DataSchemaMigration.create_table
14
- end
15
-
16
- def initialize(direction, migrations, target_version = nil)
17
- @direction = direction
18
- @target_version = target_version
19
- @migrated_versions = nil
20
- @migrations = migrations
21
-
22
- validate(@migrations)
23
-
24
- DataMigrate::DataSchemaMigration.create_table
25
- ActiveRecord::InternalMetadata.create_table
26
- end
27
-
28
8
  def load_migrated
29
9
  @migrated_versions =
30
- DataMigrate::DataSchemaMigration.normalized_versions.map(&:to_i).sort
10
+ DataMigrate::RailsHelper.data_schema_migration.normalized_versions.map(&:to_i).sort
31
11
  end
32
12
 
33
13
  class << self
14
+ def migrations_paths
15
+ [DataMigrate.config.data_migrations_path]
16
+ end
17
+
18
+ def create_data_schema_table
19
+ DataMigrate::RailsHelper.data_schema_migration.create_table
20
+ end
21
+
34
22
  def current_version
35
23
  DataMigrate::MigrationContext.new(migrations_paths).current_version
36
24
  end
@@ -66,6 +54,10 @@ module DataMigrate
66
54
 
67
55
  #TODO: this was added to be backward compatible, need to re-evaluate
68
56
  def run(direction, migration_paths, version)
57
+ # Ensure all Active Record model cache is reset for each data migration
58
+ # As recommended in: https://github.com/rails/rails/blob/da21c2e9812e5eb0698fba4a9aa38632fc004432/activerecord/lib/active_record/migration.rb#L467-L470
59
+ ActiveRecord::Base.descendants.each(&:reset_column_information)
60
+
69
61
  DataMigrate::MigrationContext.new(migration_paths).run(direction, version)
70
62
  end
71
63
 
@@ -79,10 +71,10 @@ module DataMigrate
79
71
  def record_version_state_after_migrating(version)
80
72
  if down?
81
73
  migrated.delete(version)
82
- DataMigrate::DataSchemaMigration.where(version: version.to_s).delete_all
74
+ DataMigrate::RailsHelper.data_schema_delete_version(version.to_s)
83
75
  else
84
76
  migrated << version
85
- DataMigrate::DataSchemaMigration.create!(version: version.to_s)
77
+ DataMigrate::RailsHelper.data_schema_migration.create_version(version.to_s)
86
78
  end
87
79
  end
88
80
  end
@@ -9,7 +9,7 @@ module DataMigrate
9
9
  # ActiveRecord::ConnectionAdapters::SchemaStatements
10
10
  # #assume_migrated_upto_version
11
11
  def define(info)
12
- DataMigrate::DataMigrator.assure_data_schema_table
12
+ DataMigrate::DataMigrator.create_data_schema_table
13
13
 
14
14
  return if info[:version].blank?
15
15
 
@@ -57,7 +57,7 @@ module DataMigrate
57
57
  end
58
58
 
59
59
  def table_name
60
- DataMigrate::DataSchemaMigration.table_name
60
+ DataMigrate::RailsHelper.data_schema_migration.table_name
61
61
  end
62
62
  end
63
63
  end
@@ -1,12 +1,29 @@
1
1
  module DataMigrate
2
- class DataSchemaMigration
3
- class << self
4
- delegate :table_name, :primary_key, :create_table, :normalized_versions, :create, :create!, :table_exists?, :exists?, :where, to: :instance
2
+ class DataSchemaMigration < ActiveRecord::SchemaMigration
3
+ # In Rails 7.1+, ActiveRecord::SchemaMigration methods are instance methods
4
+ # So we only load the appropriate methods depending on Rails version.
5
+ if DataMigrate::RailsHelper.rails_version_equal_to_or_higher_than_7_1
6
+ def table_name
7
+ ActiveRecord::Base.table_name_prefix + 'data_migrations' + ActiveRecord::Base.table_name_suffix
8
+ end
9
+
10
+ def primary_key
11
+ "version"
12
+ end
13
+ else
14
+ class << self
15
+ def table_name
16
+ ActiveRecord::Base.table_name_prefix + 'data_migrations' + ActiveRecord::Base.table_name_suffix
17
+ end
18
+
19
+ def primary_key
20
+ "version"
21
+ end
5
22
 
6
- def instance
7
- @instance ||= Class.new(::ActiveRecord::SchemaMigration) do
8
- define_singleton_method(:table_name) { ActiveRecord::Base.table_name_prefix + 'data_migrations' + ActiveRecord::Base.table_name_suffix }
9
- define_singleton_method(:primary_key) { "version" }
23
+ def create_version(version)
24
+ # Note that SchemaMigration.create_version in Rails 7.1 does not
25
+ # raise an error if validations fail but we retain this behaviour for now.
26
+ create!(version: version)
10
27
  end
11
28
  end
12
29
  end
@@ -0,0 +1,11 @@
1
+ module DataMigrate
2
+ # This wrapper is used to differentiate between
3
+ # a data and schema db config when running migrations
4
+ class DatabaseConfigurationWrapper
5
+ attr_reader :db_config
6
+
7
+ def initialize(db_config)
8
+ @db_config = db_config
9
+ end
10
+ end
11
+ end
@@ -5,67 +5,143 @@ require "data_migrate/config"
5
5
  module DataMigrate
6
6
  ##
7
7
  # This class extends DatabaseTasks to add a schema_file method.
8
- class DatabaseTasks
8
+ module DatabaseTasks
9
9
  extend ActiveRecord::Tasks::DatabaseTasks
10
-
11
- class << self
12
- def schema_file_type(_format = nil)
13
- "data_schema.rb"
10
+ extend self
11
+
12
+ # These method are only introduced in Rails 7.1
13
+ unless respond_to?(:with_temporary_connection_for_each)
14
+ def with_temporary_connection_for_each(env: ActiveRecord::Tasks::DatabaseTasks.env, name: nil, &block) # :nodoc:
15
+ if name
16
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: env, name: name)
17
+ with_temporary_connection(db_config, &block)
18
+ else
19
+ ActiveRecord::Base.configurations.configs_for(env_name: env, name: name).each do |db_config|
20
+ with_temporary_connection(db_config, &block)
21
+ end
22
+ end
14
23
  end
15
24
 
16
- def dump_filename(spec_name, format = ActiveRecord::Base.schema_format)
17
- filename = if spec_name == "primary"
18
- schema_file_type(format)
19
- else
20
- "#{spec_name}_#{schema_file_type(format)}"
25
+ def with_temporary_connection(db_config) # :nodoc:
26
+ with_temporary_pool(db_config) do |pool|
27
+ yield pool.connection
21
28
  end
29
+ end
22
30
 
23
- ENV["DATA_SCHEMA"] || File.join(db_dir, filename)
31
+ def migration_class # :nodoc:
32
+ ActiveRecord::Base
24
33
  end
25
34
 
26
- def check_schema_file(filename)
27
- unless File.exist?(filename)
28
- message = +%{#{filename} doesn't exist yet. Run `rake data:migrate` to create it, then try again.}
29
- Kernel.abort message
30
- end
35
+ def migration_connection # :nodoc:
36
+ migration_class.connection
31
37
  end
32
38
 
33
- def pending_migrations
34
- sort_migrations(
35
- pending_schema_migrations,
36
- pending_data_migrations
37
- )
39
+ private def with_temporary_pool(db_config)
40
+ original_db_config = migration_class.connection_db_config
41
+ pool = migration_class.connection_handler.establish_connection(db_config)
42
+
43
+ yield pool
44
+ ensure
45
+ migration_class.connection_handler.establish_connection(original_db_config)
38
46
  end
47
+ end
48
+
49
+ def db_configs_with_versions
50
+ db_configs_with_versions = Hash.new { |h, k| h[k] = [] }
51
+
52
+ with_temporary_connection_for_each do |conn|
53
+ db_config = conn.pool.db_config
54
+ if db_config.primary?
55
+ versions_to_run = DataMigrate::DatabaseTasks.pending_data_migrations.map { |m| m[:version] }
56
+ target_version = ActiveRecord::Tasks::DatabaseTasks.target_version
39
57
 
40
- def sort_migrations(*migrations)
41
- migrations.flatten.sort { |a, b| sort_string(a) <=> sort_string(b) }
58
+ versions_to_run.each do |version|
59
+ next if target_version && target_version != version
60
+ db_configs_with_versions[version] << DatabaseConfigurationWrapper.new(db_config)
61
+ end
62
+ end
42
63
  end
43
64
 
44
- def sort_string migration
45
- "#{migration[:version]}_#{migration[:kind] == :data ? 1 : 0}"
65
+ db_configs_with_versions
66
+ end
67
+
68
+ def schema_file(_format = nil)
69
+ File.join(db_dir, "data_schema.rb")
70
+ end
71
+
72
+ def schema_file_type(_format = nil)
73
+ "data_schema.rb"
74
+ end
75
+
76
+ # This method is removed in Rails 7.0
77
+ def dump_filename(spec_name, format = ActiveRecord::Base.schema_format)
78
+ filename = if spec_name == "primary"
79
+ schema_file_type(format)
80
+ else
81
+ "#{spec_name}_#{schema_file_type(format)}"
46
82
  end
47
83
 
48
- def data_migrations_path
49
- ::DataMigrate.config.data_migrations_path
84
+ ENV["DATA_SCHEMA"] || File.join(db_dir, filename)
85
+ end
86
+
87
+ def check_schema_file(filename)
88
+ unless File.exist?(filename)
89
+ message = +%{#{filename} doesn't exist yet. Run `rake data:migrate` to create it, then try again.}
90
+ Kernel.abort message
50
91
  end
92
+ end
51
93
 
52
- def run_migration(migration, direction)
53
- if migration[:kind] == :data
54
- ::ActiveRecord::Migration.write("== %s %s" % ['Data', "=" * 71])
55
- ::DataMigrate::DataMigrator.run(direction, data_migrations_path, migration[:version])
56
- else
57
- ::ActiveRecord::Migration.write("== %s %s" % ['Schema', "=" * 69])
58
- ::DataMigrate::SchemaMigration.run(
59
- direction,
60
- ::DataMigrate::SchemaMigration.migrations_paths,
61
- migration[:version]
62
- )
63
- end
94
+ def pending_migrations
95
+ sort_migrations(
96
+ pending_schema_migrations,
97
+ pending_data_migrations
98
+ )
99
+ end
100
+
101
+ def sort_migrations(*migrations)
102
+ migrations.flatten.sort { |a, b| sort_string(a) <=> sort_string(b) }
103
+ end
104
+
105
+ def sort_string migration
106
+ "#{migration[:version]}_#{migration[:kind] == :data ? 1 : 0}"
107
+ end
108
+
109
+ def data_migrations_path
110
+ ::DataMigrate.config.data_migrations_path
111
+ end
112
+
113
+ def run_migration(migration, direction)
114
+ if migration[:kind] == :data
115
+ ::ActiveRecord::Migration.write("== %s %s" % ['Data', "=" * 71])
116
+ ::DataMigrate::DataMigrator.run(direction, data_migrations_path, migration[:version])
117
+ else
118
+ ::ActiveRecord::Migration.write("== %s %s" % ['Schema', "=" * 69])
119
+ ::DataMigrate::SchemaMigration.run(
120
+ direction,
121
+ ::DataMigrate::SchemaMigration.migrations_paths,
122
+ migration[:version]
123
+ )
64
124
  end
65
125
  end
66
126
 
67
- def self.forward(step = 1)
68
- DataMigrate::DataMigrator.assure_data_schema_table
127
+ def schema_dump_path(db_config, format = ActiveRecord.schema_format)
128
+ return ENV["DATA_SCHEMA"] if ENV["DATA_SCHEMA"]
129
+
130
+ # We only require a schema.rb file for the primary database
131
+ return unless db_config.primary?
132
+
133
+ File.join(File.dirname(ActiveRecord::Tasks::DatabaseTasks.schema_dump_path(db_config, format)), schema_file_type)
134
+ end
135
+
136
+ # Override this method from `ActiveRecord::Tasks::DatabaseTasks`
137
+ # to ensure that the sha saved in ar_internal_metadata table
138
+ # is from the original schema.rb file
139
+ def schema_sha1(file)
140
+ ActiveRecord::Tasks::DatabaseTasks.schema_dump_path(ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: "primary"))
141
+ end
142
+
143
+ def forward(step = 1)
144
+ DataMigrate::DataMigrator.create_data_schema_table
69
145
  migrations = pending_migrations.reverse.pop(step).reverse
70
146
  migrations.each do | pending_migration |
71
147
  if pending_migration[:kind] == :data
@@ -78,22 +154,92 @@ module DataMigrate
78
154
  end
79
155
  end
80
156
 
81
- def self.pending_data_migrations
157
+ def pending_data_migrations
82
158
  data_migrations = DataMigrate::DataMigrator.migrations(data_migrations_path)
83
- sort_migrations(DataMigrate::DataMigrator.new(:up, data_migrations ).
84
- pending_migrations.map {|m| { version: m.version, name: m.name, kind: :data }})
159
+ data_migrator = DataMigrate::RailsHelper.data_migrator(:up, data_migrations)
160
+ sort_migrations(
161
+ data_migrator.pending_migrations.map { |m| { version: m.version, name: m.name, kind: :data } }
162
+ )
85
163
  end
86
164
 
87
- def self.pending_schema_migrations
165
+ def pending_schema_migrations
88
166
  ::DataMigrate::SchemaMigration.pending_schema_migrations
89
167
  end
90
168
 
91
- def self.past_migrations(sort = nil)
92
- data_versions = DataMigrate::DataSchemaMigration.table_exists? ? DataMigrate::DataSchemaMigration.normalized_versions : []
93
- schema_versions = ActiveRecord::SchemaMigration.normalized_versions
169
+ def past_migrations(sort = nil)
170
+ data_versions = DataMigrate::RailsHelper.data_schema_migration.table_exists? ? DataMigrate::RailsHelper.data_schema_migration.normalized_versions : []
171
+ schema_versions = DataMigrate::RailsHelper.schema_migration.normalized_versions
94
172
  migrations = data_versions.map { |v| { version: v.to_i, kind: :data } } + schema_versions.map { |v| { version: v.to_i, kind: :schema } }
95
173
 
96
174
  sort&.downcase == "asc" ? sort_migrations(migrations) : sort_migrations(migrations).reverse
97
175
  end
176
+
177
+ def self.migrate_with_data
178
+ DataMigrate::DataMigrator.create_data_schema_table
179
+
180
+ ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
181
+
182
+ db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
183
+
184
+ schema_mapped_versions = ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions(db_configs)
185
+ data_mapped_versions = DataMigrate::DatabaseTasks.db_configs_with_versions
186
+
187
+ mapped_versions = schema_mapped_versions.merge(data_mapped_versions) do |_key, schema_db_configs, data_db_configs|
188
+ schema_db_configs + data_db_configs
189
+ end
190
+
191
+ mapped_versions.sort.each do |version, db_configs|
192
+ db_configs.each do |db_config|
193
+ if is_data_migration = db_config.is_a?(DataMigrate::DatabaseConfigurationWrapper)
194
+ db_config = db_config.db_config
195
+ end
196
+
197
+ DataMigrate::DatabaseTasks.with_temporary_connection(db_config) do
198
+ if is_data_migration
199
+ DataMigrate::DataMigrator.run(:up, DataMigrate::DatabaseTasks.data_migrations_path, version)
200
+ else
201
+ ActiveRecord::Tasks::DatabaseTasks.migrate(version)
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ def self.prepare_all_with_data
209
+ seed = false
210
+
211
+ each_current_configuration(env) do |db_config|
212
+ next unless db_config.primary?
213
+
214
+ with_temporary_pool(db_config) do
215
+ begin
216
+ database_initialized = migration_connection.schema_migration.table_exists?
217
+ rescue ActiveRecord::NoDatabaseError
218
+ create(db_config)
219
+ retry
220
+ end
221
+
222
+ unless database_initialized
223
+ if File.exist?(schema_dump_path(db_config))
224
+ load_schema(db_config, ActiveRecord.schema_format, nil)
225
+ load_schema_current(
226
+ :ruby,
227
+ ENV["DATA_SCHEMA"]
228
+ )
229
+ end
230
+
231
+ seed = true
232
+ end
233
+
234
+ migrate_with_data
235
+ if ActiveRecord.dump_schema_after_migration
236
+ dump_schema(db_config)
237
+ DataMigrate::Tasks::DataMigrateTasks.dump
238
+ end
239
+ end
240
+ end
241
+
242
+ load_seed if seed
243
+ end
98
244
  end
99
245
  end