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
@@ -0,0 +1,91 @@
1
+ module DataMigrate
2
+ class RailsHelper
3
+ class << self
4
+ def rails_version_equal_to_or_higher_than_7_2
5
+ return @equal_to_or_higher_than_7_2 if defined?(@equal_to_or_higher_than_7_2)
6
+
7
+ @equal_to_or_higher_than_7_2 = Gem::Dependency.new("railties", ">= 7.2.0.alpha").match?("railties", Gem.loaded_specs["railties"].version, true)
8
+ end
9
+
10
+ def rails_version_equal_to_or_higher_than_7_1
11
+ return @equal_to_or_higher_than_7_1 if defined?(@equal_to_or_higher_than_7_1)
12
+
13
+ @equal_to_or_higher_than_7_1 = Gem::Dependency.new("railties", ">= 7.1.0.alpha").match?("railties", Gem.loaded_specs["railties"].version, true)
14
+ end
15
+
16
+ def rails_version_equal_to_or_higher_than_7_0
17
+ return @rails_version_equal_to_or_higher_than_7_0 if defined?(@rails_version_equal_to_or_higher_than_7_0)
18
+
19
+ @rails_version_equal_to_or_higher_than_7_0 = Gem::Dependency.new("railties", ">= 7.0").match?("railties", Gem.loaded_specs["railties"].version, true)
20
+ end
21
+
22
+ def internal_metadata
23
+ if rails_version_equal_to_or_higher_than_7_2
24
+ ActiveRecord::Base.connection_pool.internal_metadata
25
+ elsif rails_version_equal_to_or_higher_than_7_1
26
+ ActiveRecord::Base.connection.internal_metadata
27
+ else
28
+ ActiveRecord::InternalMetadata
29
+ end
30
+ end
31
+
32
+ def schema_migration
33
+ if rails_version_equal_to_or_higher_than_7_2
34
+ ActiveRecord::Base.connection_pool.schema_migration
35
+ elsif rails_version_equal_to_or_higher_than_7_1
36
+ ActiveRecord::Base.connection.schema_migration
37
+ else
38
+ ActiveRecord::SchemaMigration
39
+ end
40
+ end
41
+
42
+ def schema_migration_versions
43
+ if rails_version_equal_to_or_higher_than_7_1
44
+ schema_migration.versions
45
+ else
46
+ schema_migration.all.pluck(:version)
47
+ end
48
+ end
49
+
50
+ def schema_create_version(version)
51
+ if rails_version_equal_to_or_higher_than_7_1
52
+ schema_migration.create_version(version)
53
+ else
54
+ schema_migration.create(version: version)
55
+ end
56
+ end
57
+
58
+ def data_schema_delete_version(version)
59
+ if rails_version_equal_to_or_higher_than_7_1
60
+ data_schema_migration.delete_version(version)
61
+ else
62
+ data_schema_migration.where(version: version.to_s).delete_all
63
+ end
64
+ end
65
+
66
+ def data_schema_migration
67
+ if rails_version_equal_to_or_higher_than_7_2
68
+ DataMigrate::DataSchemaMigration.new(ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool)
69
+ elsif rails_version_equal_to_or_higher_than_7_1
70
+ DataMigrate::DataSchemaMigration.new(ActiveRecord::Tasks::DatabaseTasks.migration_connection)
71
+ else
72
+ DataMigrate::DataSchemaMigration
73
+ end
74
+ end
75
+
76
+ def data_migrator(
77
+ direction,
78
+ migrations,
79
+ schema_migration = DataMigrate::RailsHelper.schema_migration,
80
+ internal_metadata = DataMigrate::RailsHelper.internal_metadata,
81
+ target_version = nil
82
+ )
83
+ if rails_version_equal_to_or_higher_than_7_1
84
+ DataMigrate::DataMigrator.new(direction, migrations, schema_migration, internal_metadata, target_version)
85
+ else
86
+ DataMigrate::DataMigrator.new(direction, migrations, schema_migration, target_version)
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DataMigrate
4
+ ##
5
+ # Provides the capability to write the current data schema version to
6
+ # the data_schema file Based on ActiveRecord::SchemaDumper
7
+ class SchemaDumper
8
+ private_class_method :new
9
+
10
+ class << self
11
+ def dump(connection = ActiveRecord::Base.connection, stream = $stdout)
12
+ new(connection).dump(stream)
13
+ stream
14
+ end
15
+ end
16
+
17
+ def dump(stream)
18
+ define_params = @version ? "version: #{@version}" : ""
19
+
20
+ stream.puts "DataMigrate::Data.define(#{define_params})"
21
+
22
+ stream
23
+ end
24
+
25
+ private
26
+
27
+ def initialize(connection)
28
+ @connection = connection
29
+ all_versions = DataMigrate::RailsHelper.data_schema_migration.normalized_versions
30
+
31
+ @version = begin
32
+ all_versions.max
33
+ rescue StandardError
34
+ 0
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DataMigrate
4
+ # Helper class to getting access to db schema
5
+ # to allow data/schema combiation tasks
6
+ class SchemaMigration
7
+ def self.pending_schema_migrations
8
+ all_migrations = DataMigrate::MigrationContext.new(migrations_paths).migrations
9
+ sort_migrations(
10
+ ActiveRecord::Migrator.new(:up, all_migrations, DataMigrate::RailsHelper.schema_migration, DataMigrate::RailsHelper.internal_metadata).
11
+ pending_migrations.
12
+ map {|m| { version: m.version, kind: :schema }}
13
+ )
14
+ end
15
+
16
+ def self.run(direction, migration_paths, version)
17
+ ActiveRecord::MigrationContext.new(migration_paths, DataMigrate::RailsHelper.schema_migration).run(direction, version)
18
+ end
19
+
20
+ def self.sort_migrations(set1, set2 = nil)
21
+ migrations = set1 + (set2 || [])
22
+ migrations.sort {|a, b| sort_string(a) <=> sort_string(b)}
23
+ end
24
+
25
+ def self.migrations_paths
26
+ spec_name = DataMigrate.config.spec_name
27
+ # The positional argument true is to include pre-release versions, such as 7.1.0.alpha
28
+ if spec_name && Gem::Dependency.new("railties", ">= 7.0").match?("railties", Gem.loaded_specs["railties"].version, true)
29
+ ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: spec_name).migrations_paths
30
+ elsif spec_name && Gem::Dependency.new("railties", "~> 6.1").match?("railties", Gem.loaded_specs["railties"].version)
31
+ ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name).migrations_paths
32
+ else
33
+ Rails.application.config.paths["db/migrate"].to_a
34
+ end
35
+ end
36
+
37
+ def self.sort_string(migration)
38
+ "#{migration[:version]}_#{migration[:kind] == :data ? 1 : 0}"
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DataMigrate
4
+ class StatusService
5
+ class << self
6
+ def dump(connection = ActiveRecord::Base.connection, stream = $stdout)
7
+ new(connection).dump(stream)
8
+ stream
9
+ end
10
+ end
11
+
12
+ def initialize(connection)
13
+ @connection = connection
14
+ end
15
+
16
+ def root_folder
17
+ Rails.root
18
+ end
19
+
20
+ def dump(stream)
21
+ output(stream)
22
+ end
23
+
24
+ private
25
+
26
+ def table_name
27
+ DataMigrate::RailsHelper.data_schema_migration.table_name
28
+ end
29
+
30
+ def output(stream)
31
+ unless DataMigrate::RailsHelper.data_schema_migration.table_exists?
32
+ stream.puts "Data migrations table does not exist yet."
33
+ return
34
+ end
35
+
36
+ # output
37
+ stream.puts "\ndatabase: #{database_name}\n\n"
38
+ stream.puts "#{"Status".center(8)} #{"Migration ID".ljust(14)} Migration Name"
39
+ stream.puts "-" * 50
40
+ db_list.each do |status, version, name|
41
+ stream.puts "#{status.center(8)} #{version.ljust(14)} #{name}"
42
+ end
43
+ stream.puts
44
+ end
45
+
46
+ def database_name
47
+ if Gem::Dependency.new("railties", "~> 7.0").match?("railties", Gem.loaded_specs["railties"].version)
48
+ ActiveRecord::Base.connection_db_config.configuration_hash[:database]
49
+ elsif Gem::Dependency.new("railties", "~> 6.1").match?("railties", Gem.loaded_specs["railties"].version)
50
+ ActiveRecord::Base.connection_config[:database]
51
+ end
52
+ end
53
+
54
+ def db_list
55
+ DataMigrate::DataMigrator.migrations_status
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DataMigrate
4
+ module Tasks
5
+ module DataMigrateTasks
6
+ extend self
7
+
8
+ def migrations_paths
9
+ @migrations_paths ||= Array.wrap(DataMigrate.config.data_migrations_path)
10
+ end
11
+
12
+ def dump
13
+ if dump_schema_after_migration?
14
+ filename = DataMigrate::DatabaseTasks.schema_file
15
+ ActiveRecord::Base.establish_connection(DataMigrate.config.db_configuration) if DataMigrate.config.db_configuration
16
+ File.open(filename, "w:utf-8") do |file|
17
+ DataMigrate::SchemaDumper.dump(ActiveRecord::Base.connection, file)
18
+ end
19
+ end
20
+ end
21
+
22
+ def migrate
23
+ target_version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
24
+
25
+ DataMigrate::DataMigrator.create_data_schema_table
26
+ DataMigrate::MigrationContext.new(migrations_paths).migrate(target_version)
27
+ end
28
+
29
+ def abort_if_pending_migrations(migrations, message)
30
+ if migrations.any?
31
+ puts "You have #{migrations.size} pending #{'migration'.pluralize(migrations.size)}:"
32
+ migrations.each do |pending_migration|
33
+ puts " %4d %s" % [pending_migration[:version], pending_migration[:name]]
34
+ end
35
+ abort message
36
+ end
37
+ end
38
+
39
+ def dump_schema_after_migration?
40
+ if ActiveRecord.respond_to?(:dump_schema_after_migration)
41
+ ActiveRecord.dump_schema_after_migration
42
+ else
43
+ ActiveRecord::Base.dump_schema_after_migration
44
+ end
45
+ end
46
+
47
+ def status
48
+ DataMigrate::StatusService.dump
49
+ end
50
+
51
+ def status_with_schema
52
+ db_list_data = ActiveRecord::Base.connection.select_values(
53
+ "SELECT version FROM #{DataMigrate::RailsHelper.data_schema_migration.table_name}"
54
+ )
55
+ db_list_schema = DataMigrate::RailsHelper.schema_migration_versions
56
+ file_list = []
57
+
58
+ migrations_paths.each do |path|
59
+ Dir.foreach(File.join(Rails.root, path)) do |file|
60
+ # only files matching "20091231235959_some_name.rb" pattern
61
+ if match_data = /(\d{14})_(.+)\.rb/.match(file)
62
+ status = db_list_data.delete(match_data[1]) ? 'up' : 'down'
63
+ file_list << [status, match_data[1], match_data[2], 'data']
64
+ end
65
+ end
66
+ end
67
+
68
+ DataMigrate::SchemaMigration.migrations_paths.map do |path|
69
+ Dir.children(path) if Dir.exist?(path)
70
+ end.flatten.compact.each do |file|
71
+ # only files matching "20091231235959_some_name.rb" pattern
72
+ if match_data = /(\d{14})_(.+)\.rb/.match(file)
73
+ status = db_list_schema.delete(match_data[1]) ? 'up' : 'down'
74
+ file_list << [status, match_data[1], match_data[2], 'schema']
75
+ end
76
+ end
77
+
78
+ file_list.sort!{|a,b| "#{a[1]}_#{a[3] == 'data' ? 1 : 0}" <=> "#{b[1]}_#{b[3] == 'data' ? 1 : 0}" }
79
+
80
+ # output
81
+ puts "\ndatabase: #{database_name}\n\n"
82
+ puts "#{"Status".center(8)} #{"Type".center(8)} #{"Migration ID".ljust(14)} Migration Name"
83
+ puts "-" * 60
84
+ file_list.each do |file|
85
+ puts "#{file[0].center(8)} #{file[3].center(8)} #{file[1].ljust(14)} #{file[2].humanize}"
86
+ end
87
+ db_list_schema.each do |version|
88
+ puts "#{'up'.center(8)} #{version.ljust(14)} *** NO SCHEMA FILE ***"
89
+ end
90
+ db_list_data.each do |version|
91
+ puts "#{'up'.center(8)} #{version.ljust(14)} *** NO DATA FILE ***"
92
+ end
93
+ puts
94
+ end
95
+
96
+ private
97
+
98
+ def database_name
99
+ if Gem::Dependency.new("railties", "~> 7.0").match?("railties", Gem.loaded_specs["railties"].version)
100
+ ActiveRecord::Base.connection_db_config.database
101
+ elsif Gem::Dependency.new("railties", "~> 6.1").match?("railties", Gem.loaded_specs["railties"].version)
102
+ ActiveRecord::Base.connection_config[:database]
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -1,3 +1,3 @@
1
1
  module DataMigrate
2
- VERSION = '3.2.0'.freeze
2
+ VERSION = "11.3.0".freeze
3
3
  end
data/lib/data_migrate.rb CHANGED
@@ -1,8 +1,21 @@
1
- require File.join(File.dirname(__FILE__), 'data_migrate', 'data_migrator')
2
- require File.join(File.dirname(__FILE__), 'data_migrate', 'data_schema_migration')
3
- if Rails::VERSION::MAJOR >= 5
4
- require File.join(File.dirname(__FILE__), 'data_migrate', 'migration_five')
5
- else
6
- require File.join(File.dirname(__FILE__), 'data_migrate', 'migration')
1
+ # frozen_string_literal: true
2
+
3
+ require File.join(File.dirname(__FILE__), "data_migrate", "rails_helper")
4
+ require File.join(File.dirname(__FILE__), "data_migrate", "data_migrator")
5
+ require File.join(File.dirname(__FILE__), "data_migrate", "data_schema_migration")
6
+ require File.join(File.dirname(__FILE__), "data_migrate", "data_schema")
7
+ require File.join(File.dirname(__FILE__), "data_migrate", "database_tasks")
8
+ require File.join(File.dirname(__FILE__), "data_migrate", "schema_dumper")
9
+ require File.join(File.dirname(__FILE__), "data_migrate", "status_service")
10
+ require File.join(File.dirname(__FILE__), "data_migrate", "migration_context")
11
+ require File.join(File.dirname(__FILE__), "data_migrate", "railtie")
12
+ require File.join(File.dirname(__FILE__), "data_migrate", "tasks/data_migrate_tasks")
13
+ require File.join(File.dirname(__FILE__), "data_migrate", "config")
14
+ require File.join(File.dirname(__FILE__), "data_migrate", "schema_migration")
15
+ require File.join(File.dirname(__FILE__), "data_migrate", "database_configurations_wrapper")
16
+
17
+ module DataMigrate
18
+ def self.root
19
+ File.dirname(__FILE__)
20
+ end
7
21
  end
8
- require File.join(File.dirname(__FILE__), 'data_migrate', 'railtie')
@@ -1,9 +1,22 @@
1
1
  require 'rails/generators/named_base'
2
+
2
3
  module DataMigrate
3
4
  module Generators
4
5
  class DataMigrationGenerator < Rails::Generators::NamedBase #:nodoc:
5
- def self.source_root
6
- @_data_migrate_source_root ||= File.expand_path(File.join(File.dirname(__FILE__), generator_name, 'templates'))
6
+ class << self
7
+ def source_root
8
+ build_data_migrate_source_root
9
+ end
10
+
11
+ private
12
+
13
+ def build_data_migrate_source_root
14
+ if DataMigrate.config.data_template_path == DataMigrate::Config::DEFAULT_DATA_TEMPLATE_PATH
15
+ File.expand_path(File.join(File.dirname(__FILE__), generator_name, 'templates'))
16
+ else
17
+ File.expand_path(File.dirname(DataMigrate.config.data_template_path))
18
+ end
19
+ end
7
20
  end
8
21
  end
9
22
  end
@@ -1,32 +1,24 @@
1
- require 'generators/data_migrate'
2
- require 'rails/generators'
3
- require 'rails/generators/migration'
1
+ require "generators/data_migrate"
2
+ require "rails/generators"
3
+ require "rails/generators/active_record/migration"
4
+ require "rails/generators/migration"
5
+ require "data_migrate/config"
4
6
 
5
7
  module DataMigrate
6
8
  module Generators
7
9
  class DataMigrationGenerator < Rails::Generators::NamedBase
8
10
  namespace "data_migration"
9
- include Rails::Generators::Migration
11
+ include ActiveRecord::Generators::Migration
10
12
 
11
- argument :attributes, type: :array, default: [], banner: 'field:type field:type'
13
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
12
14
 
13
15
  def create_data_migration
14
16
  set_local_assigns!
15
- migration_template 'data_migration.rb', "db/data/#{file_name}.rb"
17
+ migration_template template_path, data_migrations_file_path
16
18
  end
17
19
 
18
20
  protected
19
21
 
20
- attr_reader :migration_action
21
-
22
- def self.next_migration_number(dirname)
23
- if ActiveRecord::Base.timestamped_migrations
24
- Time.new.utc.strftime("%Y%m%d%H%M%S")
25
- else
26
- "%.3d" % (current_migration_number(dirname) + 1)
27
- end
28
- end
29
-
30
22
  def set_local_assigns!
31
23
  if file_name =~ /^(add|remove)_.*_(?:to|from)_(.*)/
32
24
  @migration_action = $1
@@ -34,12 +26,21 @@ module DataMigrate
34
26
  end
35
27
  end
36
28
 
29
+ def template_path
30
+ DataMigrate.config.data_template_path
31
+ end
32
+
37
33
  def migration_base_class_name
38
- if ActiveRecord.version >= Gem::Version.new('5.0')
39
- "ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]"
40
- else
41
- 'ActiveRecord::Migration'
42
- end
34
+ "ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]"
35
+ end
36
+
37
+ def data_migrations_file_path
38
+ File.join(data_migrations_path, "#{file_name}.rb")
39
+ end
40
+
41
+ # Use the first path in the data_migrations_path as the target directory
42
+ def data_migrations_path
43
+ Array.wrap(DataMigrate.config.data_migrations_path).first
43
44
  end
44
45
  end
45
46
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class <%= migration_class_name %> < <%= migration_base_class_name %>
2
- def self.up
4
+ def up
3
5
  end
4
6
 
5
- def self.down
7
+ def down
6
8
  raise ActiveRecord::IrreversibleMigration
7
9
  end
8
10
  end