strong_migrations 0.7.8 → 0.7.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +32 -32
- data/lib/strong_migrations/database_tasks.rb +2 -1
- data/lib/strong_migrations/version.rb +1 -1
- metadata +4 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2fb3fbcc5caf98759ebe2ef05a4ef011eca91924e479647d36e2b261baf2c8e
|
4
|
+
data.tar.gz: '0118bd4e05814f2d531a659a724237080763843bd6cb3ff0b880447348004585'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a04ea74876b44c645c9cba04c2f7b4932fcc0637eedd78b544dadf40272c84fb0461420e66c49c991c214f5d36b53acbface0347af25cb65c1e9c1251375886
|
7
|
+
data.tar.gz: 8e97437c5eae3b3aa6508e08c21aa8caf648a03989e621d37c165d1a2412a3cc67784d0923d47e7f814475bb000c6e68e93bf5ce6ef5dbd83f03fc399bb85b4c
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -43,7 +43,7 @@ end
|
|
43
43
|
|
44
44
|
Deploy the code, then wrap this step in a safety_assured { ... } block.
|
45
45
|
|
46
|
-
class RemoveColumn < ActiveRecord::Migration[
|
46
|
+
class RemoveColumn < ActiveRecord::Migration[7.0]
|
47
47
|
def change
|
48
48
|
safety_assured { remove_column :users, :name }
|
49
49
|
end
|
@@ -90,7 +90,7 @@ You can also add [custom checks](#custom-checks) or [disable specific checks](#d
|
|
90
90
|
Active Record caches database columns at runtime, so if you drop a column, it can cause exceptions until your app reboots.
|
91
91
|
|
92
92
|
```ruby
|
93
|
-
class RemoveSomeColumnFromUsers < ActiveRecord::Migration[
|
93
|
+
class RemoveSomeColumnFromUsers < ActiveRecord::Migration[7.0]
|
94
94
|
def change
|
95
95
|
remove_column :users, :some_column
|
96
96
|
end
|
@@ -111,7 +111,7 @@ end
|
|
111
111
|
3. Write a migration to remove the column (wrap in `safety_assured` block)
|
112
112
|
|
113
113
|
```ruby
|
114
|
-
class RemoveSomeColumnFromUsers < ActiveRecord::Migration[
|
114
|
+
class RemoveSomeColumnFromUsers < ActiveRecord::Migration[7.0]
|
115
115
|
def change
|
116
116
|
safety_assured { remove_column :users, :some_column }
|
117
117
|
end
|
@@ -127,7 +127,7 @@ end
|
|
127
127
|
In earlier versions of Postgres, MySQL, and MariaDB, adding a column with a default value to an existing table causes the entire table to be rewritten. During this time, reads and writes are blocked in Postgres, and writes are blocked in MySQL and MariaDB.
|
128
128
|
|
129
129
|
```ruby
|
130
|
-
class AddSomeColumnToUsers < ActiveRecord::Migration[
|
130
|
+
class AddSomeColumnToUsers < ActiveRecord::Migration[7.0]
|
131
131
|
def change
|
132
132
|
add_column :users, :some_column, :text, default: "default_value"
|
133
133
|
end
|
@@ -141,7 +141,7 @@ In Postgres 11+, MySQL 8.0.12+, and MariaDB 10.3.2+, this no longer requires a t
|
|
141
141
|
Instead, add the column without a default value, then change the default.
|
142
142
|
|
143
143
|
```ruby
|
144
|
-
class AddSomeColumnToUsers < ActiveRecord::Migration[
|
144
|
+
class AddSomeColumnToUsers < ActiveRecord::Migration[7.0]
|
145
145
|
def up
|
146
146
|
add_column :users, :some_column, :text
|
147
147
|
change_column_default :users, :some_column, "default_value"
|
@@ -162,7 +162,7 @@ See the next section for how to backfill.
|
|
162
162
|
Active Record creates a transaction around each migration, and backfilling in the same transaction that alters a table keeps the table locked for the [duration of the backfill](https://wework.github.io/data/2015/11/05/add-columns-with-default-values-to-large-tables-in-rails-postgres/).
|
163
163
|
|
164
164
|
```ruby
|
165
|
-
class AddSomeColumnToUsers < ActiveRecord::Migration[
|
165
|
+
class AddSomeColumnToUsers < ActiveRecord::Migration[7.0]
|
166
166
|
def change
|
167
167
|
add_column :users, :some_column, :text
|
168
168
|
User.update_all some_column: "default_value"
|
@@ -177,7 +177,7 @@ Also, running a single query to update data can cause issues for large tables.
|
|
177
177
|
There are three keys to backfilling safely: batching, throttling, and running it outside a transaction. Use the Rails console or a separate migration with `disable_ddl_transaction!`.
|
178
178
|
|
179
179
|
```ruby
|
180
|
-
class BackfillSomeColumn < ActiveRecord::Migration[
|
180
|
+
class BackfillSomeColumn < ActiveRecord::Migration[7.0]
|
181
181
|
disable_ddl_transaction!
|
182
182
|
|
183
183
|
def up
|
@@ -196,7 +196,7 @@ end
|
|
196
196
|
Changing the type of a column causes the entire table to be rewritten. During this time, reads and writes are blocked in Postgres, and writes are blocked in MySQL and MariaDB.
|
197
197
|
|
198
198
|
```ruby
|
199
|
-
class ChangeSomeColumnType < ActiveRecord::Migration[
|
199
|
+
class ChangeSomeColumnType < ActiveRecord::Migration[7.0]
|
200
200
|
def change
|
201
201
|
change_column :users, :some_column, :new_type
|
202
202
|
end
|
@@ -235,7 +235,7 @@ A safer approach is to:
|
|
235
235
|
Renaming a column that’s in use will cause errors in your application.
|
236
236
|
|
237
237
|
```ruby
|
238
|
-
class RenameSomeColumn < ActiveRecord::Migration[
|
238
|
+
class RenameSomeColumn < ActiveRecord::Migration[7.0]
|
239
239
|
def change
|
240
240
|
rename_column :users, :some_column, :new_name
|
241
241
|
end
|
@@ -260,7 +260,7 @@ A safer approach is to:
|
|
260
260
|
Renaming a table that’s in use will cause errors in your application.
|
261
261
|
|
262
262
|
```ruby
|
263
|
-
class RenameUsersToCustomers < ActiveRecord::Migration[
|
263
|
+
class RenameUsersToCustomers < ActiveRecord::Migration[7.0]
|
264
264
|
def change
|
265
265
|
rename_table :users, :customers
|
266
266
|
end
|
@@ -285,7 +285,7 @@ A safer approach is to:
|
|
285
285
|
The `force` option can drop an existing table.
|
286
286
|
|
287
287
|
```ruby
|
288
|
-
class CreateUsers < ActiveRecord::Migration[
|
288
|
+
class CreateUsers < ActiveRecord::Migration[7.0]
|
289
289
|
def change
|
290
290
|
create_table :users, force: true do |t|
|
291
291
|
# ...
|
@@ -299,7 +299,7 @@ end
|
|
299
299
|
Create tables without the `force` option.
|
300
300
|
|
301
301
|
```ruby
|
302
|
-
class CreateUsers < ActiveRecord::Migration[
|
302
|
+
class CreateUsers < ActiveRecord::Migration[7.0]
|
303
303
|
def change
|
304
304
|
create_table :users do |t|
|
305
305
|
# ...
|
@@ -319,7 +319,7 @@ If you intend to drop an existing table, run `drop_table` first.
|
|
319
319
|
Adding a check constraint blocks reads and writes in Postgres and blocks writes in MySQL and MariaDB while every row is checked.
|
320
320
|
|
321
321
|
```ruby
|
322
|
-
class AddCheckConstraint < ActiveRecord::Migration[
|
322
|
+
class AddCheckConstraint < ActiveRecord::Migration[7.0]
|
323
323
|
def change
|
324
324
|
add_check_constraint :users, "price > 0", name: "price_check"
|
325
325
|
end
|
@@ -331,7 +331,7 @@ end
|
|
331
331
|
Add the check constraint without validating existing rows:
|
332
332
|
|
333
333
|
```ruby
|
334
|
-
class AddCheckConstraint < ActiveRecord::Migration[
|
334
|
+
class AddCheckConstraint < ActiveRecord::Migration[7.0]
|
335
335
|
def change
|
336
336
|
add_check_constraint :users, "price > 0", name: "price_check", validate: false
|
337
337
|
end
|
@@ -341,7 +341,7 @@ end
|
|
341
341
|
Then validate them in a separate migration.
|
342
342
|
|
343
343
|
```ruby
|
344
|
-
class ValidateCheckConstraint < ActiveRecord::Migration[
|
344
|
+
class ValidateCheckConstraint < ActiveRecord::Migration[7.0]
|
345
345
|
def change
|
346
346
|
validate_check_constraint :users, name: "price_check"
|
347
347
|
end
|
@@ -361,7 +361,7 @@ end
|
|
361
361
|
Setting `NOT NULL` on an existing column blocks reads and writes while every row is checked.
|
362
362
|
|
363
363
|
```ruby
|
364
|
-
class SetSomeColumnNotNull < ActiveRecord::Migration[
|
364
|
+
class SetSomeColumnNotNull < ActiveRecord::Migration[7.0]
|
365
365
|
def change
|
366
366
|
change_column_null :users, :some_column, false
|
367
367
|
end
|
@@ -375,7 +375,7 @@ Instead, add a check constraint.
|
|
375
375
|
For Rails 6.1, use:
|
376
376
|
|
377
377
|
```ruby
|
378
|
-
class SetSomeColumnNotNull < ActiveRecord::Migration[
|
378
|
+
class SetSomeColumnNotNull < ActiveRecord::Migration[7.0]
|
379
379
|
def change
|
380
380
|
add_check_constraint :users, "some_column IS NOT NULL", name: "users_some_column_null", validate: false
|
381
381
|
end
|
@@ -399,7 +399,7 @@ Then validate it in a separate migration. A `NOT NULL` check constraint is [func
|
|
399
399
|
For Rails 6.1, use:
|
400
400
|
|
401
401
|
```ruby
|
402
|
-
class ValidateSomeColumnNotNull < ActiveRecord::Migration[
|
402
|
+
class ValidateSomeColumnNotNull < ActiveRecord::Migration[7.0]
|
403
403
|
def change
|
404
404
|
validate_check_constraint :users, name: "users_some_column_null"
|
405
405
|
|
@@ -437,7 +437,7 @@ end
|
|
437
437
|
Strong Migrations can’t ensure safety for raw SQL statements. Make really sure that what you’re doing is safe, then use:
|
438
438
|
|
439
439
|
```ruby
|
440
|
-
class ExecuteSQL < ActiveRecord::Migration[
|
440
|
+
class ExecuteSQL < ActiveRecord::Migration[7.0]
|
441
441
|
def change
|
442
442
|
safety_assured { execute "..." }
|
443
443
|
end
|
@@ -453,7 +453,7 @@ end
|
|
453
453
|
In Postgres, adding an index non-concurrently blocks writes.
|
454
454
|
|
455
455
|
```ruby
|
456
|
-
class AddSomeIndexToUsers < ActiveRecord::Migration[
|
456
|
+
class AddSomeIndexToUsers < ActiveRecord::Migration[7.0]
|
457
457
|
def change
|
458
458
|
add_index :users, :some_column
|
459
459
|
end
|
@@ -465,7 +465,7 @@ end
|
|
465
465
|
Add indexes concurrently.
|
466
466
|
|
467
467
|
```ruby
|
468
|
-
class AddSomeIndexToUsers < ActiveRecord::Migration[
|
468
|
+
class AddSomeIndexToUsers < ActiveRecord::Migration[7.0]
|
469
469
|
disable_ddl_transaction!
|
470
470
|
|
471
471
|
def change
|
@@ -491,7 +491,7 @@ rails g index table column
|
|
491
491
|
Rails adds an index non-concurrently to references by default, which blocks writes in Postgres.
|
492
492
|
|
493
493
|
```ruby
|
494
|
-
class AddReferenceToUsers < ActiveRecord::Migration[
|
494
|
+
class AddReferenceToUsers < ActiveRecord::Migration[7.0]
|
495
495
|
def change
|
496
496
|
add_reference :users, :city
|
497
497
|
end
|
@@ -503,7 +503,7 @@ end
|
|
503
503
|
Make sure the index is added concurrently.
|
504
504
|
|
505
505
|
```ruby
|
506
|
-
class AddReferenceToUsers < ActiveRecord::Migration[
|
506
|
+
class AddReferenceToUsers < ActiveRecord::Migration[7.0]
|
507
507
|
disable_ddl_transaction!
|
508
508
|
|
509
509
|
def change
|
@@ -521,7 +521,7 @@ end
|
|
521
521
|
In Postgres, adding a foreign key blocks writes on both tables.
|
522
522
|
|
523
523
|
```ruby
|
524
|
-
class AddForeignKeyOnUsers < ActiveRecord::Migration[
|
524
|
+
class AddForeignKeyOnUsers < ActiveRecord::Migration[7.0]
|
525
525
|
def change
|
526
526
|
add_foreign_key :users, :orders
|
527
527
|
end
|
@@ -531,7 +531,7 @@ end
|
|
531
531
|
or
|
532
532
|
|
533
533
|
```ruby
|
534
|
-
class AddReferenceToUsers < ActiveRecord::Migration[
|
534
|
+
class AddReferenceToUsers < ActiveRecord::Migration[7.0]
|
535
535
|
def change
|
536
536
|
add_reference :users, :order, foreign_key: true
|
537
537
|
end
|
@@ -545,7 +545,7 @@ Add the foreign key without validating existing rows, then validate them in a se
|
|
545
545
|
For Rails 5.2+, use:
|
546
546
|
|
547
547
|
```ruby
|
548
|
-
class AddForeignKeyOnUsers < ActiveRecord::Migration[
|
548
|
+
class AddForeignKeyOnUsers < ActiveRecord::Migration[7.0]
|
549
549
|
def change
|
550
550
|
add_foreign_key :users, :orders, validate: false
|
551
551
|
end
|
@@ -555,7 +555,7 @@ end
|
|
555
555
|
Then:
|
556
556
|
|
557
557
|
```ruby
|
558
|
-
class ValidateForeignKeyOnUsers < ActiveRecord::Migration[
|
558
|
+
class ValidateForeignKeyOnUsers < ActiveRecord::Migration[7.0]
|
559
559
|
def change
|
560
560
|
validate_foreign_key :users, :orders
|
561
561
|
end
|
@@ -593,7 +593,7 @@ end
|
|
593
593
|
In Postgres, there’s no equality operator for the `json` column type, which can cause errors for existing `SELECT DISTINCT` queries in your application.
|
594
594
|
|
595
595
|
```ruby
|
596
|
-
class AddPropertiesToUsers < ActiveRecord::Migration[
|
596
|
+
class AddPropertiesToUsers < ActiveRecord::Migration[7.0]
|
597
597
|
def change
|
598
598
|
add_column :users, :properties, :json
|
599
599
|
end
|
@@ -605,7 +605,7 @@ end
|
|
605
605
|
Use `jsonb` instead.
|
606
606
|
|
607
607
|
```ruby
|
608
|
-
class AddPropertiesToUsers < ActiveRecord::Migration[
|
608
|
+
class AddPropertiesToUsers < ActiveRecord::Migration[7.0]
|
609
609
|
def change
|
610
610
|
add_column :users, :properties, :jsonb
|
611
611
|
end
|
@@ -619,7 +619,7 @@ end
|
|
619
619
|
Adding a non-unique index with more than three columns rarely improves performance.
|
620
620
|
|
621
621
|
```ruby
|
622
|
-
class AddSomeIndexToUsers < ActiveRecord::Migration[
|
622
|
+
class AddSomeIndexToUsers < ActiveRecord::Migration[7.0]
|
623
623
|
def change
|
624
624
|
add_index :users, [:a, :b, :c, :d]
|
625
625
|
end
|
@@ -631,7 +631,7 @@ end
|
|
631
631
|
Instead, start an index with columns that narrow down the results the most.
|
632
632
|
|
633
633
|
```ruby
|
634
|
-
class AddSomeIndexToUsers < ActiveRecord::Migration[
|
634
|
+
class AddSomeIndexToUsers < ActiveRecord::Migration[7.0]
|
635
635
|
def change
|
636
636
|
add_index :users, [:b, :d]
|
637
637
|
end
|
@@ -645,7 +645,7 @@ For Postgres, be sure to add them concurrently.
|
|
645
645
|
To mark a step in the migration as safe, despite using a method that might otherwise be dangerous, wrap it in a `safety_assured` block.
|
646
646
|
|
647
647
|
```ruby
|
648
|
-
class MySafeMigration < ActiveRecord::Migration[
|
648
|
+
class MySafeMigration < ActiveRecord::Migration[7.0]
|
649
649
|
def change
|
650
650
|
safety_assured { remove_column :users, :some_column }
|
651
651
|
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: 0.7.
|
4
|
+
version: 0.7.9
|
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: 2021-
|
13
|
+
date: 2021-12-16 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -26,79 +26,9 @@ dependencies:
|
|
26
26
|
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: '5'
|
29
|
-
- !ruby/object:Gem::Dependency
|
30
|
-
name: bundler
|
31
|
-
requirement: !ruby/object:Gem::Requirement
|
32
|
-
requirements:
|
33
|
-
- - ">="
|
34
|
-
- !ruby/object:Gem::Version
|
35
|
-
version: '0'
|
36
|
-
type: :development
|
37
|
-
prerelease: false
|
38
|
-
version_requirements: !ruby/object:Gem::Requirement
|
39
|
-
requirements:
|
40
|
-
- - ">="
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: '0'
|
43
|
-
- !ruby/object:Gem::Dependency
|
44
|
-
name: rake
|
45
|
-
requirement: !ruby/object:Gem::Requirement
|
46
|
-
requirements:
|
47
|
-
- - ">="
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: '0'
|
50
|
-
type: :development
|
51
|
-
prerelease: false
|
52
|
-
version_requirements: !ruby/object:Gem::Requirement
|
53
|
-
requirements:
|
54
|
-
- - ">="
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version: '0'
|
57
|
-
- !ruby/object:Gem::Dependency
|
58
|
-
name: minitest
|
59
|
-
requirement: !ruby/object:Gem::Requirement
|
60
|
-
requirements:
|
61
|
-
- - ">="
|
62
|
-
- !ruby/object:Gem::Version
|
63
|
-
version: '0'
|
64
|
-
type: :development
|
65
|
-
prerelease: false
|
66
|
-
version_requirements: !ruby/object:Gem::Requirement
|
67
|
-
requirements:
|
68
|
-
- - ">="
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
version: '0'
|
71
|
-
- !ruby/object:Gem::Dependency
|
72
|
-
name: pg
|
73
|
-
requirement: !ruby/object:Gem::Requirement
|
74
|
-
requirements:
|
75
|
-
- - ">="
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '0'
|
78
|
-
type: :development
|
79
|
-
prerelease: false
|
80
|
-
version_requirements: !ruby/object:Gem::Requirement
|
81
|
-
requirements:
|
82
|
-
- - ">="
|
83
|
-
- !ruby/object:Gem::Version
|
84
|
-
version: '0'
|
85
|
-
- !ruby/object:Gem::Dependency
|
86
|
-
name: mysql2
|
87
|
-
requirement: !ruby/object:Gem::Requirement
|
88
|
-
requirements:
|
89
|
-
- - ">="
|
90
|
-
- !ruby/object:Gem::Version
|
91
|
-
version: '0'
|
92
|
-
type: :development
|
93
|
-
prerelease: false
|
94
|
-
version_requirements: !ruby/object:Gem::Requirement
|
95
|
-
requirements:
|
96
|
-
- - ">="
|
97
|
-
- !ruby/object:Gem::Version
|
98
|
-
version: '0'
|
99
29
|
description:
|
100
30
|
email:
|
101
|
-
- andrew@
|
31
|
+
- andrew@ankane.org
|
102
32
|
- bob.remeika@gmail.com
|
103
33
|
executables: []
|
104
34
|
extensions: []
|
@@ -138,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
68
|
- !ruby/object:Gem::Version
|
139
69
|
version: '0'
|
140
70
|
requirements: []
|
141
|
-
rubygems_version: 3.
|
71
|
+
rubygems_version: 3.1.6
|
142
72
|
signing_key:
|
143
73
|
specification_version: 4
|
144
74
|
summary: Catch unsafe migrations in development
|