data_migrate 3.5.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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