strong_migrations 0.6.5 → 0.7.1
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/CHANGELOG.md +28 -0
- data/LICENSE.txt +1 -1
- data/README.md +189 -138
- data/lib/generators/strong_migrations/install_generator.rb +28 -0
- data/lib/generators/strong_migrations/templates/initializer.rb.tt +22 -0
- data/lib/strong_migrations.rb +43 -50
- data/lib/strong_migrations/checker.rb +139 -29
- data/lib/strong_migrations/railtie.rb +0 -4
- data/lib/strong_migrations/version.rb +1 -1
- data/lib/tasks/strong_migrations.rake +0 -6
- metadata +4 -3
- data/lib/strong_migrations/migration_helpers.rb +0 -117
@@ -5,10 +5,6 @@ module StrongMigrations
|
|
5
5
|
class Railtie < Rails::Railtie
|
6
6
|
rake_tasks do
|
7
7
|
load "tasks/strong_migrations.rake"
|
8
|
-
|
9
|
-
["db:drop", "db:reset", "db:schema:load", "db:structure:load"].each do |t|
|
10
|
-
Rake::Task[t].enhance ["strong_migrations:safety_assured"]
|
11
|
-
end
|
12
8
|
end
|
13
9
|
end
|
14
10
|
end
|
@@ -1,10 +1,4 @@
|
|
1
|
-
# https://nithinbekal.com/posts/safe-rake-tasks
|
2
|
-
|
3
1
|
namespace :strong_migrations do
|
4
|
-
task safety_assured: :environment do
|
5
|
-
raise "Set SAFETY_ASSURED=1 to run this task in production" if Rails.env.production? && !ENV["SAFETY_ASSURED"]
|
6
|
-
end
|
7
|
-
|
8
2
|
# https://www.pgrs.net/2008/03/13/alphabetize-schema-rb-columns/
|
9
3
|
task :alphabetize_columns do
|
10
4
|
$stderr.puts "Dumping schema"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: strong_migrations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2020-
|
13
|
+
date: 2020-07-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -108,12 +108,13 @@ files:
|
|
108
108
|
- CONTRIBUTING.md
|
109
109
|
- LICENSE.txt
|
110
110
|
- README.md
|
111
|
+
- lib/generators/strong_migrations/install_generator.rb
|
112
|
+
- lib/generators/strong_migrations/templates/initializer.rb.tt
|
111
113
|
- lib/strong_migrations.rb
|
112
114
|
- lib/strong_migrations/alphabetize_columns.rb
|
113
115
|
- lib/strong_migrations/checker.rb
|
114
116
|
- lib/strong_migrations/database_tasks.rb
|
115
117
|
- lib/strong_migrations/migration.rb
|
116
|
-
- lib/strong_migrations/migration_helpers.rb
|
117
118
|
- lib/strong_migrations/railtie.rb
|
118
119
|
- lib/strong_migrations/version.rb
|
119
120
|
- lib/tasks/strong_migrations.rake
|
@@ -1,117 +0,0 @@
|
|
1
|
-
module StrongMigrations
|
2
|
-
module MigrationHelpers
|
3
|
-
def add_foreign_key_safely(from_table, to_table, **options)
|
4
|
-
ensure_postgresql(__method__)
|
5
|
-
ensure_not_in_transaction(__method__)
|
6
|
-
|
7
|
-
reversible do |dir|
|
8
|
-
dir.up do
|
9
|
-
if ActiveRecord::VERSION::STRING >= "5.2"
|
10
|
-
add_foreign_key(from_table, to_table, options.merge(validate: false))
|
11
|
-
validate_foreign_key(from_table, to_table)
|
12
|
-
else
|
13
|
-
options = connection.foreign_key_options(from_table, to_table, options)
|
14
|
-
fk_name, column, primary_key = options.values_at(:name, :column, :primary_key)
|
15
|
-
primary_key ||= "id"
|
16
|
-
|
17
|
-
statement = ["ALTER TABLE %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)"]
|
18
|
-
statement << on_delete_update_statement(:delete, options[:on_delete]) if options[:on_delete]
|
19
|
-
statement << on_delete_update_statement(:update, options[:on_update]) if options[:on_update]
|
20
|
-
statement << "NOT VALID"
|
21
|
-
|
22
|
-
safety_assured do
|
23
|
-
execute quote_identifiers(statement.join(" "), [from_table, fk_name, column, to_table, primary_key])
|
24
|
-
execute quote_identifiers("ALTER TABLE %s VALIDATE CONSTRAINT %s", [from_table, fk_name])
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
dir.down do
|
30
|
-
remove_foreign_key(from_table, to_table)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def add_null_constraint_safely(table_name, column_name, name: nil)
|
36
|
-
ensure_postgresql(__method__)
|
37
|
-
ensure_not_in_transaction(__method__)
|
38
|
-
|
39
|
-
reversible do |dir|
|
40
|
-
dir.up do
|
41
|
-
name ||= null_constraint_name(table_name, column_name)
|
42
|
-
|
43
|
-
safety_assured do
|
44
|
-
execute quote_identifiers("ALTER TABLE %s ADD CONSTRAINT %s CHECK (%s IS NOT NULL) NOT VALID", [table_name, name, column_name])
|
45
|
-
execute quote_identifiers("ALTER TABLE %s VALIDATE CONSTRAINT %s", [table_name, name])
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
dir.down do
|
50
|
-
remove_null_constraint_safely(table_name, column_name)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# removing constraints is safe, but this method is safe to reverse as well
|
56
|
-
def remove_null_constraint_safely(table_name, column_name, name: nil)
|
57
|
-
# could also ensure in transaction so it can be reversed
|
58
|
-
# but that's more of a concern for a reversible migrations check
|
59
|
-
ensure_postgresql(__method__)
|
60
|
-
|
61
|
-
reversible do |dir|
|
62
|
-
dir.up do
|
63
|
-
name ||= null_constraint_name(table_name, column_name)
|
64
|
-
|
65
|
-
safety_assured do
|
66
|
-
execute quote_identifiers("ALTER TABLE %s DROP CONSTRAINT %s", [table_name, name])
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
dir.down do
|
71
|
-
add_null_constraint_safely(table_name, column_name)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
private
|
77
|
-
|
78
|
-
def ensure_postgresql(method_name)
|
79
|
-
raise StrongMigrations::Error, "`#{method_name}` is intended for Postgres only" unless postgresql?
|
80
|
-
end
|
81
|
-
|
82
|
-
def postgresql?
|
83
|
-
%w(PostgreSQL PostGIS).include?(connection.adapter_name)
|
84
|
-
end
|
85
|
-
|
86
|
-
def ensure_not_in_transaction(method_name)
|
87
|
-
if connection.transaction_open?
|
88
|
-
raise StrongMigrations::Error, "Cannot run `#{method_name}` inside a transaction. Use `disable_ddl_transaction` to disable the transaction."
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# match https://github.com/nullobject/rein
|
93
|
-
def null_constraint_name(table_name, column_name)
|
94
|
-
"#{table_name}_#{column_name}_null"
|
95
|
-
end
|
96
|
-
|
97
|
-
def on_delete_update_statement(delete_or_update, action)
|
98
|
-
on = delete_or_update.to_s.upcase
|
99
|
-
|
100
|
-
case action
|
101
|
-
when :nullify
|
102
|
-
"ON #{on} SET NULL"
|
103
|
-
when :cascade
|
104
|
-
"ON #{on} CASCADE"
|
105
|
-
when :restrict
|
106
|
-
"ON #{on} RESTRICT"
|
107
|
-
else
|
108
|
-
# same error message as Active Record
|
109
|
-
raise "'#{action}' is not supported for :on_update or :on_delete.\nSupported values are: :nullify, :cascade, :restrict"
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
def quote_identifiers(statement, identifiers)
|
114
|
-
statement % identifiers.map { |v| connection.quote_table_name(v) }
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|