data_migrate 3.5.0 → 4.0.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.ruby-style.yml +2 -0
  4. data/.travis.yml +1 -1
  5. data/Appraisals +5 -5
  6. data/Changelog.md +6 -0
  7. data/Gemfile.rails5.2 +5 -0
  8. data/README.md +4 -10
  9. data/data_migrate.gemspec +1 -1
  10. data/gemfiles/rails_5.2.gemfile +7 -0
  11. data/lib/data_migrate.rb +19 -4
  12. data/lib/data_migrate/data_migrator.rb +5 -0
  13. data/lib/data_migrate/data_migrator_five.rb +84 -0
  14. data/lib/data_migrate/data_schema.rb +29 -9
  15. data/lib/data_migrate/data_schema_migration.rb +1 -0
  16. data/lib/data_migrate/database_tasks.rb +69 -0
  17. data/lib/data_migrate/migration.rb +1 -1
  18. data/lib/data_migrate/migration_context.rb +90 -0
  19. data/lib/data_migrate/schema_dumper.rb +1 -3
  20. data/lib/data_migrate/schema_migration.rb +31 -0
  21. data/lib/data_migrate/schema_migration_five.rb +31 -0
  22. data/lib/data_migrate/status_service.rb +1 -1
  23. data/lib/data_migrate/status_service_five.rb +48 -0
  24. data/lib/data_migrate/tasks/data_migrate_tasks.rb +25 -0
  25. data/lib/data_migrate/version.rb +1 -1
  26. data/lib/generators/data_migration/data_migration_generator.rb +3 -1
  27. data/spec/data_migrate/data_migrator_spec.rb +1 -13
  28. data/spec/data_migrate/{data_schema_spec.rb → data_spec.rb} +7 -5
  29. data/spec/data_migrate/database_tasks_spec.rb +96 -0
  30. data/spec/data_migrate/migration_context_spec.rb +107 -0
  31. data/spec/data_migrate/schema_dumper_spec.rb +5 -3
  32. data/spec/data_migrate/schema_migration_spec.rb +69 -0
  33. data/spec/data_migrate/status_service_spec.rb +15 -18
  34. data/spec/data_migrate/tasks/data_migrate_tasks_spec.rb +50 -0
  35. data/spec/db/4.2/20091231235959_some_name.rb +9 -0
  36. data/spec/db/4.2/20171231235959_super_update.rb +9 -0
  37. data/spec/db/5.0/20091231235959_some_name.rb +9 -0
  38. data/spec/db/5.0/20171231235959_super_update.rb +9 -0
  39. data/spec/db/data/20091231235959_some_name.rb +9 -0
  40. data/spec/db/data/20171231235959_super_update.rb +9 -0
  41. data/spec/db/migrate/4.2/20131111111111_late_migration.rb +9 -0
  42. data/spec/db/migrate/4.2/20202020202011_db_migration.rb +9 -0
  43. data/spec/db/migrate/5.0/20131111111111_late_migration.rb +9 -0
  44. data/spec/db/migrate/5.0/20202020202011_db_migration.rb +9 -0
  45. data/spec/db/migrate/5.2/20131111111111_late_migration.rb +9 -0
  46. data/spec/db/migrate/5.2/20202020202011_db_migration.rb +9 -0
  47. data/spec/spec_helper.rb +4 -0
  48. metadata +41 -7
@@ -30,9 +30,7 @@ module DataMigrate
30
30
 
31
31
  def initialize(connection)
32
32
  @connection = connection
33
- all_versions = DataMigrate::DataSchemaMigration.all.map do |x|
34
- x.version.to_i
35
- end
33
+ all_versions = DataSchemaMigration.normalized_versions
36
34
 
37
35
  @version = begin
38
36
  all_versions.max
@@ -0,0 +1,31 @@
1
+ module DataMigrate
2
+ # Helper class to getting access to db schema
3
+ # to allow data/schema combiation tasks
4
+ class SchemaMigration
5
+ def self.pending_schema_migrations
6
+ all_migrations = DataMigrate::DataMigrator.migrations(migrations_paths)
7
+ sort_migrations(
8
+ ActiveRecord::Migrator.new(:up, all_migrations).
9
+ pending_migrations.
10
+ map {|m| { version: m.version, kind: :schema }}
11
+ )
12
+ end
13
+
14
+ def self.run(direction, migration_paths, version)
15
+ ActiveRecord::Migrator.run(direction, migration_paths, version)
16
+ end
17
+
18
+ def self.sort_migrations(set1, set2 = nil)
19
+ migrations = set1 + (set2 || [])
20
+ migrations.sort {|a, b| sort_string(a) <=> sort_string(b)}
21
+ end
22
+
23
+ def self.migrations_paths
24
+ Rails.application.config.paths["db/migrate"].to_a
25
+ end
26
+
27
+ def self.sort_string(migration)
28
+ "#{migration[:version]}_#{migration[:kind] == :data ? 1 : 0}"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ module DataMigrate
2
+ # Helper class to getting access to db schema
3
+ # to allow data/schema combiation tasks
4
+ class SchemaMigration
5
+ def self.pending_schema_migrations
6
+ all_migrations = ActiveRecord::MigrationContext.new(migrations_paths).migrations
7
+ sort_migrations(
8
+ ActiveRecord::Migrator.new(:up, all_migrations).
9
+ pending_migrations.
10
+ map {|m| { version: m.version, kind: :schema }}
11
+ )
12
+ end
13
+
14
+ def self.run(direction, migration_paths, version)
15
+ ActiveRecord::MigrationContext.new(migration_paths).run(direction, version)
16
+ end
17
+
18
+ def self.sort_migrations(set1, set2 = nil)
19
+ migrations = set1 + (set2 || [])
20
+ migrations.sort {|a, b| sort_string(a) <=> sort_string(b)}
21
+ end
22
+
23
+ def self.migrations_paths
24
+ Rails.application.config.paths["db/migrate"].to_a
25
+ end
26
+
27
+ def self.sort_string(migration)
28
+ "#{migration[:version]}_#{migration[:kind] == :data ? 1 : 0}"
29
+ end
30
+ end
31
+ end
@@ -45,7 +45,7 @@ module DataMigrate
45
45
  def migration_list(db_list)
46
46
  list = []
47
47
  db_list.each do |version|
48
- list << ["up", version, "*** NO FILE ***"]
48
+ list << ["up", version, "********** NO FILE *************"]
49
49
  end
50
50
  list
51
51
  end
@@ -0,0 +1,48 @@
1
+ module DataMigrate
2
+ class StatusService
3
+ class << self
4
+ def dump(connection = ActiveRecord::Base.connection, stream = STDOUT)
5
+ new(connection).dump(stream)
6
+ stream
7
+ end
8
+ end
9
+
10
+ def initialize(connection)
11
+ @connection = connection
12
+ end
13
+
14
+ def root_folder
15
+ Rails.root
16
+ end
17
+
18
+ def dump(stream)
19
+ output(stream)
20
+ end
21
+
22
+ private
23
+
24
+ def table_name
25
+ DataMigrate::DataSchemaMigration.table_name
26
+ end
27
+
28
+ def output(stream)
29
+ unless DataMigrate::DataSchemaMigration.table_exists?
30
+ stream.puts "Data migrations table does not exist yet."
31
+ return
32
+ end
33
+
34
+ # output
35
+ stream.puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
36
+ stream.puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
37
+ stream.puts "-" * 50
38
+ db_list.each do |status, version, name|
39
+ stream.puts "#{status.center(8)} #{version.ljust(14)} #{name}"
40
+ end
41
+ stream.puts
42
+ end
43
+
44
+ def db_list
45
+ DataMigrate::DataMigrator.migrations_status
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,25 @@
1
+ module DataMigrate
2
+ module Tasks
3
+ module DataMigrateTasks
4
+ extend self
5
+ def migrations_paths
6
+ @migrations_paths ||= begin
7
+ if Rails.application && Rails.application.paths["data/migrate"]
8
+ Rails.application.paths["data/migrate"].to_a
9
+ end
10
+ end
11
+ end
12
+
13
+ def migrate
14
+ DataMigrate::DataMigrator.assure_data_schema_table
15
+ target_version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
16
+ if Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR == 2
17
+ DataMigrate::MigrationContext.new(migrations_paths).migrate(target_version)
18
+ else
19
+ paths = migrations_paths || "db/data/"
20
+ DataMigrate::DataMigrator.migrate(paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,3 +1,3 @@
1
1
  module DataMigrate
2
- VERSION = "3.5.0".freeze
2
+ VERSION = "4.0.0".freeze
3
3
  end
@@ -1,6 +1,7 @@
1
1
  require "generators/data_migrate"
2
2
  require "rails/generators"
3
3
  require "rails/generators/active_record/migration"
4
+ require "rails/generators/migration"
4
5
 
5
6
  module DataMigrate
6
7
  module Generators
@@ -8,7 +9,6 @@ module DataMigrate
8
9
  namespace "data_migration"
9
10
  include ActiveRecord::Generators::Migration
10
11
 
11
-
12
12
  argument :attributes, type: :array, default: [], banner: "field:type field:type"
13
13
 
14
14
  def create_data_migration
@@ -28,6 +28,8 @@ module DataMigrate
28
28
  def migration_base_class_name
29
29
  if ActiveRecord.version >= Gem::Version.new("5.0")
30
30
  "ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]"
31
+ elsif ActiveRecord.version >= Gem::Version.new("5.2")
32
+ "DataMigrate::MigrationContext"
31
33
  else
32
34
  "ActiveRecord::Migration"
33
35
  end
@@ -11,7 +11,7 @@ describe DataMigrate::DataMigrator do
11
11
 
12
12
  describe :assure_data_schema_table do
13
13
  before do
14
- expect(subject).to receive(:db_config) { db_config }.at_least(:once)
14
+ allow(subject).to receive(:db_config) { db_config }.at_least(:once)
15
15
  ActiveRecord::Base.establish_connection(db_config)
16
16
  end
17
17
 
@@ -30,18 +30,6 @@ describe DataMigrate::DataMigrator do
30
30
  end
31
31
  end
32
32
 
33
- describe :schema_migrations_table_name do
34
- it "returns correct table name" do
35
- expect(subject.schema_migrations_table_name).to eq("data_migrations")
36
- end
37
- end
38
-
39
- describe :migrations_path do
40
- it "returns correct migrations path" do
41
- expect(subject.migrations_path).to eq("db/data")
42
- end
43
- end
44
-
45
33
  describe :match do
46
34
  context "when the file does not match" do
47
35
  it "returns nil" do
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "spec_helper"
4
+
3
5
  describe DataMigrate::Data do
4
6
  let(:subject) { DataMigrate::Data }
5
7
  let(:db_config) do
@@ -27,10 +29,10 @@ describe DataMigrate::Data do
27
29
 
28
30
  describe :define do
29
31
  before do
30
- expect(DataMigrate::DataMigrator).
31
- to receive(:db_config) { db_config }.at_least(:once)
32
+ allow(DataMigrate::DataMigrator).
33
+ to receive(:db_config) { db_config }
32
34
  ActiveRecord::Base.establish_connection(db_config)
33
- ActiveRecord::Base.connection.initialize_schema_migrations_table
35
+ ActiveRecord::SchemaMigration.create_table
34
36
  end
35
37
 
36
38
  after do
@@ -66,11 +68,11 @@ describe DataMigrate::Data do
66
68
 
67
69
  sql_select = <<-SQL
68
70
  SELECT version
69
- FROM #{DataMigrate::DataMigrator.schema_migrations_table_name}
71
+ FROM #{DataMigrate::DataSchemaMigration.table_name}
70
72
  SQL
71
73
 
72
74
  db_list_data = ActiveRecord::Base.connection.
73
- select_values(sql_select).map(&:to_i)
75
+ select_values(sql_select).map(&:to_i)
74
76
  expect(db_list_data).to match_array(
75
77
  [fixture_file_timestamps[0], fixture_file_timestamps[1]].map(&:to_i)
76
78
  )
@@ -1,7 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "spec_helper"
4
+
3
5
  describe DataMigrate::DatabaseTasks do
4
6
  let(:subject) { DataMigrate::DatabaseTasks }
7
+ let(:migration_path) {
8
+ if Rails::VERSION::MAJOR == 5
9
+ if Rails::VERSION::MINOR == 2
10
+ "spec/db/migrate/5.2"
11
+ else
12
+ "spec/db/migrate/5.0"
13
+ end
14
+ else
15
+ "spec/db/migrate/4.2"
16
+ end
17
+ }
18
+ let(:data_migrations_path) {
19
+ if Rails::VERSION::MAJOR == 5
20
+ if Rails::VERSION::MINOR == 2
21
+ "spec/db/data"
22
+ else
23
+ "spec/db/5.0"
24
+ end
25
+ else
26
+ "spec/db/4.2"
27
+ end
28
+ }
29
+ let(:db_config) do
30
+ {
31
+ adapter: "sqlite3",
32
+ database: "spec/db/test.db"
33
+ }
34
+ end
5
35
 
6
36
  before do
7
37
  # In a normal Rails installation, db_dir would defer to
@@ -10,9 +40,75 @@ describe DataMigrate::DatabaseTasks do
10
40
  allow(subject).to receive(:db_dir).and_return("db")
11
41
  end
12
42
 
43
+ before do
44
+ allow(DataMigrate::Tasks::DataMigrateTasks).to receive(:migrations_paths) {
45
+ data_migrations_path
46
+ }
47
+ allow(DataMigrate::DataMigrator).to receive(:db_config) { db_config }
48
+ ActiveRecord::Base.establish_connection(db_config)
49
+ end
50
+
13
51
  describe :data_schema_file do
14
52
  it "returns the correct data schema file path" do
15
53
  expect(subject.data_schema_file).to eq "db/data_schema.rb"
16
54
  end
17
55
  end
56
+
57
+ context "migrations" do
58
+ after do
59
+ begin
60
+ ActiveRecord::Migration.drop_table("data_migrations")
61
+ rescue ActiveRecord::StatementInvalid
62
+ end
63
+ ActiveRecord::Migration.drop_table("schema_migrations")
64
+ end
65
+
66
+ before do
67
+ ActiveRecord::Base.establish_connection(db_config)
68
+ ActiveRecord::SchemaMigration.create_table
69
+
70
+ allow(DataMigrate::SchemaMigration).to receive(:migrations_paths) {
71
+ migration_path
72
+ }
73
+ allow(DataMigrate::DatabaseTasks).to receive(:data_migrations_path) {
74
+ data_migrations_path
75
+ }.at_least(:once)
76
+ allow(DataMigrate::DatabaseTasks).to receive(:schema_migrations_path) {
77
+ migration_path
78
+ }.at_least(:once)
79
+ end
80
+
81
+ describe :past_migrations do
82
+ it do
83
+ subject.forward
84
+ m = subject.past_migrations
85
+ expect(m.count).to eq 1
86
+ expect(m.first[:version]).to eq 20091231235959
87
+ end
88
+
89
+ it "shows nothing without any migrations" do
90
+ m = subject.past_migrations
91
+ expect(m.count).to eq 0
92
+ end
93
+ end
94
+
95
+ describe :forward do
96
+
97
+ it "run forward default amount of times" do
98
+ subject.forward
99
+ versions = DataMigrate::DataSchemaMigration.normalized_versions
100
+ expect(versions.count).to eq(1)
101
+ end
102
+
103
+ it "run forward defined number of times" do
104
+ subject.forward(2)
105
+ versions = DataMigrate::DataSchemaMigration.normalized_versions
106
+ expect(versions.count).to eq(1)
107
+ expect(versions.first).to eq "20091231235959"
108
+ versions = ActiveRecord::SchemaMigration.normalized_versions
109
+ expect(versions.count).to eq(1)
110
+ expect(versions.first).to eq "20131111111111"
111
+ end
112
+ end
113
+ end
18
114
  end
@@ -0,0 +1,107 @@
1
+ require "spec_helper"
2
+
3
+ describe DataMigrate::DataMigrator do
4
+ let(:context) {
5
+ DataMigrate::MigrationContext.new("spec/db/data")
6
+ }
7
+
8
+ before do
9
+ unless Rails::VERSION::MAJOR == 5 and
10
+ Rails::VERSION::MINOR == 2
11
+ skip("Tests are only applicable for Rails 5.2")
12
+ end
13
+ end
14
+
15
+ after do
16
+ begin
17
+ ActiveRecord::Migration.drop_table("data_migrations")
18
+ rescue StandardError
19
+ nil
20
+ end
21
+ end
22
+
23
+ let(:db_config) do
24
+ {
25
+ adapter: "sqlite3",
26
+ database: "spec/db/test.db"
27
+ }
28
+ end
29
+
30
+ describe :migrate do
31
+ before do
32
+ ActiveRecord::Base.establish_connection(db_config)
33
+ ActiveRecord::SchemaMigration.create_table
34
+ end
35
+
36
+ it "migrates existing file" do
37
+ context.migrate(nil)
38
+ context.migrations_status
39
+ versions = DataMigrate::DataSchemaMigration.normalized_versions
40
+ expect(versions.count).to eq(2)
41
+ expect(versions).to include("20091231235959")
42
+ expect(versions).to include("20171231235959")
43
+ end
44
+
45
+ it "undo migration" do
46
+ context.migrate(nil)
47
+ context.run(:down, 20171231235959)
48
+ versions = DataMigrate::DataSchemaMigration.normalized_versions
49
+ expect(versions.count).to eq(1)
50
+ expect(versions).to include("20091231235959")
51
+ end
52
+
53
+ it "does not do anything if migration is undone twice" do
54
+ context.migrate(nil)
55
+ expect {
56
+ context.run(:down, 20171231235959)
57
+ }.to output(/Undoing SuperUpdate/).to_stdout
58
+ expect {
59
+ context.run(:down, 20171231235959)
60
+ }.not_to output(/Undoing SuperUpdate/).to_stdout
61
+ end
62
+
63
+ it "runs a specific migration" do
64
+ context.run(:up, 20171231235959)
65
+ versions = DataMigrate::DataSchemaMigration.normalized_versions
66
+ expect(versions.count).to eq(1)
67
+ expect(versions).to include("20171231235959")
68
+ end
69
+
70
+ it "does not do anything if migration is ran twice" do
71
+ expect {
72
+ context.run(:up, 20171231235959)
73
+ }.to output(/Doing SuperUpdate/).to_stdout
74
+ expect {
75
+ context.run(:down, 20171231235959)
76
+ }.not_to output(/Doing SuperUpdate/).to_stdout
77
+ end
78
+
79
+ it "alerts for an invalid specific migration" do
80
+ expect {
81
+ context.run(:up, 201712312)
82
+ }.to raise_error(
83
+ ActiveRecord::UnknownMigrationVersionError,
84
+ /No migration with version number 201712312/
85
+ )
86
+ end
87
+
88
+ it "rolls back latest migration" do
89
+ context.migrate(nil)
90
+ expect {
91
+ context.rollback
92
+ }.to output(/Undoing SuperUpdate/).to_stdout
93
+ versions = DataMigrate::DataSchemaMigration.normalized_versions
94
+ expect(versions.count).to eq(1)
95
+ expect(versions).to include("20091231235959")
96
+ end
97
+
98
+ it "rolls back 2 migrations" do
99
+ context.migrate(nil)
100
+ expect {
101
+ context.rollback(2)
102
+ }.to output(/Undoing SomeName/).to_stdout
103
+ versions = DataMigrate::DataSchemaMigration.normalized_versions
104
+ expect(versions.count).to eq(0)
105
+ end
106
+ end
107
+ end