strong_migrations 1.3.0 → 1.4.4
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 +31 -0
- data/README.md +32 -12
- data/lib/strong_migrations/adapters/abstract_adapter.rb +17 -1
- data/lib/strong_migrations/adapters/mariadb_adapter.rb +3 -0
- data/lib/strong_migrations/adapters/mysql_adapter.rb +27 -7
- data/lib/strong_migrations/checker.rb +2 -0
- data/lib/strong_migrations/checks.rb +38 -15
- data/lib/strong_migrations/error_messages.rb +14 -1
- data/lib/strong_migrations/safe_methods.rb +13 -3
- data/lib/strong_migrations/schema_dumper.rb +21 -0
- data/lib/strong_migrations/version.rb +1 -1
- data/lib/strong_migrations.rb +30 -15
- data/lib/tasks/strong_migrations.rake +1 -6
- metadata +4 -4
- data/lib/strong_migrations/alphabetize_columns.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7444023bd5f0829a289ebc9d222a28f041a4e3789224438f9fd6bffa01fa6668
|
4
|
+
data.tar.gz: feb5010616cc8ef6cf36088be7a67bb0d74272cde79d0e9a0a442272bfa92d99
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0599a3fef628ec724471ef53b7ad7358831e6b638bdd0ca3b7cb79c1b416da6c044793ecca5475f5e602e8a7d1235ced3ff3fda526f31b9c4a56990c8531f9b4'
|
7
|
+
data.tar.gz: 6aac91ecb348c6a04c25511adf7df5d3e97823f6b9acdfbfd86bac50c4f5856f15fdcc271f00d0fc6f1e5d2cfdbaf3da5e056b1476aaf9b224e7df89b9737e01
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,34 @@
|
|
1
|
+
## 1.4.4 (2023-03-08)
|
2
|
+
|
3
|
+
- Fixed `add_foreign_key` with `name` and `column` options with `safe_by_default`
|
4
|
+
|
5
|
+
## 1.4.3 (2023-02-19)
|
6
|
+
|
7
|
+
- Fixed check for `change_column` to account for charset with MySQL and MariaDB
|
8
|
+
|
9
|
+
## 1.4.2 (2023-01-29)
|
10
|
+
|
11
|
+
- Added `alphabetize_schema` option
|
12
|
+
|
13
|
+
## 1.4.1 (2023-01-05)
|
14
|
+
|
15
|
+
- Added support for multiple databases to `target_version`
|
16
|
+
|
17
|
+
## 1.4.0 (2022-10-31)
|
18
|
+
|
19
|
+
- Added check for `add_exclusion_constraint`
|
20
|
+
- Added support for `RACK_ENV`
|
21
|
+
- Fixed error when `Rails` defined without `Rails.env`
|
22
|
+
- Fixed error with `change_column_null` when table does not exist
|
23
|
+
|
24
|
+
## 1.3.2 (2022-10-09)
|
25
|
+
|
26
|
+
- Improved error message for `add_column` with `default: nil` with Postgres 10
|
27
|
+
|
28
|
+
## 1.3.1 (2022-09-21)
|
29
|
+
|
30
|
+
- Fixed check for `add_column` with `default: nil` with Postgres 10
|
31
|
+
|
1
32
|
## 1.3.0 (2022-08-30)
|
2
33
|
|
3
34
|
- Added check for `add_column` with `uuid` type and volatile default value
|
data/README.md
CHANGED
@@ -74,6 +74,7 @@ Postgres-specific checks:
|
|
74
74
|
- [adding an index non-concurrently](#adding-an-index-non-concurrently)
|
75
75
|
- [adding a reference](#adding-a-reference)
|
76
76
|
- [adding a foreign key](#adding-a-foreign-key)
|
77
|
+
- [adding an exclusion constraint](#adding-an-exclusion-constraint)
|
77
78
|
- [adding a json column](#adding-a-json-column)
|
78
79
|
- [setting NOT NULL on an existing column](#setting-not-null-on-an-existing-column)
|
79
80
|
|
@@ -107,7 +108,7 @@ end
|
|
107
108
|
end
|
108
109
|
```
|
109
110
|
|
110
|
-
2. Deploy code
|
111
|
+
2. Deploy the code
|
111
112
|
3. Write a migration to remove the column (wrap in `safety_assured` block)
|
112
113
|
|
113
114
|
```ruby
|
@@ -118,7 +119,7 @@ end
|
|
118
119
|
end
|
119
120
|
```
|
120
121
|
|
121
|
-
4. Deploy and run migration
|
122
|
+
4. Deploy and run the migration
|
122
123
|
5. Remove the line added in step 1
|
123
124
|
|
124
125
|
### Adding a column with a default value
|
@@ -223,7 +224,7 @@ And some in MySQL and MariaDB:
|
|
223
224
|
|
224
225
|
Type | Safe Changes
|
225
226
|
--- | ---
|
226
|
-
`string` | Increasing `:limit` from under
|
227
|
+
`string` | Increasing `:limit` from under 63 up to 63, increasing `:limit` from over 63 to the max (the threshold can be different if using an encoding other than `utf8mb4` - for instance, it’s 85 for `utf8mb3` and 255 for `latin1`)
|
227
228
|
|
228
229
|
#### Good
|
229
230
|
|
@@ -488,6 +489,24 @@ class ValidateForeignKeyOnUsers < ActiveRecord::Migration[7.0]
|
|
488
489
|
end
|
489
490
|
```
|
490
491
|
|
492
|
+
### Adding an exclusion constraint
|
493
|
+
|
494
|
+
#### Bad
|
495
|
+
|
496
|
+
In Postgres, adding an exclusion constraint blocks reads and writes while every row is checked.
|
497
|
+
|
498
|
+
```ruby
|
499
|
+
class AddExclusionContraint < ActiveRecord::Migration[7.1]
|
500
|
+
def change
|
501
|
+
add_exclusion_constraint :users, "number WITH =", using: :gist
|
502
|
+
end
|
503
|
+
end
|
504
|
+
```
|
505
|
+
|
506
|
+
#### Good
|
507
|
+
|
508
|
+
[Let us know](https://github.com/ankane/strong_migrations/issues/new) if you have a safe way to do this (exclusion constraints cannot be marked `NOT VALID`).
|
509
|
+
|
491
510
|
### Adding a json column
|
492
511
|
|
493
512
|
#### Bad
|
@@ -805,6 +824,12 @@ The major version works well for Postgres, while the full version is recommended
|
|
805
824
|
|
806
825
|
For safety, this option only affects development and test environments. In other environments, the actual server version is always used.
|
807
826
|
|
827
|
+
If your app has multiple databases with different versions, with Rails 6.1+, you can use:
|
828
|
+
|
829
|
+
```ruby
|
830
|
+
StrongMigrations.target_version = {primary: 13, catalog: 15}
|
831
|
+
```
|
832
|
+
|
808
833
|
## Analyze Tables
|
809
834
|
|
810
835
|
Analyze tables automatically (to update planner statistics) after an index is added. Create an initializer with:
|
@@ -815,23 +840,18 @@ StrongMigrations.auto_analyze = true
|
|
815
840
|
|
816
841
|
## Faster Migrations
|
817
842
|
|
818
|
-
Only dump the schema when adding a new migration. If you use Git, add to
|
843
|
+
Only dump the schema when adding a new migration. If you use Git, add to `config/environments/development.rb`:
|
819
844
|
|
820
845
|
```rb
|
821
|
-
|
822
|
-
ActiveRecord::Base.dump_schema_after_migration = Rails.env.development? &&
|
823
|
-
`git status db/migrate/ --porcelain`.present?
|
824
|
-
end
|
825
|
-
|
826
|
-
task "db:migrate": "faster_migrations"
|
846
|
+
config.active_record.dump_schema_after_migration = `git status db/migrate/ --porcelain`.present?
|
827
847
|
```
|
828
848
|
|
829
849
|
## Schema Sanity
|
830
850
|
|
831
|
-
Columns can flip order in `db/schema.rb` when you have multiple developers. One way to prevent this is to [alphabetize them](https://www.pgrs.net/2008/03/12/alphabetize-schema-rb-columns/). Add to
|
851
|
+
Columns can flip order in `db/schema.rb` when you have multiple developers. One way to prevent this is to [alphabetize them](https://www.pgrs.net/2008/03/12/alphabetize-schema-rb-columns/). Add to `config/initializers/strong_migrations.rb`:
|
832
852
|
|
833
853
|
```ruby
|
834
|
-
|
854
|
+
StrongMigrations.alphabetize_schema = true
|
835
855
|
```
|
836
856
|
|
837
857
|
## Permissions
|
@@ -50,7 +50,23 @@ module StrongMigrations
|
|
50
50
|
target_version ||= StrongMigrations.target_version
|
51
51
|
version =
|
52
52
|
if target_version && StrongMigrations.developer_env?
|
53
|
-
target_version.
|
53
|
+
if target_version.is_a?(Hash)
|
54
|
+
# Active Record 6.0 supports multiple databases
|
55
|
+
# but connection.pool.spec.name always returns "primary"
|
56
|
+
# in migrations with rails db:migrate
|
57
|
+
if ActiveRecord::VERSION::STRING.to_f < 6.1
|
58
|
+
# error class is not shown in db:migrate output so ensure message is descriptive
|
59
|
+
raise StrongMigrations::Error, "StrongMigrations.target_version does not support multiple databases for Active Record < 6.1"
|
60
|
+
end
|
61
|
+
|
62
|
+
db_config_name = connection.pool.db_config.name
|
63
|
+
target_version.stringify_keys.fetch(db_config_name) do
|
64
|
+
# error class is not shown in db:migrate output so ensure message is descriptive
|
65
|
+
raise StrongMigrations::Error, "StrongMigrations.target_version is not configured for :#{db_config_name} database"
|
66
|
+
end.to_s
|
67
|
+
else
|
68
|
+
target_version.to_s
|
69
|
+
end
|
54
70
|
else
|
55
71
|
yield
|
56
72
|
end
|
@@ -18,6 +18,9 @@ module StrongMigrations
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def set_statement_timeout(timeout)
|
21
|
+
# fix deprecation warning with Active Record 7.1
|
22
|
+
timeout = timeout.value if timeout.is_a?(ActiveSupport::Duration)
|
23
|
+
|
21
24
|
select_all("SET max_statement_time = #{connection.quote(timeout)}")
|
22
25
|
end
|
23
26
|
|
@@ -25,6 +25,9 @@ module StrongMigrations
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def set_lock_timeout(timeout)
|
28
|
+
# fix deprecation warning with Active Record 7.1
|
29
|
+
timeout = timeout.value if timeout.is_a?(ActiveSupport::Duration)
|
30
|
+
|
28
31
|
select_all("SET lock_wait_timeout = #{connection.quote(timeout)}")
|
29
32
|
end
|
30
33
|
|
@@ -49,14 +52,31 @@ module StrongMigrations
|
|
49
52
|
|
50
53
|
case type.to_s
|
51
54
|
when "string"
|
52
|
-
# https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html
|
53
|
-
# https://mariadb.com/kb/en/innodb-online-ddl-operations-with-the-instant-alter-algorithm/#changing-the-data-type-of-a-column
|
54
|
-
# increased limit, but doesn't change number of length bytes
|
55
|
-
# 1-255 = 1 byte, 256-65532 = 2 bytes, 65533+ = too big for varchar
|
56
55
|
limit = options[:limit] || 255
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
if ["varchar"].include?(existing_type) && limit >= existing_column.limit
|
57
|
+
# https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html
|
58
|
+
# https://mariadb.com/kb/en/innodb-online-ddl-operations-with-the-instant-alter-algorithm/#changing-the-data-type-of-a-column
|
59
|
+
# increased limit, but doesn't change number of length bytes
|
60
|
+
# 1-255 = 1 byte, 256-65532 = 2 bytes, 65533+ = too big for varchar
|
61
|
+
|
62
|
+
# account for charset
|
63
|
+
# https://dev.mysql.com/doc/refman/8.0/en/charset-mysql.html
|
64
|
+
# https://mariadb.com/kb/en/supported-character-sets-and-collations/
|
65
|
+
sql = <<~SQL
|
66
|
+
SELECT cs.MAXLEN
|
67
|
+
FROM INFORMATION_SCHEMA.CHARACTER_SETS cs
|
68
|
+
INNER JOIN INFORMATION_SCHEMA.COLLATIONS c ON c.CHARACTER_SET_NAME = cs.CHARACTER_SET_NAME
|
69
|
+
INNER JOIN INFORMATION_SCHEMA.TABLES t ON t.TABLE_COLLATION = c.COLLATION_NAME
|
70
|
+
WHERE t.TABLE_SCHEMA = database() AND t.TABLE_NAME = #{connection.quote(table)}
|
71
|
+
SQL
|
72
|
+
row = connection.select_all(sql).first
|
73
|
+
if row
|
74
|
+
threshold = 255 / row["MAXLEN"]
|
75
|
+
safe = limit <= threshold || existing_column.limit > threshold
|
76
|
+
else
|
77
|
+
warn "[strong_migrations] Could not determine charset"
|
78
|
+
end
|
79
|
+
end
|
60
80
|
end
|
61
81
|
|
62
82
|
safe
|
@@ -32,9 +32,11 @@ module StrongMigrations
|
|
32
32
|
table, column, type = args
|
33
33
|
default = options[:default]
|
34
34
|
|
35
|
-
#
|
35
|
+
# Check key since DEFAULT NULL behaves differently from no default
|
36
|
+
#
|
37
|
+
# Also, Active Record has special case for uuid columns that allows function default values
|
36
38
|
# https://github.com/rails/rails/blob/v7.0.3.1/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb#L92-L93
|
37
|
-
if
|
39
|
+
if options.key?(:default) && (!adapter.add_column_default_safe? || (volatile = (postgresql? && type.to_s == "uuid" && default.to_s.include?("()") && adapter.default_volatile?(default))))
|
38
40
|
if options[:null] == false
|
39
41
|
options = options.except(:null)
|
40
42
|
append = "
|
@@ -42,14 +44,21 @@ module StrongMigrations
|
|
42
44
|
Then add the NOT NULL constraint in separate migrations."
|
43
45
|
end
|
44
46
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
if default.nil?
|
48
|
+
raise_error :add_column_default_null,
|
49
|
+
command: command_str("add_column", [table, column, type, options.except(:default)]),
|
50
|
+
append: append,
|
51
|
+
rewrite_blocks: adapter.rewrite_blocks
|
52
|
+
else
|
53
|
+
raise_error :add_column_default,
|
54
|
+
add_command: command_str("add_column", [table, column, type, options.except(:default)]),
|
55
|
+
change_command: command_str("change_column_default", [table, column, default]),
|
56
|
+
remove_command: command_str("remove_column", [table, column]),
|
57
|
+
code: backfill_code(table, column, default, volatile),
|
58
|
+
append: append,
|
59
|
+
rewrite_blocks: adapter.rewrite_blocks,
|
60
|
+
default_type: (volatile ? "volatile" : "non-null")
|
61
|
+
end
|
53
62
|
elsif default.is_a?(Proc) && postgresql?
|
54
63
|
# adding a column with a VOLATILE default is not safe
|
55
64
|
# https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-NOTES
|
@@ -64,6 +73,14 @@ Then add the NOT NULL constraint in separate migrations."
|
|
64
73
|
end
|
65
74
|
end
|
66
75
|
|
76
|
+
def check_add_exclusion_constraint(*args)
|
77
|
+
table = args[0]
|
78
|
+
|
79
|
+
unless new_table?(table)
|
80
|
+
raise_error :add_exclusion_constraint
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
67
84
|
# unlike add_index, we don't make an exception here for new tables
|
68
85
|
#
|
69
86
|
# with add_index, it's fine to lock a new table even after inserting data
|
@@ -161,7 +178,8 @@ Then add the foreign key in separate migrations."
|
|
161
178
|
table, column, type = args
|
162
179
|
|
163
180
|
safe = false
|
164
|
-
|
181
|
+
table_columns = connection.columns(table) rescue []
|
182
|
+
existing_column = table_columns.find { |c| c.name.to_s == column.to_s }
|
165
183
|
if existing_column
|
166
184
|
existing_type = existing_column.sql_type.sub(/\(\d+(,\d+)?\)/, "")
|
167
185
|
safe = adapter.change_type_safe?(table, column, type, options, existing_column, existing_type)
|
@@ -222,9 +240,7 @@ Then add the foreign key in separate migrations."
|
|
222
240
|
|
223
241
|
add_constraint_code =
|
224
242
|
if constraint_methods
|
225
|
-
#
|
226
|
-
expr_column = column.to_s =~ /\A[a-z0-9_]+\z/ ? column : connection.quote_column_name(column)
|
227
|
-
command_str(:add_check_constraint, [table, "#{expr_column} IS NOT NULL", {name: constraint_name, validate: false}])
|
243
|
+
command_str(:add_check_constraint, [table, "#{quote_column_if_needed(column)} IS NOT NULL", {name: constraint_name, validate: false}])
|
228
244
|
else
|
229
245
|
safety_assured_str(add_code)
|
230
246
|
end
|
@@ -424,12 +440,19 @@ Then add the foreign key in separate migrations."
|
|
424
440
|
model = table.to_s.classify
|
425
441
|
if function
|
426
442
|
# update_all(column: Arel.sql(default)) also works in newer versions of Active Record
|
427
|
-
"#{
|
443
|
+
update_expr = "#{quote_column_if_needed(column)} = #{default}"
|
444
|
+
"#{model}.unscoped.in_batches do |relation| \n relation.where(#{column}: nil).update_all(#{update_expr.inspect})\n sleep(0.01)\n end"
|
428
445
|
else
|
429
446
|
"#{model}.unscoped.in_batches do |relation| \n relation.update_all #{column}: #{default.inspect}\n sleep(0.01)\n end"
|
430
447
|
end
|
431
448
|
end
|
432
449
|
|
450
|
+
# only quote when needed
|
451
|
+
# important! only use for display purposes
|
452
|
+
def quote_column_if_needed(column)
|
453
|
+
column.to_s =~ /\A[a-z0-9_]+\z/ ? column : connection.quote_column_name(column)
|
454
|
+
end
|
455
|
+
|
433
456
|
def new_table?(table)
|
434
457
|
@new_tables.include?(table.to_s)
|
435
458
|
end
|
@@ -25,6 +25,16 @@ class Backfill%{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
|
25
25
|
end
|
26
26
|
end",
|
27
27
|
|
28
|
+
add_column_default_null:
|
29
|
+
"Adding a column with a null default blocks %{rewrite_blocks} while the entire table is rewritten.
|
30
|
+
Instead, add the column without a default value.
|
31
|
+
|
32
|
+
class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
33
|
+
def change
|
34
|
+
%{command}
|
35
|
+
end
|
36
|
+
end",
|
37
|
+
|
28
38
|
add_column_default_callable:
|
29
39
|
"Strong Migrations does not support inspecting callable default values.
|
30
40
|
Please make really sure you're not calling a VOLATILE function,
|
@@ -221,7 +231,10 @@ end",
|
|
221
231
|
|
222
232
|
validate_check_constraint:
|
223
233
|
"Validating a check constraint while writes are blocked is dangerous.
|
224
|
-
Use disable_ddl_transaction! or a separate migration."
|
234
|
+
Use disable_ddl_transaction! or a separate migration.",
|
235
|
+
|
236
|
+
add_exclusion_constraint:
|
237
|
+
"Adding an exclusion constraint blocks reads and writes while every row is checked."
|
225
238
|
}
|
226
239
|
self.enabled_checks = (error_messages.keys - [:remove_index]).map { |k| [k, {}] }.to_h
|
227
240
|
end
|
@@ -48,10 +48,20 @@ module StrongMigrations
|
|
48
48
|
dir.up do
|
49
49
|
@migration.add_foreign_key(from_table, to_table, *args, **options.merge(validate: false))
|
50
50
|
disable_transaction
|
51
|
-
|
51
|
+
validate_options = options.slice(:column, :name)
|
52
|
+
if ActiveRecord::VERSION::MAJOR >= 6
|
53
|
+
@migration.validate_foreign_key(from_table, to_table, **validate_options)
|
54
|
+
else
|
55
|
+
@migration.validate_foreign_key(from_table, validate_options.any? ? validate_options : to_table)
|
56
|
+
end
|
52
57
|
end
|
53
58
|
dir.down do
|
54
|
-
|
59
|
+
remove_options = options.slice(:column, :name)
|
60
|
+
if ActiveRecord::VERSION::MAJOR >= 6
|
61
|
+
@migration.remove_foreign_key(from_table, to_table, **remove_options)
|
62
|
+
else
|
63
|
+
@migration.remove_foreign_key(from_table, remove_options.any? ? remove_options : to_table)
|
64
|
+
end
|
55
65
|
end
|
56
66
|
end
|
57
67
|
end
|
@@ -64,7 +74,7 @@ module StrongMigrations
|
|
64
74
|
@migration.validate_check_constraint(table, **validate_options)
|
65
75
|
end
|
66
76
|
dir.down do
|
67
|
-
@migration.remove_check_constraint(table, expression, **add_options)
|
77
|
+
@migration.remove_check_constraint(table, expression, **add_options.except(:validate))
|
68
78
|
end
|
69
79
|
end
|
70
80
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module StrongMigrations
|
2
|
+
module SchemaDumper
|
3
|
+
def initialize(connection, *args, **options)
|
4
|
+
return super unless StrongMigrations.alphabetize_schema
|
5
|
+
|
6
|
+
super(WrappedConnection.new(connection), *args, **options)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class WrappedConnection
|
11
|
+
delegate_missing_to :@connection
|
12
|
+
|
13
|
+
def initialize(connection)
|
14
|
+
@connection = connection
|
15
|
+
end
|
16
|
+
|
17
|
+
def columns(*args, **options)
|
18
|
+
@connection.columns(*args, **options).sort_by(&:name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/strong_migrations.rb
CHANGED
@@ -2,22 +2,22 @@
|
|
2
2
|
require "active_support"
|
3
3
|
|
4
4
|
# adapters
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
require_relative "strong_migrations/adapters/abstract_adapter"
|
6
|
+
require_relative "strong_migrations/adapters/mysql_adapter"
|
7
|
+
require_relative "strong_migrations/adapters/mariadb_adapter"
|
8
|
+
require_relative "strong_migrations/adapters/postgresql_adapter"
|
9
9
|
|
10
10
|
# modules
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
require_relative "strong_migrations/checks"
|
12
|
+
require_relative "strong_migrations/safe_methods"
|
13
|
+
require_relative "strong_migrations/checker"
|
14
|
+
require_relative "strong_migrations/database_tasks"
|
15
|
+
require_relative "strong_migrations/migration"
|
16
|
+
require_relative "strong_migrations/migrator"
|
17
|
+
require_relative "strong_migrations/version"
|
18
18
|
|
19
19
|
# integrations
|
20
|
-
|
20
|
+
require_relative "strong_migrations/railtie" if defined?(Rails)
|
21
21
|
|
22
22
|
module StrongMigrations
|
23
23
|
class Error < StandardError; end
|
@@ -28,7 +28,8 @@ module StrongMigrations
|
|
28
28
|
attr_accessor :auto_analyze, :start_after, :checks, :error_messages,
|
29
29
|
:target_postgresql_version, :target_mysql_version, :target_mariadb_version,
|
30
30
|
:enabled_checks, :lock_timeout, :statement_timeout, :check_down, :target_version,
|
31
|
-
:safe_by_default, :target_sql_mode, :lock_timeout_retries, :lock_timeout_retry_delay
|
31
|
+
:safe_by_default, :target_sql_mode, :lock_timeout_retries, :lock_timeout_retry_delay,
|
32
|
+
:alphabetize_schema
|
32
33
|
attr_writer :lock_timeout_limit
|
33
34
|
end
|
34
35
|
self.auto_analyze = false
|
@@ -38,10 +39,21 @@ module StrongMigrations
|
|
38
39
|
self.checks = []
|
39
40
|
self.safe_by_default = false
|
40
41
|
self.check_down = false
|
42
|
+
self.alphabetize_schema = false
|
41
43
|
|
42
44
|
# private
|
43
45
|
def self.developer_env?
|
44
|
-
|
46
|
+
env == "development" || env == "test"
|
47
|
+
end
|
48
|
+
|
49
|
+
# private
|
50
|
+
def self.env
|
51
|
+
if defined?(Rails.env)
|
52
|
+
Rails.env
|
53
|
+
else
|
54
|
+
# default to production for safety
|
55
|
+
ENV["RACK_ENV"] || "production"
|
56
|
+
end
|
45
57
|
end
|
46
58
|
|
47
59
|
def self.lock_timeout_limit
|
@@ -74,7 +86,7 @@ module StrongMigrations
|
|
74
86
|
end
|
75
87
|
|
76
88
|
# load error messages
|
77
|
-
|
89
|
+
require_relative "strong_migrations/error_messages"
|
78
90
|
|
79
91
|
ActiveSupport.on_load(:active_record) do
|
80
92
|
ActiveRecord::Migration.prepend(StrongMigrations::Migration)
|
@@ -83,4 +95,7 @@ ActiveSupport.on_load(:active_record) do
|
|
83
95
|
if defined?(ActiveRecord::Tasks::DatabaseTasks)
|
84
96
|
ActiveRecord::Tasks::DatabaseTasks.singleton_class.prepend(StrongMigrations::DatabaseTasks)
|
85
97
|
end
|
98
|
+
|
99
|
+
require_relative "strong_migrations/schema_dumper"
|
100
|
+
ActiveRecord::SchemaDumper.prepend(StrongMigrations::SchemaDumper)
|
86
101
|
end
|
@@ -4,11 +4,6 @@ namespace :strong_migrations do
|
|
4
4
|
$stderr.puts "Dumping schema"
|
5
5
|
ActiveRecord::Base.logger.level = Logger::INFO
|
6
6
|
|
7
|
-
|
8
|
-
ActiveRecord::Base.connection.class.prepend StrongMigrations::AlphabetizeColumns
|
9
|
-
if ActiveRecord::ConnectionAdapters.const_defined?('PostGISAdapter')
|
10
|
-
ActiveRecord::ConnectionAdapters::PostGISAdapter.prepend StrongMigrations::AlphabetizeColumns
|
11
|
-
end
|
12
|
-
ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend StrongMigrations::AlphabetizeColumns
|
7
|
+
StrongMigrations.alphabetize_schema = true
|
13
8
|
end
|
14
9
|
end
|
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: 1.
|
4
|
+
version: 1.4.4
|
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:
|
13
|
+
date: 2023-03-08 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -45,7 +45,6 @@ files:
|
|
45
45
|
- lib/strong_migrations/adapters/mariadb_adapter.rb
|
46
46
|
- lib/strong_migrations/adapters/mysql_adapter.rb
|
47
47
|
- lib/strong_migrations/adapters/postgresql_adapter.rb
|
48
|
-
- lib/strong_migrations/alphabetize_columns.rb
|
49
48
|
- lib/strong_migrations/checker.rb
|
50
49
|
- lib/strong_migrations/checks.rb
|
51
50
|
- lib/strong_migrations/database_tasks.rb
|
@@ -54,6 +53,7 @@ files:
|
|
54
53
|
- lib/strong_migrations/migrator.rb
|
55
54
|
- lib/strong_migrations/railtie.rb
|
56
55
|
- lib/strong_migrations/safe_methods.rb
|
56
|
+
- lib/strong_migrations/schema_dumper.rb
|
57
57
|
- lib/strong_migrations/version.rb
|
58
58
|
- lib/tasks/strong_migrations.rake
|
59
59
|
homepage: https://github.com/ankane/strong_migrations
|
@@ -75,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: '0'
|
77
77
|
requirements: []
|
78
|
-
rubygems_version: 3.
|
78
|
+
rubygems_version: 3.4.6
|
79
79
|
signing_key:
|
80
80
|
specification_version: 4
|
81
81
|
summary: Catch unsafe migrations in development
|