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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.ruby-style.yml +2 -0
- data/.travis.yml +1 -1
- data/Appraisals +5 -5
- data/Changelog.md +6 -0
- data/Gemfile.rails5.2 +5 -0
- data/README.md +4 -10
- data/data_migrate.gemspec +1 -1
- data/gemfiles/rails_5.2.gemfile +7 -0
- data/lib/data_migrate.rb +19 -4
- data/lib/data_migrate/data_migrator.rb +5 -0
- data/lib/data_migrate/data_migrator_five.rb +84 -0
- data/lib/data_migrate/data_schema.rb +29 -9
- data/lib/data_migrate/data_schema_migration.rb +1 -0
- data/lib/data_migrate/database_tasks.rb +69 -0
- data/lib/data_migrate/migration.rb +1 -1
- data/lib/data_migrate/migration_context.rb +90 -0
- data/lib/data_migrate/schema_dumper.rb +1 -3
- data/lib/data_migrate/schema_migration.rb +31 -0
- data/lib/data_migrate/schema_migration_five.rb +31 -0
- data/lib/data_migrate/status_service.rb +1 -1
- data/lib/data_migrate/status_service_five.rb +48 -0
- data/lib/data_migrate/tasks/data_migrate_tasks.rb +25 -0
- data/lib/data_migrate/version.rb +1 -1
- data/lib/generators/data_migration/data_migration_generator.rb +3 -1
- data/spec/data_migrate/data_migrator_spec.rb +1 -13
- data/spec/data_migrate/{data_schema_spec.rb → data_spec.rb} +7 -5
- data/spec/data_migrate/database_tasks_spec.rb +96 -0
- data/spec/data_migrate/migration_context_spec.rb +107 -0
- data/spec/data_migrate/schema_dumper_spec.rb +5 -3
- data/spec/data_migrate/schema_migration_spec.rb +69 -0
- data/spec/data_migrate/status_service_spec.rb +15 -18
- data/spec/data_migrate/tasks/data_migrate_tasks_spec.rb +50 -0
- data/spec/db/4.2/20091231235959_some_name.rb +9 -0
- data/spec/db/4.2/20171231235959_super_update.rb +9 -0
- data/spec/db/5.0/20091231235959_some_name.rb +9 -0
- data/spec/db/5.0/20171231235959_super_update.rb +9 -0
- data/spec/db/data/20091231235959_some_name.rb +9 -0
- data/spec/db/data/20171231235959_super_update.rb +9 -0
- data/spec/db/migrate/4.2/20131111111111_late_migration.rb +9 -0
- data/spec/db/migrate/4.2/20202020202011_db_migration.rb +9 -0
- data/spec/db/migrate/5.0/20131111111111_late_migration.rb +9 -0
- data/spec/db/migrate/5.0/20202020202011_db_migration.rb +9 -0
- data/spec/db/migrate/5.2/20131111111111_late_migration.rb +9 -0
- data/spec/db/migrate/5.2/20202020202011_db_migration.rb +9 -0
- data/spec/spec_helper.rb +4 -0
- metadata +41 -7
@@ -30,9 +30,7 @@ module DataMigrate
|
|
30
30
|
|
31
31
|
def initialize(connection)
|
32
32
|
@connection = connection
|
33
|
-
all_versions =
|
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
|
@@ -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
|
data/lib/data_migrate/version.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
31
|
-
to receive(:db_config) { db_config }
|
32
|
+
allow(DataMigrate::DataMigrator).
|
33
|
+
to receive(:db_config) { db_config }
|
32
34
|
ActiveRecord::Base.establish_connection(db_config)
|
33
|
-
ActiveRecord::
|
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::
|
71
|
+
FROM #{DataMigrate::DataSchemaMigration.table_name}
|
70
72
|
SQL
|
71
73
|
|
72
74
|
db_list_data = ActiveRecord::Base.connection.
|
73
|
-
|
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
|