data_migrate 3.2.0 → 11.3.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 (46) hide show
  1. checksums.yaml +5 -5
  2. data/Changelog.md +246 -2
  3. data/README.md +107 -91
  4. data/lib/capistrano/data_migrate/migrate.rb +3 -4
  5. data/lib/data_migrate/config.rb +33 -0
  6. data/lib/data_migrate/data_migrator.rb +54 -58
  7. data/lib/data_migrate/data_schema.rb +63 -0
  8. data/lib/data_migrate/data_schema_migration.rb +23 -6
  9. data/lib/data_migrate/database_configurations_wrapper.rb +11 -0
  10. data/lib/data_migrate/database_tasks.rb +290 -0
  11. data/lib/data_migrate/migration_context.rb +93 -0
  12. data/lib/data_migrate/rails_helper.rb +91 -0
  13. data/lib/data_migrate/schema_dumper.rb +38 -0
  14. data/lib/data_migrate/schema_migration.rb +41 -0
  15. data/lib/data_migrate/status_service.rb +58 -0
  16. data/lib/data_migrate/tasks/data_migrate_tasks.rb +107 -0
  17. data/lib/data_migrate/version.rb +1 -1
  18. data/lib/data_migrate.rb +20 -7
  19. data/lib/generators/data_migrate.rb +15 -2
  20. data/lib/generators/data_migration/data_migration_generator.rb +22 -21
  21. data/lib/generators/data_migration/templates/data_migration.rb +4 -2
  22. data/tasks/databases.rake +115 -228
  23. metadata +64 -42
  24. data/.gitignore +0 -6
  25. data/.rspec +0 -3
  26. data/.travis.yml +0 -17
  27. data/Appraisals +0 -21
  28. data/Gemfile +0 -4
  29. data/Gemfile.rails5 +0 -5
  30. data/Gemfile.rails5.1 +0 -5
  31. data/Rakefile +0 -2
  32. data/data_migrate.gemspec +0 -39
  33. data/gemfiles/rails_4.0.gemfile +0 -7
  34. data/gemfiles/rails_4.1.gemfile +0 -7
  35. data/gemfiles/rails_4.2.gemfile +0 -8
  36. data/gemfiles/rails_5.0.gemfile +0 -7
  37. data/gemfiles/rails_5.1.gemfile +0 -7
  38. data/lib/data_migrate/migration.rb +0 -26
  39. data/lib/data_migrate/migration_five.rb +0 -26
  40. data/screenshot.png +0 -0
  41. data/spec/data_migrate/data_migrator_spec.rb +0 -45
  42. data/spec/data_migrate/data_schema_migration_spec.rb +0 -16
  43. data/spec/data_migrate/migration.rb +0 -19
  44. data/spec/generators/data_migration/data_migration_generator_spec.rb +0 -27
  45. data/spec/spec_helper.rb +0 -5
  46. data/tasks/.gitkeep +0 -0
@@ -1,84 +1,80 @@
1
- require 'active_record'
1
+ # frozen_string_literal: true
2
2
 
3
- module DataMigrate
3
+ require "active_record"
4
+ require "data_migrate/config"
4
5
 
6
+ module DataMigrate
5
7
  class DataMigrator < ActiveRecord::Migrator
6
-
7
- def record_version_state_after_migrating(version)
8
- if down?
9
- migrated.delete(version)
10
- DataMigrate::DataSchemaMigration.where(:version => version.to_s).delete_all
11
- else
12
- migrated << version
13
- DataMigrate::DataSchemaMigration.create!(:version => version.to_s)
14
- end
8
+ def load_migrated
9
+ @migrated_versions =
10
+ DataMigrate::RailsHelper.data_schema_migration.normalized_versions.map(&:to_i).sort
15
11
  end
16
12
 
17
13
  class << self
18
- def get_all_versions(connection = ActiveRecord::Base.connection)
19
- if table_exists?(connection, schema_migrations_table_name)
20
- # Certain versions of the gem wrote data migration versions into
21
- # schema_migrations table. After the fix, it was corrected to write into
22
- # data_migrations. However, not to break anything we are going to
23
- # get versions from both tables.
24
- #
25
- # This may cause some problems:
26
- # Eg. rake data:versions will show version from the schema_migrations table
27
- # which may be a version of actual schema migration and not data migration
28
- DataMigrate::DataSchemaMigration.all.map { |x| x.version.to_i }.sort +
29
- ActiveRecord::SchemaMigration.all.map { |x| x.version.to_i }.sort
30
- else
31
- []
32
- end
14
+ def migrations_paths
15
+ Array.wrap(DataMigrate.config.data_migrations_path)
33
16
  end
34
17
 
35
- def schema_migrations_table_name
36
- ActiveRecord::Base.table_name_prefix + 'data_migrations' + ActiveRecord::Base.table_name_suffix
18
+ def create_data_schema_table
19
+ DataMigrate::RailsHelper.data_schema_migration.create_table
37
20
  end
38
21
 
39
- def migrations_path
40
- 'db/data'
22
+ def current_version
23
+ DataMigrate::MigrationContext.new(migrations_paths).current_version
41
24
  end
42
25
 
43
- def assure_data_schema_table
44
- ActiveRecord::Base.establish_connection(db_config)
45
- sm_table = DataMigrate::DataMigrator.schema_migrations_table_name
26
+ ##
27
+ # Compares the given filename with what we expect data migration
28
+ # filenames to be, eg the "20091231235959_some_name.rb" pattern
29
+ # @param (String) filename
30
+ # @return (MatchData)
31
+ def match(filename)
32
+ /(\d{14})_(.+)\.rb$/.match(filename)
33
+ end
46
34
 
47
- unless table_exists?(ActiveRecord::Base.connection, sm_table)
48
- create_table(sm_table)
49
- end
35
+ def needs_migration?
36
+ DataMigrate::DatabaseTasks.pending_migrations.count.positive?
37
+ end
38
+ ##
39
+ # Provides the full migrations_path filepath
40
+ # @return (String)
41
+ def full_migrations_path
42
+ File.join(Rails.root, *migrations_paths.split(File::SEPARATOR))
50
43
  end
51
44
 
52
- private
45
+ def migrations_status
46
+ DataMigrate::MigrationContext.new(migrations_paths).migrations_status
47
+ end
53
48
 
54
- def create_table(sm_table)
55
- ActiveRecord::Base.connection.create_table(sm_table, :id => false) do |schema_migrations_table|
56
- schema_migrations_table.column :version, :string, :null => false
57
- end
49
+ # TODO: this was added to be backward compatible, need to re-evaluate
50
+ def migrations(_migrations_paths)
51
+ DataMigrate::MigrationContext.new(_migrations_paths).migrations
52
+ end
58
53
 
59
- suffix = ActiveRecord::Base.table_name_suffix
60
- prefix = ActiveRecord::Base.table_name_prefix
61
- index_name = "#{prefix}unique_data_migrations#{suffix}"
54
+ #TODO: this was added to be backward compatible, need to re-evaluate
55
+ def run(direction, migration_paths, version)
56
+ # Ensure all Active Record model cache is reset for each data migration
57
+ # As recommended in: https://github.com/rails/rails/blob/da21c2e9812e5eb0698fba4a9aa38632fc004432/activerecord/lib/active_record/migration.rb#L467-L470
58
+ ActiveRecord::Base.descendants.each(&:reset_column_information)
62
59
 
63
- ActiveRecord::Base.connection.add_index sm_table, :version,
64
- :unique => true,
65
- :name => index_name
60
+ DataMigrate::MigrationContext.new(migration_paths).run(direction, version)
66
61
  end
67
62
 
68
- def table_exists?(connection, table_name)
69
- # Avoid the warning that table_exists? prints in Rails 5.0 due a change in behavior between
70
- # Rails 5.0 and Rails 5.1 of this method with respect to database views.
71
- if ActiveRecord.version >= Gem::Version.new('5.0') && ActiveRecord.version < Gem::Version.new('5.1')
72
- connection.data_source_exists?(table_name)
73
- else
74
- connection.table_exists?(schema_migrations_table_name)
75
- end
63
+ def rollback(migrations_path, steps)
64
+ DataMigrate::MigrationContext.new(migrations_path).rollback(steps)
76
65
  end
66
+ end
77
67
 
78
- def db_config
79
- ActiveRecord::Base.configurations[Rails.env || 'development'] || ENV["DATABASE_URL"]
80
- end
68
+ private
81
69
 
70
+ def record_version_state_after_migrating(version)
71
+ if down?
72
+ migrated.delete(version)
73
+ DataMigrate::RailsHelper.data_schema_delete_version(version.to_s)
74
+ else
75
+ migrated << version
76
+ DataMigrate::RailsHelper.data_schema_migration.create_version(version.to_s)
77
+ end
82
78
  end
83
79
  end
84
80
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DataMigrate
4
+ ##
5
+ # Provides the definition method for data_schema.rb
6
+ class Data < ActiveRecord::Schema
7
+ # This method is based on the following two methods
8
+ # ActiveRecord::Schema#define
9
+ # ActiveRecord::ConnectionAdapters::SchemaStatements
10
+ # #assume_migrated_upto_version
11
+ def define(info)
12
+ DataMigrate::DataMigrator.create_data_schema_table
13
+
14
+ return if info[:version].blank?
15
+
16
+ version = info[:version].to_i
17
+
18
+ unless migrated.include?(version)
19
+ execute "INSERT INTO #{sm_table} (version) VALUES ('#{version}')"
20
+ end
21
+
22
+ insert(version)
23
+ end
24
+
25
+ private
26
+
27
+ def migrated
28
+ @migrated ||= select_values("SELECT version FROM #{sm_table}").map(&:to_i)
29
+ end
30
+
31
+ def versions
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
38
+ end
39
+ end
40
+ end
41
+
42
+ def insert(version)
43
+ inserted = Set.new
44
+ (versions - migrated).each do |v|
45
+ if inserted.include?(v)
46
+ raise "Duplicate data migration #{v}. Please renumber your data " \
47
+ "migrations to resolve the conflict."
48
+ elsif v < version
49
+ execute "INSERT INTO #{sm_table} (version) VALUES ('#{v}')"
50
+ inserted << v
51
+ end
52
+ end
53
+ end
54
+
55
+ def sm_table
56
+ quote_table_name(table_name)
57
+ end
58
+
59
+ def table_name
60
+ DataMigrate::RailsHelper.data_schema_migration.table_name
61
+ end
62
+ end
63
+ end
@@ -1,14 +1,31 @@
1
1
  module DataMigrate
2
- class DataSchemaMigration < ::ActiveRecord::SchemaMigration
3
- class << self
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
4
6
  def table_name
5
- ActiveRecord::Base.table_name_prefix + 'data_migrations' + ActiveRecord::Base.table_name_suffix
7
+ ActiveRecord::Base.table_name_prefix + DataMigrate.config.data_migrations_table_name + ActiveRecord::Base.table_name_suffix
6
8
  end
7
9
 
8
- def index_name
9
- "#{table_name_prefix}unique_data_migrations#{table_name_suffix}"
10
+ def primary_key
11
+ "version"
12
+ end
13
+ else
14
+ class << self
15
+ def table_name
16
+ ActiveRecord::Base.table_name_prefix + DataMigrate.config.data_migrations_table_name + ActiveRecord::Base.table_name_suffix
17
+ end
18
+
19
+ def primary_key
20
+ "version"
21
+ end
22
+
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)
27
+ end
10
28
  end
11
29
  end
12
30
  end
13
31
  end
14
-
@@ -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
@@ -0,0 +1,290 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "data_migrate/config"
4
+
5
+ module DataMigrate
6
+ ##
7
+ # This class extends DatabaseTasks to add a schema_file method.
8
+ module DatabaseTasks
9
+ extend ActiveRecord::Tasks::DatabaseTasks
10
+ extend self
11
+
12
+ if respond_to?(:register_task)
13
+ register_task(/mysql/, "ActiveRecord::Tasks::MySQLDatabaseTasks")
14
+ register_task(/trilogy/, "ActiveRecord::Tasks::MySQLDatabaseTasks")
15
+ register_task(/postgresql/, "ActiveRecord::Tasks::PostgreSQLDatabaseTasks")
16
+ register_task(/sqlite/, "ActiveRecord::Tasks::SQLiteDatabaseTasks")
17
+ end
18
+
19
+ # These method are only introduced in Rails 7.1
20
+ unless respond_to?(:with_temporary_pool_for_each)
21
+ def with_temporary_pool_for_each(env: ActiveRecord::Tasks::DatabaseTasks.env, name: nil, &block) # :nodoc:
22
+ if name
23
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: env, name: name)
24
+ with_temporary_pool(db_config, &block)
25
+ else
26
+ ActiveRecord::Base.configurations.configs_for(env_name: env, name: name).each do |db_config|
27
+ with_temporary_pool(db_config, &block)
28
+ end
29
+ end
30
+ end
31
+
32
+ def with_temporary_connection(db_config, &block) # :nodoc:
33
+ with_temporary_pool(db_config) do |pool|
34
+ pool.with_connection(&block)
35
+ end
36
+ end
37
+
38
+ def migration_class # :nodoc:
39
+ ActiveRecord::Base
40
+ end
41
+
42
+ def migration_connection # :nodoc:
43
+ migration_class.connection
44
+ end
45
+
46
+ private def with_temporary_pool(db_config)
47
+ original_db_config = migration_class.connection_db_config
48
+ pool = migration_class.connection_handler.establish_connection(db_config)
49
+
50
+ yield pool
51
+ ensure
52
+ migration_class.connection_handler.establish_connection(original_db_config)
53
+ end
54
+ end
55
+
56
+ def db_configs_with_versions
57
+ db_configs_with_versions = Hash.new { |h, k| h[k] = [] }
58
+
59
+ with_temporary_pool_for_each do |pool|
60
+ db_config = pool.db_config
61
+ if db_config.primary?
62
+ versions_to_run = DataMigrate::DatabaseTasks.pending_data_migrations.map { |m| m[:version] }
63
+ target_version = ActiveRecord::Tasks::DatabaseTasks.target_version
64
+
65
+ versions_to_run.each do |version|
66
+ next if target_version && target_version != version
67
+ db_configs_with_versions[version] << DatabaseConfigurationWrapper.new(db_config)
68
+ end
69
+ end
70
+ end
71
+
72
+ db_configs_with_versions
73
+ end
74
+
75
+ def schema_file(_format = nil)
76
+ File.join(db_dir, "data_schema.rb")
77
+ end
78
+
79
+ def schema_file_type(_format = nil)
80
+ "data_schema.rb"
81
+ end
82
+
83
+ # This method is removed in Rails 7.0
84
+ def dump_filename(spec_name, format = ActiveRecord::Base.schema_format)
85
+ filename = if spec_name == "primary"
86
+ schema_file_type(format)
87
+ else
88
+ "#{spec_name}_#{schema_file_type(format)}"
89
+ end
90
+
91
+ ENV["DATA_SCHEMA"] || File.join(db_dir, filename)
92
+ end
93
+
94
+ def check_schema_file(filename)
95
+ unless File.exist?(filename)
96
+ message = +%{#{filename} doesn't exist yet. Run `rake data:migrate` to create it, then try again.}
97
+ Kernel.abort message
98
+ end
99
+ end
100
+
101
+ def pending_migrations
102
+ sort_migrations(
103
+ pending_schema_migrations,
104
+ pending_data_migrations
105
+ )
106
+ end
107
+
108
+ def sort_migrations(*migrations)
109
+ migrations.flatten.sort { |a, b| sort_string(a) <=> sort_string(b) }
110
+ end
111
+
112
+ def sort_string migration
113
+ "#{migration[:version]}_#{migration[:kind] == :data ? 1 : 0}"
114
+ end
115
+
116
+ def data_migrations_path
117
+ ::DataMigrate.config.data_migrations_path
118
+ end
119
+
120
+ def run_migration(migration, direction)
121
+ if migration[:kind] == :data
122
+ ::ActiveRecord::Migration.write("== %s %s" % ['Data', "=" * 71])
123
+ ::DataMigrate::DataMigrator.run(direction, data_migrations_path, migration[:version])
124
+ else
125
+ ::ActiveRecord::Migration.write("== %s %s" % ['Schema', "=" * 69])
126
+ ::DataMigrate::SchemaMigration.run(
127
+ direction,
128
+ ::DataMigrate::SchemaMigration.migrations_paths,
129
+ migration[:version]
130
+ )
131
+ end
132
+ end
133
+
134
+ def schema_dump_path(db_config, format = ActiveRecord.schema_format)
135
+ return ENV["DATA_SCHEMA"] if ENV["DATA_SCHEMA"]
136
+
137
+ # We only require a schema.rb file for the primary database
138
+ return unless db_config.primary?
139
+
140
+ File.join(File.dirname(ActiveRecord::Tasks::DatabaseTasks.schema_dump_path(db_config, format)), schema_file_type)
141
+ end
142
+
143
+ # Override this method from `ActiveRecord::Tasks::DatabaseTasks`
144
+ # to ensure that the sha saved in ar_internal_metadata table
145
+ # is from the original schema.rb file
146
+ def schema_sha1(file)
147
+ ActiveRecord::Tasks::DatabaseTasks.schema_dump_path(ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: "primary"))
148
+ end
149
+
150
+ def forward(step = 1)
151
+ DataMigrate::DataMigrator.create_data_schema_table
152
+ migrations = pending_migrations.reverse.pop(step).reverse
153
+ migrations.each do | pending_migration |
154
+ if pending_migration[:kind] == :data
155
+ ActiveRecord::Migration.write("== %s %s" % ["Data", "=" * 71])
156
+ DataMigrate::DataMigrator.run(:up, data_migrations_path, pending_migration[:version])
157
+ elsif pending_migration[:kind] == :schema
158
+ ActiveRecord::Migration.write("== %s %s" % ["Schema", "=" * 69])
159
+ DataMigrate::SchemaMigration.run(:up, DataMigrate::SchemaMigration.migrations_paths, pending_migration[:version])
160
+ end
161
+ end
162
+ end
163
+
164
+ def pending_data_migrations
165
+ data_migrations = DataMigrate::DataMigrator.migrations(data_migrations_path)
166
+ data_migrator = DataMigrate::RailsHelper.data_migrator(:up, data_migrations)
167
+ sort_migrations(
168
+ data_migrator.pending_migrations.map { |m| { version: m.version, name: m.name, kind: :data } }
169
+ )
170
+ end
171
+
172
+ def pending_schema_migrations
173
+ ::DataMigrate::SchemaMigration.pending_schema_migrations
174
+ end
175
+
176
+ def past_migrations(sort = nil)
177
+ data_versions = DataMigrate::RailsHelper.data_schema_migration.table_exists? ? DataMigrate::RailsHelper.data_schema_migration.normalized_versions : []
178
+ schema_versions = DataMigrate::RailsHelper.schema_migration.normalized_versions
179
+ migrations = data_versions.map { |v| { version: v.to_i, kind: :data } } + schema_versions.map { |v| { version: v.to_i, kind: :schema } }
180
+
181
+ sort&.downcase == "asc" ? sort_migrations(migrations) : sort_migrations(migrations).reverse
182
+ end
183
+
184
+ def self.migrate_with_data
185
+ DataMigrate::DataMigrator.create_data_schema_table
186
+
187
+ ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
188
+
189
+ # 7.2 removes the param for db_configs_with_versions in https://github.com/rails/rails/commit/9572fcb4a0bd5396436689a6a42613886871cd81
190
+ # 7.1 stable backported the change in https://github.com/rails/rails/commit/c53ec4b60980036b43528829d4b0b7457f759224
191
+ schema_mapped_versions = if Gem::Dependency.new("railties", ">= 7.1.4").match?("railties", Gem.loaded_specs["railties"].version, true)
192
+ ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions
193
+ else
194
+ db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
195
+
196
+ ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions(db_configs)
197
+ end
198
+
199
+ data_mapped_versions = DataMigrate::DatabaseTasks.db_configs_with_versions
200
+
201
+ mapped_versions = schema_mapped_versions.merge(data_mapped_versions) do |_key, schema_db_configs, data_db_configs|
202
+ schema_db_configs + data_db_configs
203
+ end
204
+
205
+ mapped_versions.sort.each do |version, db_configs|
206
+ db_configs.each do |db_config|
207
+ if is_data_migration = db_config.is_a?(DataMigrate::DatabaseConfigurationWrapper)
208
+ db_config = db_config.db_config
209
+ end
210
+
211
+ DataMigrate::DatabaseTasks.with_temporary_connection(db_config) do
212
+ if is_data_migration
213
+ DataMigrate::DataMigrator.run(:up, DataMigrate::DatabaseTasks.data_migrations_path, version)
214
+ else
215
+ ActiveRecord::Tasks::DatabaseTasks.migrate(version)
216
+ end
217
+ end
218
+ end
219
+ end
220
+ end
221
+
222
+ def self.prepare_all_with_data
223
+ seed = false
224
+
225
+ each_current_configuration(env) do |db_config|
226
+ next unless primary?(db_config)
227
+
228
+ with_temporary_pool(db_config) do |pool|
229
+ connection = pool.respond_to?(:lease_connection) ? pool.lease_connection : pool.connection
230
+ unless database_exists?(connection)
231
+ create(db_config)
232
+ if File.exist?(schema_dump_path(db_config))
233
+ load_schema(db_config, schema_format, nil)
234
+ load_schema_current(
235
+ :ruby,
236
+ ENV["DATA_SCHEMA"]
237
+ )
238
+ end
239
+
240
+ seed = true
241
+ end
242
+
243
+ migrate_with_data
244
+ if dump_schema_after_migration?
245
+ dump_schema(db_config)
246
+ DataMigrate::Tasks::DataMigrateTasks.dump
247
+ end
248
+ end
249
+ end
250
+
251
+ load_seed if seed
252
+ end
253
+
254
+ private
255
+
256
+ def database_exists?(connection)
257
+ if connection.respond_to?(:database_exists?) # Rails 7.1+
258
+ connection.database_exists?
259
+ else
260
+ connection.table_exists?(ActiveRecord::SchemaMigration.table_name)
261
+ end
262
+ rescue ActiveRecord::NoDatabaseError
263
+ false
264
+ end
265
+
266
+ def primary?(db_config)
267
+ if db_config.respond_to?(:primary?) # Rails 7.0+
268
+ db_config.primary?
269
+ else
270
+ db_config.name == "primary"
271
+ end
272
+ end
273
+
274
+ def dump_schema_after_migration?
275
+ if ActiveRecord.respond_to?(:dump_schema_after_migration)
276
+ ActiveRecord.dump_schema_after_migration
277
+ else
278
+ ActiveRecord::Base.dump_schema_after_migration
279
+ end
280
+ end
281
+
282
+ def schema_format
283
+ if ActiveRecord.respond_to?(:schema_format)
284
+ ActiveRecord.schema_format
285
+ else
286
+ ActiveRecord::Base.schema_format
287
+ end
288
+ end
289
+ end
290
+ end
@@ -0,0 +1,93 @@
1
+ module DataMigrate
2
+ class MigrationContext < ActiveRecord::MigrationContext
3
+ def initialize(migrations_paths = "db/data")
4
+ @migrations_paths = migrations_paths || "db/data"
5
+ end
6
+
7
+ def up(target_version = nil)
8
+ selected_migrations = if block_given?
9
+ migrations.select { |m| yield m }
10
+ else
11
+ migrations
12
+ end
13
+
14
+ data_migrator = DataMigrate::RailsHelper.data_migrator(:up, selected_migrations, DataMigrate::RailsHelper.schema_migration, DataMigrate::RailsHelper.internal_metadata, target_version)
15
+ data_migrator.migrate
16
+ end
17
+
18
+ def down(target_version = nil)
19
+ selected_migrations =
20
+ if block_given?
21
+ migrations.select { |m| yield m }
22
+ else
23
+ migrations
24
+ end
25
+
26
+ data_migrator = DataMigrate::RailsHelper.data_migrator(:down, selected_migrations, DataMigrate::RailsHelper.schema_migration, DataMigrate::RailsHelper.internal_metadata, target_version)
27
+ data_migrator.migrate
28
+ end
29
+
30
+ def run(direction, target_version)
31
+ data_migrator = DataMigrate::RailsHelper.data_migrator(direction, migrations, DataMigrate::RailsHelper.schema_migration, DataMigrate::RailsHelper.internal_metadata, target_version)
32
+ data_migrator.run
33
+ end
34
+
35
+ def current_version
36
+ get_all_versions.max || 0
37
+ rescue ActiveRecord::NoDatabaseError
38
+ end
39
+
40
+ def migration_files
41
+ paths = Array(migrations_paths)
42
+ Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
43
+ end
44
+
45
+ def migrations_status
46
+ db_list = DataMigrate::RailsHelper.data_schema_migration.normalized_versions
47
+
48
+ file_list = migration_files.map do |file|
49
+ version, name, scope = parse_migration_filename(file)
50
+ raise ActiveRecord::IllegalMigrationNameError.new(file) unless version
51
+ version = DataMigrate::RailsHelper.schema_migration.normalize_migration_number(version)
52
+ status = db_list.delete(version) ? "up" : "down"
53
+ [status, version, (name + scope).humanize]
54
+ end.compact
55
+
56
+ db_list.map! do |version|
57
+ ["up", version, "********** NO FILE **********"]
58
+ end
59
+
60
+ (db_list + file_list).sort_by { |_, version, _| version }
61
+ end
62
+
63
+ private
64
+
65
+ def get_all_versions
66
+ if DataMigrate::RailsHelper.data_schema_migration.table_exists?
67
+ DataMigrate::RailsHelper.data_schema_migration.normalized_versions.map(&:to_i)
68
+ else
69
+ []
70
+ end
71
+ end
72
+
73
+ def move(direction, steps)
74
+ migrator = DataMigrate::RailsHelper.data_migrator(direction, migrations)
75
+
76
+ if current_version != 0 && !migrator.current_migration
77
+ raise ActiveRecord::UnknownMigrationVersionError.new(current_version)
78
+ end
79
+
80
+ start_index =
81
+ if current_version.zero?
82
+ 0
83
+ else
84
+ migrator.migrations.index(migrator.current_migration)
85
+ end
86
+
87
+ finish = migrator.migrations[start_index + steps]
88
+ version = finish ? finish.version : 0
89
+ send(direction, version)
90
+ end
91
+
92
+ end
93
+ end