data_migrate 9.1.0 → 11.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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +40 -0
  3. data/README.md +22 -15
  4. data/lib/data_migrate/data_migrator.rb +15 -23
  5. data/lib/data_migrate/data_schema.rb +7 -7
  6. data/lib/data_migrate/data_schema_migration.rb +24 -7
  7. data/lib/data_migrate/database_configurations_wrapper.rb +11 -0
  8. data/lib/data_migrate/database_tasks.rb +224 -61
  9. data/lib/data_migrate/migration_context.rb +11 -8
  10. data/lib/data_migrate/rails_helper.rb +91 -0
  11. data/lib/data_migrate/schema_dumper.rb +1 -1
  12. data/lib/data_migrate/schema_migration.rb +5 -4
  13. data/lib/data_migrate/status_service.rb +3 -3
  14. data/lib/data_migrate/tasks/data_migrate_tasks.rb +11 -9
  15. data/lib/data_migrate/version.rb +1 -1
  16. data/lib/data_migrate.rb +2 -1
  17. data/lib/generators/data_migration/data_migration_generator.rb +2 -1
  18. data/tasks/databases.rake +9 -46
  19. metadata +13 -54
  20. data/.github/workflows/build.yml +0 -34
  21. data/.github/workflows/gempush.yml +0 -28
  22. data/.gitignore +0 -13
  23. data/.hound.yml +0 -4
  24. data/.overcommit.yml +0 -21
  25. data/.rbenv-gemsets +0 -2
  26. data/.rspec +0 -3
  27. data/.rubocop.yml +0 -2
  28. data/.ruby-style.yml +0 -1061
  29. data/Appraisals +0 -11
  30. data/Gemfile +0 -4
  31. data/Gemfile.rails6.1 +0 -11
  32. data/Rakefile +0 -2
  33. data/data_migrate.gemspec +0 -41
  34. data/gemfiles/rails_6.0.gemfile +0 -8
  35. data/gemfiles/rails_6.1.gemfile +0 -8
  36. data/gemfiles/rails_7.0.gemfile +0 -8
  37. data/lib/data_migrate/legacy_migrator.rb +0 -22
  38. data/screenshot.png +0 -0
  39. data/spec/data_migrate/config_spec.rb +0 -69
  40. data/spec/data_migrate/data_migrator_spec.rb +0 -80
  41. data/spec/data_migrate/data_schema_migration_spec.rb +0 -16
  42. data/spec/data_migrate/data_spec.rb +0 -74
  43. data/spec/data_migrate/database_tasks_spec.rb +0 -90
  44. data/spec/data_migrate/legacy_migrator_spec.rb +0 -38
  45. data/spec/data_migrate/migration.rb +0 -17
  46. data/spec/data_migrate/migration_context_spec.rb +0 -101
  47. data/spec/data_migrate/schema_dumper_spec.rb +0 -33
  48. data/spec/data_migrate/schema_migration_spec.rb +0 -97
  49. data/spec/data_migrate/status_service_spec.rb +0 -73
  50. data/spec/data_migrate/tasks/data_migrate_tasks_spec.rb +0 -129
  51. data/spec/db/data/20091231235959_some_name.rb +0 -9
  52. data/spec/db/data/20171231235959_super_update.rb +0 -9
  53. data/spec/db/data/20181128000207_excluded_file.rb.other_ext +0 -1
  54. data/spec/db/data/partial_schema/data_schema.rb +0 -1
  55. data/spec/db/data/partial_schema/test_data_schema.rb +0 -1
  56. data/spec/db/data/schema/data_schema.rb +0 -1
  57. data/spec/db/data/schema/test_data_schema.rb +0 -1
  58. data/spec/db/migrate/20131111111111_late_migration.rb +0 -9
  59. data/spec/db/migrate/20202020202011_db_migration.rb +0 -9
  60. data/spec/generators/data_migration/data_migration_generator_spec.rb +0 -101
  61. data/spec/spec_helper.rb +0 -28
  62. data/tasks/.gitkeep +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a19a5d3223862fe4ee25980432501b8e054bad3cc530e036f8d3f6206f4146c2
4
- data.tar.gz: ae1da5e5f75edc2dead2fcab270aaa70fe36d5d52011a2dbd687a3feee8868d4
3
+ metadata.gz: 907383933e031d0a1da7bad6dd3a43807794c0abeb27313af27e59ed8d802f3a
4
+ data.tar.gz: 1ddf826962f7078972ca9a234a723646d7744a41990dbe38550155fc0276fca3
5
5
  SHA512:
6
- metadata.gz: 61b4d3052eecd2512e9d9b1bf0f3b6d82502308d9031a71c53bc54d10a167415633475afe2683f8fa65de96a84ae2f1fc69a4132833775640af86550f6f3e161
7
- data.tar.gz: 86c53c8a4567a256368c280faf90f4acfa9c3153b1b56398b3cd36b28727db7f88de3133788303dc8210c632cf113d0f2017c0125728a19d0fd504f625d293b6
6
+ metadata.gz: e9e79dd56bda8e5f2afecb79f940eb17d7b5439c1d07b38d67943d58fc0ebaf159283d4478ac13925a2ee399097f6825b519052d3fea9f7b04c659a98647e75f
7
+ data.tar.gz: '0959a1bcf969cbc7834c839eca029d1416ff287ea2927a8ae0493a7880fb6910adea4baf5a2d162bd4cce35f80b610dc2f9d671cf77cf6583a699a96196871de'
data/Changelog.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # Changelog
2
2
 
3
+ # 11.2.0
4
+
5
+ - Remove committed Gemfile.lock, reduce bundled file list when running `gem install` https://github.com/ilyakatz/data-migrate/pull/351
6
+ - [Bump actionpack from 7.1.3.4 to 7.1.4.1](https://github.com/ilyakatz/data-migrate/pull/348)
7
+ - [Bump rexml from 3.3.6 to 3.3.9](https://github.com/ilyakatz/data-migrate/pull/349)
8
+ - Fix db_config_with_versions arity change and backport https://github.com/ilyakatz/data-migrate/pull/337
9
+
10
+ # 11.1.0
11
+ - Allow multiple data migration paths https://github.com/ilyakatz/data-migrate/pull/331
12
+ - Fix db:prepare:with_data task on [Rails 7.2](https://github.com/ilyakatz/data-migrate/pull/339)
13
+ - Fix ConnectionPool deprecation warnings on [Rails 7.2](https://github.com/ilyakatz/data-migrate/pull/341)
14
+ - Add Rails 8.0 to testing grounds https://github.com/ilyakatz/data-migrate/pull/341
15
+ - [Bump webrick from 1.8.1 to 1.8.2](https://github.com/ilyakatz/data-migrate/pull/345)
16
+
17
+ # 11.0.0
18
+ - [Update rexml to 3.3.6](https://github.com/ilyakatz/data-migrate/pull/329)
19
+ - Fixes a bug which ignored migrations on [Rails 7.1 and higher](https://github.com/ilyakatz/data-migrate/pull/326)
20
+
21
+ # 11.0.0rc
22
+ - Remove Ruby 3.0 from build matrix
23
+ - Support Rails 7.2.0 https://github.com/ilyakatz/data-migrate/pull/312
24
+ - Update gemfile.lock builds
25
+
26
+ ## 9.4.2
27
+ - Fix db:prepare:with_data task
28
+
29
+ ## 9.4.1
30
+ - Add db:prepare task
31
+
32
+ ## 9.4.0
33
+ - Reset model schema cache before each data migration https://github.com/ilyakatz/data-migrate/pull/307
34
+ - Run load_config rake task before db:migrate:with_data https://github.com/ilyakatz/data-migrate/pull/308
35
+
36
+ ## 9.3.0
37
+ - Improve with_data Rake task for multiple database https://github.com/ilyakatz/data-migrate/pull/296
38
+
39
+ ## 9.2.0
40
+ - Support Rails 7.1 https://github.com/ilyakatz/data-migrate/pull/278
41
+ - Build and test against 7.1.0.rc1 https://github.com/ilyakatz/data-migrate/pull/286
42
+
3
43
  ## 9.1.0
4
44
 
5
45
  - Fix a bug that caused `schema_sha1` in `ar_internal_metadata` to be reset to the `data_schema.rb` file. (#272)
data/README.md CHANGED
@@ -36,8 +36,13 @@ table to track all migrations.
36
36
 
37
37
  ## Rails Support
38
38
 
39
- Support Rails 6.0 through 7.0
39
+ Support Rails 6.1 through 7.2
40
40
 
41
+ For **Rails 6.0** support, please use gem version `9.1.x`:
42
+
43
+ ```ruby
44
+ gem 'data_migrate', '~> 9.1.0'
45
+ ```
41
46
 
42
47
  #### v1
43
48
 
@@ -86,13 +91,14 @@ You can generate a data migration as you would a schema migration:
86
91
  rake db:migrate:status:with_data # Display status of data and schema migrations
87
92
  rake db:migrate:up:with_data # Runs the "up" for a given migration VERSION
88
93
  rake db:migrate:with_data # Migrate the database data and schema (options: VERSION=x, VERBOSE=false)
94
+ rake db:prepare:with_data # Runs setup if database does not exist, or runs data and schema migrations if it does
89
95
  rake db:rollback:with_data # Rolls the schema back to the previous version (specify steps w/ STEP=n)
90
96
  rake db:schema:load:with_data # Load both schema.rb and data_schema.rb file into the database
91
97
  rake db:structure:load:with_data # Load both structure.sql and data_schema.rb file into the database
92
98
  rake db:version:with_data # Retrieves the current schema version numbers for data and schema migrations
93
99
 
94
100
 
95
- Tasks work as they would with the 'vanilla' db version. The 'with_data' addition to the 'db' tasks will run the task in the context of both the data and schema migrations. That is, rake db:rollback:with_data will check to see if it was a schema or data migration invoked last, and do that. Tasks invoked in that space also have an additional line of output, indicating if the action is performed on data or schema.
101
+ Tasks work as they would with the 'vanilla' db version. The 'with_data' addition to the 'db' tasks will run the task in the context of both the data and schema migrations. That is, rake db:rollback:with_data will check to see if it was a schema or data migration invoked last, and do that. Tasks invoked in that space also have an additional line of output, indicating if the action is performed on data or schema.
96
102
 
97
103
  With 'up' and 'down', you can specify the option 'BOTH', which defaults to false. Using true, will migrate both the data and schema (in the desired direction) if they both match the version provided. Again, going up, schema is given precedence. Down its data.
98
104
 
@@ -138,19 +144,12 @@ From now on capistrano will run `rake db:migrate:with_data` in every deploy.
138
144
  ## Rails Engines support
139
145
 
140
146
  This gem also has a initial support for adding data migrations inside Rails engines.
141
- Inside the Engine's class initializer (the one that inherits from `Rails::Engine`, usually inside `engines/ENGINE_NAME/lib/engine.rb`) you need to add something like this:
142
-
147
+ Just add your engines directory pattern to data_migrations initializer, for example
148
+ in the case your engines are located in `engines` folder you can set it up like this:
143
149
 
144
150
  ```ruby
145
- module EngineName
146
- class Engine < ::Rails::Engine
147
- initializer :engine_name do |app|
148
- ::DataMigrate.configure do |data_migrate|
149
- default_path = ::DataMigrate::Config.new.data_migrations_path
150
- data_migrate.data_migrations_path = [default_path, root.join('db', 'data')]
151
- end
152
- end
153
- end
151
+ DataMigrate.configure do |config|
152
+ config.data_migrations_path = ['db/data'] + Dir['engines/**/db/data']
154
153
  end
155
154
  ```
156
155
 
@@ -163,12 +162,20 @@ Then, in the Engine's `db/data` folder, you can add data migrations and run them
163
162
  Run tests for a specific version of Rails
164
163
 
165
164
  ```
166
- bundle exec appraisal install
167
- bundle exec appraisal rails-6.0 rspec
168
165
  bundle exec appraisal rails-6.1 rspec
169
166
  bundle exec appraisal rails-7.0 rspec
167
+ bundle exec appraisal rails-7.1 rspec
168
+ bundle exec appraisal rails-7.2 rspec
170
169
  ```
171
170
 
171
+ ## Releasing new version
172
+
173
+ 1. Create a new tag, eg `git tag 9.4.1`
174
+ 1. Go to https://github.com/ilyakatz/data-migrate/tags
175
+ 1. Click "Create release" under 9.4.1
176
+ 1. CLick "Generate release notes"
177
+ 1. Click "Publish release"
178
+
172
179
  ## Thanks
173
180
 
174
181
  [Andrew J Vargo](http://github.com/ajvargo) Andrew was the original creator and maintainer of this project!
@@ -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.create_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
+ Array.wrap(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
@@ -29,13 +29,13 @@ module DataMigrate
29
29
  end
30
30
 
31
31
  def versions
32
- @versions ||= begin
33
- versions = []
34
- Dir.foreach(DataMigrate::DataMigrator.full_migrations_path) do |file|
35
- match_data = DataMigrate::DataMigrator.match(file)
36
- versions << match_data[1].to_i if match_data
32
+ @versions ||= Set.new.tap do |versions|
33
+ DataMigrate::DataMigrator.migrations_paths.each do |path|
34
+ Dir.foreach(path) do |file|
35
+ match_data = DataMigrate::DataMigrator.match(file)
36
+ versions << match_data[1].to_i if match_data
37
+ end
37
38
  end
38
- versions
39
39
  end
40
40
  end
41
41
 
@@ -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,86 +5,142 @@ 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
+ extend self
10
11
 
11
- class << self
12
- def schema_file(_format = nil)
13
- File.join(db_dir, "data_schema.rb")
14
- end
15
-
16
- def schema_file_type(_format = nil)
17
- "data_schema.rb"
18
- end
19
-
20
- def dump_filename(spec_name, format = ActiveRecord::Base.schema_format)
21
- filename = if spec_name == "primary"
22
- schema_file_type(format)
12
+ # These method are only introduced in Rails 7.1
13
+ unless respond_to?(:with_temporary_pool_for_each)
14
+ def with_temporary_pool_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_pool(db_config, &block)
23
18
  else
24
- "#{spec_name}_#{schema_file_type(format)}"
19
+ ActiveRecord::Base.configurations.configs_for(env_name: env, name: name).each do |db_config|
20
+ with_temporary_pool(db_config, &block)
21
+ end
25
22
  end
26
-
27
- ENV["DATA_SCHEMA"] || File.join(db_dir, filename)
28
23
  end
29
24
 
30
- def check_schema_file(filename)
31
- unless File.exist?(filename)
32
- message = +%{#{filename} doesn't exist yet. Run `rake data:migrate` to create it, then try again.}
33
- Kernel.abort message
25
+ def with_temporary_connection(db_config, &block) # :nodoc:
26
+ with_temporary_pool(db_config) do |pool|
27
+ pool.with_connection(&block)
34
28
  end
35
29
  end
36
30
 
37
- def pending_migrations
38
- sort_migrations(
39
- pending_schema_migrations,
40
- pending_data_migrations
41
- )
31
+ def migration_class # :nodoc:
32
+ ActiveRecord::Base
42
33
  end
43
34
 
44
- def sort_migrations(*migrations)
45
- migrations.flatten.sort { |a, b| sort_string(a) <=> sort_string(b) }
35
+ def migration_connection # :nodoc:
36
+ migration_class.connection
46
37
  end
47
38
 
48
- def sort_string migration
49
- "#{migration[:version]}_#{migration[:kind] == :data ? 1 : 0}"
50
- end
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)
51
42
 
52
- def data_migrations_path
53
- ::DataMigrate.config.data_migrations_path
43
+ yield pool
44
+ ensure
45
+ migration_class.connection_handler.establish_connection(original_db_config)
54
46
  end
47
+ end
55
48
 
56
- def run_migration(migration, direction)
57
- if migration[:kind] == :data
58
- ::ActiveRecord::Migration.write("== %s %s" % ['Data', "=" * 71])
59
- ::DataMigrate::DataMigrator.run(direction, data_migrations_path, migration[:version])
60
- else
61
- ::ActiveRecord::Migration.write("== %s %s" % ['Schema', "=" * 69])
62
- ::DataMigrate::SchemaMigration.run(
63
- direction,
64
- ::DataMigrate::SchemaMigration.migrations_paths,
65
- migration[:version]
66
- )
49
+ def db_configs_with_versions
50
+ db_configs_with_versions = Hash.new { |h, k| h[k] = [] }
51
+
52
+ with_temporary_pool_for_each do |pool|
53
+ db_config = 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
57
+
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
67
62
  end
68
63
  end
69
64
 
70
- def schema_dump_path(db_config, format = ActiveRecord.schema_format)
71
- return ENV["DATA_SCHEMA"] if ENV["DATA_SCHEMA"]
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)}"
82
+ end
72
83
 
73
- # We only require a schema.rb file for the primary database
74
- return unless db_config.primary?
84
+ ENV["DATA_SCHEMA"] || File.join(db_dir, filename)
85
+ end
75
86
 
76
- super.gsub(/(_)?schema\.rb\z/, '\1data_schema.rb')
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
77
91
  end
92
+ end
93
+
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
78
112
 
79
- # Override this method from `ActiveRecord::Tasks::DatabaseTasks`
80
- # to ensure that the sha saved in ar_internal_metadata table
81
- # is from the original schema.rb file
82
- def schema_sha1(file)
83
- super(file.gsub(/data_schema.rb\z/, 'schema.rb'))
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
+ )
84
124
  end
85
125
  end
86
126
 
87
- def self.forward(step = 1)
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)
88
144
  DataMigrate::DataMigrator.create_data_schema_table
89
145
  migrations = pending_migrations.reverse.pop(step).reverse
90
146
  migrations.each do | pending_migration |
@@ -98,22 +154,129 @@ module DataMigrate
98
154
  end
99
155
  end
100
156
 
101
- def self.pending_data_migrations
157
+ def pending_data_migrations
102
158
  data_migrations = DataMigrate::DataMigrator.migrations(data_migrations_path)
103
- sort_migrations(DataMigrate::DataMigrator.new(:up, data_migrations ).
104
- 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
+ )
105
163
  end
106
164
 
107
- def self.pending_schema_migrations
165
+ def pending_schema_migrations
108
166
  ::DataMigrate::SchemaMigration.pending_schema_migrations
109
167
  end
110
168
 
111
- def self.past_migrations(sort = nil)
112
- data_versions = DataMigrate::DataSchemaMigration.table_exists? ? DataMigrate::DataSchemaMigration.normalized_versions : []
113
- 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
114
172
  migrations = data_versions.map { |v| { version: v.to_i, kind: :data } } + schema_versions.map { |v| { version: v.to_i, kind: :schema } }
115
173
 
116
174
  sort&.downcase == "asc" ? sort_migrations(migrations) : sort_migrations(migrations).reverse
117
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
+ # 7.2 removes the param for db_configs_with_versions in https://github.com/rails/rails/commit/9572fcb4a0bd5396436689a6a42613886871cd81
183
+ # 7.1 stable backported the change in https://github.com/rails/rails/commit/c53ec4b60980036b43528829d4b0b7457f759224
184
+ schema_mapped_versions = if Gem::Dependency.new("railties", ">= 7.1.4").match?("railties", Gem.loaded_specs["railties"].version, true)
185
+ ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions
186
+ else
187
+ db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
188
+
189
+ ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions(db_configs)
190
+ end
191
+
192
+ data_mapped_versions = DataMigrate::DatabaseTasks.db_configs_with_versions
193
+
194
+ mapped_versions = schema_mapped_versions.merge(data_mapped_versions) do |_key, schema_db_configs, data_db_configs|
195
+ schema_db_configs + data_db_configs
196
+ end
197
+
198
+ mapped_versions.sort.each do |version, db_configs|
199
+ db_configs.each do |db_config|
200
+ if is_data_migration = db_config.is_a?(DataMigrate::DatabaseConfigurationWrapper)
201
+ db_config = db_config.db_config
202
+ end
203
+
204
+ DataMigrate::DatabaseTasks.with_temporary_connection(db_config) do
205
+ if is_data_migration
206
+ DataMigrate::DataMigrator.run(:up, DataMigrate::DatabaseTasks.data_migrations_path, version)
207
+ else
208
+ ActiveRecord::Tasks::DatabaseTasks.migrate(version)
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
214
+
215
+ def self.prepare_all_with_data
216
+ seed = false
217
+
218
+ each_current_configuration(env) do |db_config|
219
+ next unless primary?(db_config)
220
+
221
+ with_temporary_pool(db_config) do |pool|
222
+ unless database_exists?(pool.connection)
223
+ create(db_config)
224
+ if File.exist?(schema_dump_path(db_config))
225
+ load_schema(db_config, schema_format, nil)
226
+ load_schema_current(
227
+ :ruby,
228
+ ENV["DATA_SCHEMA"]
229
+ )
230
+ end
231
+
232
+ seed = true
233
+ end
234
+
235
+ migrate_with_data
236
+ if dump_schema_after_migration?
237
+ dump_schema(db_config)
238
+ DataMigrate::Tasks::DataMigrateTasks.dump
239
+ end
240
+ end
241
+ end
242
+
243
+ load_seed if seed
244
+ end
245
+
246
+ private
247
+
248
+ def database_exists?(connection)
249
+ if connection.respond_to?(:database_exists?) # Rails 7.1+
250
+ connection.database_exists?
251
+ else
252
+ connection.table_exists?(ActiveRecord::SchemaMigration.table_name)
253
+ end
254
+ rescue ActiveRecord::NoDatabaseError
255
+ false
256
+ end
257
+
258
+ def primary?(db_config)
259
+ if db_config.respond_to?(:primary?) # Rails 7.0+
260
+ db_config.primary?
261
+ else
262
+ db_config.name == "primary"
263
+ end
264
+ end
265
+
266
+ def dump_schema_after_migration?
267
+ if ActiveRecord.respond_to?(:dump_schema_after_migration)
268
+ ActiveRecord.dump_schema_after_migration
269
+ else
270
+ ActiveRecord::Base.dump_schema_after_migration
271
+ end
272
+ end
273
+
274
+ def schema_format
275
+ if ActiveRecord.respond_to?(:schema_format)
276
+ ActiveRecord.schema_format
277
+ else
278
+ ActiveRecord::Base.schema_format
279
+ end
280
+ end
118
281
  end
119
282
  end