strong_migrations 0.7.4 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2bd2b26a8cb5d3577ffaad3878ff961dec2bc6cb55c51897b2681febbf8f0b10
4
- data.tar.gz: b48c9ff1050345351a9f938c6dd6dc8530fbc4842e0fc3c60702287fa3fb825c
3
+ metadata.gz: 2361d565fefd198370b908622526d01c4b5052f5361947c6410d1176b21b20a9
4
+ data.tar.gz: c9ee9a7b444980b957f60dbb09290a5296a94e9f121af6b1d83756b2645ab54e
5
5
  SHA512:
6
- metadata.gz: 4bc2817b7878c3041442e4e4607db55b2861e7cba16220e635ee28a4b9ebd6dbd0a7ab16033555fa51f4f98601fe0eda198fa91e3030dfff63839c7cdc9aa028
7
- data.tar.gz: 254e72cd2ce295759819f05cde920cf4c3ea9ae0d45af9f21d6ac11d55549d0d3544f97f511dc5b1dc0cf44c03c25af4208e4ab4f317449d9aabea90cd485b99
6
+ metadata.gz: ca57e53122e37d7674143a48a5699bacf07f07f3c638abbf71331a3c4686a1e08f4f1fa02160e99ea0e21ed3a811aa43dc11581143b0229f5201ddc335fd792b
7
+ data.tar.gz: 4b760e24cda9a14efed64300992645ec9e4b207bbafb5210bdfd2195764980cc0ab08ebbd6693aac6518d5302da918a74e20d5d282d654700efe89e4a8418a63
@@ -1,3 +1,7 @@
1
+ ## 0.7.5 (2021-01-12)
2
+
3
+ - Added checks for `add_check_constraint` and `validate_check_constraint`
4
+
1
5
  ## 0.7.4 (2020-12-16)
2
6
 
3
7
  - Added `safe_by_default` option to install generator
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 Bob Remeika and David Waller, 2015-2020 Andrew Kane
1
+ Copyright (c) 2013 Bob Remeika and David Waller, 2015-2021 Andrew Kane
2
2
 
3
3
  MIT License
4
4
 
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[6.0]
46
+ class RemoveColumn < ActiveRecord::Migration[6.1]
47
47
  def change
48
48
  safety_assured { remove_column :users, :name }
49
49
  end
@@ -66,6 +66,7 @@ Potentially dangerous operations:
66
66
  - [renaming a column](#renaming-a-column)
67
67
  - [renaming a table](#renaming-a-table)
68
68
  - [creating a table with the force option](#creating-a-table-with-the-force-option)
69
+ - [adding a check constraint](#adding-a-check-constraint)
69
70
  - [setting NOT NULL on an existing column](#setting-not-null-on-an-existing-column)
70
71
  - [executing SQL directly](#executing-SQL-directly)
71
72
 
@@ -89,7 +90,7 @@ You can also add [custom checks](#custom-checks) or [disable specific checks](#d
89
90
  Active Record caches database columns at runtime, so if you drop a column, it can cause exceptions until your app reboots.
90
91
 
91
92
  ```ruby
92
- class RemoveSomeColumnFromUsers < ActiveRecord::Migration[6.0]
93
+ class RemoveSomeColumnFromUsers < ActiveRecord::Migration[6.1]
93
94
  def change
94
95
  remove_column :users, :some_column
95
96
  end
@@ -110,7 +111,7 @@ end
110
111
  3. Write a migration to remove the column (wrap in `safety_assured` block)
111
112
 
112
113
  ```ruby
113
- class RemoveSomeColumnFromUsers < ActiveRecord::Migration[6.0]
114
+ class RemoveSomeColumnFromUsers < ActiveRecord::Migration[6.1]
114
115
  def change
115
116
  safety_assured { remove_column :users, :some_column }
116
117
  end
@@ -126,7 +127,7 @@ end
126
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.
127
128
 
128
129
  ```ruby
129
- class AddSomeColumnToUsers < ActiveRecord::Migration[6.0]
130
+ class AddSomeColumnToUsers < ActiveRecord::Migration[6.1]
130
131
  def change
131
132
  add_column :users, :some_column, :text, default: "default_value"
132
133
  end
@@ -140,7 +141,7 @@ In Postgres 11+, MySQL 8.0.12+, and MariaDB 10.3.2+, this no longer requires a t
140
141
  Instead, add the column without a default value, then change the default.
141
142
 
142
143
  ```ruby
143
- class AddSomeColumnToUsers < ActiveRecord::Migration[6.0]
144
+ class AddSomeColumnToUsers < ActiveRecord::Migration[6.1]
144
145
  def up
145
146
  add_column :users, :some_column, :text
146
147
  change_column_default :users, :some_column, "default_value"
@@ -161,7 +162,7 @@ See the next section for how to backfill.
161
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/).
162
163
 
163
164
  ```ruby
164
- class AddSomeColumnToUsers < ActiveRecord::Migration[6.0]
165
+ class AddSomeColumnToUsers < ActiveRecord::Migration[6.1]
165
166
  def change
166
167
  add_column :users, :some_column, :text
167
168
  User.update_all some_column: "default_value"
@@ -176,7 +177,7 @@ Also, running a single query to update data can cause issues for large tables.
176
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!`.
177
178
 
178
179
  ```ruby
179
- class BackfillSomeColumn < ActiveRecord::Migration[6.0]
180
+ class BackfillSomeColumn < ActiveRecord::Migration[6.1]
180
181
  disable_ddl_transaction!
181
182
 
182
183
  def up
@@ -195,7 +196,7 @@ end
195
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.
196
197
 
197
198
  ```ruby
198
- class ChangeSomeColumnType < ActiveRecord::Migration[6.0]
199
+ class ChangeSomeColumnType < ActiveRecord::Migration[6.1]
199
200
  def change
200
201
  change_column :users, :some_column, :new_type
201
202
  end
@@ -234,7 +235,7 @@ A safer approach is to:
234
235
  Renaming a column that’s in use will cause errors in your application.
235
236
 
236
237
  ```ruby
237
- class RenameSomeColumn < ActiveRecord::Migration[6.0]
238
+ class RenameSomeColumn < ActiveRecord::Migration[6.1]
238
239
  def change
239
240
  rename_column :users, :some_column, :new_name
240
241
  end
@@ -259,7 +260,7 @@ A safer approach is to:
259
260
  Renaming a table that’s in use will cause errors in your application.
260
261
 
261
262
  ```ruby
262
- class RenameUsersToCustomers < ActiveRecord::Migration[6.0]
263
+ class RenameUsersToCustomers < ActiveRecord::Migration[6.1]
263
264
  def change
264
265
  rename_table :users, :customers
265
266
  end
@@ -284,7 +285,7 @@ A safer approach is to:
284
285
  The `force` option can drop an existing table.
285
286
 
286
287
  ```ruby
287
- class CreateUsers < ActiveRecord::Migration[6.0]
288
+ class CreateUsers < ActiveRecord::Migration[6.1]
288
289
  def change
289
290
  create_table :users, force: true do |t|
290
291
  # ...
@@ -298,7 +299,7 @@ end
298
299
  Create tables without the `force` option.
299
300
 
300
301
  ```ruby
301
- class CreateUsers < ActiveRecord::Migration[6.0]
302
+ class CreateUsers < ActiveRecord::Migration[6.1]
302
303
  def change
303
304
  create_table :users do |t|
304
305
  # ...
@@ -309,6 +310,48 @@ end
309
310
 
310
311
  If you intend to drop an existing table, run `drop_table` first.
311
312
 
313
+ ### Adding a check constraint
314
+
315
+ :turtle: Safe by default available
316
+
317
+ #### Bad
318
+
319
+ Adding a check constraint blocks reads and writes in Postgres and blocks writes in MySQL and MariaDB while every row is checked.
320
+
321
+ ```ruby
322
+ class AddCheckConstraint < ActiveRecord::Migration[6.1]
323
+ def change
324
+ add_check_constraint :users, "price > 0", name: "price_check"
325
+ end
326
+ end
327
+ ```
328
+
329
+ #### Good - Postgres
330
+
331
+ Add the check constraint without validating existing rows:
332
+
333
+ ```ruby
334
+ class AddCheckConstraint < ActiveRecord::Migration[6.1]
335
+ def change
336
+ add_check_constraint :users, "price > 0", name: "price_check", validate: false
337
+ end
338
+ end
339
+ ```
340
+
341
+ Then validate them in a separate migration.
342
+
343
+ ```ruby
344
+ class ValidateCheckConstraint < ActiveRecord::Migration[6.1]
345
+ def change
346
+ validate_check_constraint :users, name: "price_check"
347
+ end
348
+ end
349
+ ```
350
+
351
+ #### Good - MySQL and MariaDB
352
+
353
+ [Let us know](https://github.com/ankane/strong_migrations/issues/new) if you have a safe way to do this (check constraints can be added with `NOT ENFORCED`, but enforcing blocks writes).
354
+
312
355
  ### Setting NOT NULL on an existing column
313
356
 
314
357
  :turtle: Safe by default available
@@ -318,7 +361,7 @@ If you intend to drop an existing table, run `drop_table` first.
318
361
  Setting `NOT NULL` on an existing column blocks reads and writes while every row is checked.
319
362
 
320
363
  ```ruby
321
- class SetSomeColumnNotNull < ActiveRecord::Migration[6.0]
364
+ class SetSomeColumnNotNull < ActiveRecord::Migration[6.1]
322
365
  def change
323
366
  change_column_null :users, :some_column, false
324
367
  end
@@ -327,7 +370,19 @@ end
327
370
 
328
371
  #### Good - Postgres
329
372
 
330
- Instead, add a check constraint:
373
+ Instead, add a check constraint.
374
+
375
+ For Rails 6.1, use:
376
+
377
+ ```ruby
378
+ class SetSomeColumnNotNull < ActiveRecord::Migration[6.1]
379
+ def change
380
+ add_check_constraint :users, "some_column IS NOT NULL", name: "users_some_column_null", validate: false
381
+ end
382
+ end
383
+ ```
384
+
385
+ For Rails < 6.1, use:
331
386
 
332
387
  ```ruby
333
388
  class SetSomeColumnNotNull < ActiveRecord::Migration[6.0]
@@ -339,7 +394,23 @@ class SetSomeColumnNotNull < ActiveRecord::Migration[6.0]
339
394
  end
340
395
  ```
341
396
 
342
- Then validate it in a separate migration. A `NOT NULL` check constraint is [functionally equivalent](https://medium.com/doctolib/adding-a-not-null-constraint-on-pg-faster-with-minimal-locking-38b2c00c4d1c) to setting `NOT NULL` on the column, but it won’t show up in `schema.rb`. In Postgres 12+, once the check constraint is validated, you can safely set `NOT NULL` on the column and drop the check constraint.
397
+ Then validate it in a separate migration. A `NOT NULL` check constraint is [functionally equivalent](https://medium.com/doctolib/adding-a-not-null-constraint-on-pg-faster-with-minimal-locking-38b2c00c4d1c) to setting `NOT NULL` on the column (but it won’t show up in `schema.rb` in Rails < 6.1). In Postgres 12+, once the check constraint is validated, you can safely set `NOT NULL` on the column and drop the check constraint.
398
+
399
+ For Rails 6.1, use:
400
+
401
+ ```ruby
402
+ class ValidateSomeColumnNotNull < ActiveRecord::Migration[6.1]
403
+ def change
404
+ validate_check_constraint :users, name: "users_some_column_null"
405
+
406
+ # in Postgres 12+, you can then safely set NOT NULL on the column
407
+ change_column_null :users, :some_column, false
408
+ remove_check_constraint :users, name: "users_some_column_null"
409
+ end
410
+ end
411
+ ```
412
+
413
+ For Rails < 6.1, use:
343
414
 
344
415
  ```ruby
345
416
  class ValidateSomeColumnNotNull < ActiveRecord::Migration[6.0]
@@ -366,7 +437,7 @@ end
366
437
  Strong Migrations can’t ensure safety for raw SQL statements. Make really sure that what you’re doing is safe, then use:
367
438
 
368
439
  ```ruby
369
- class ExecuteSQL < ActiveRecord::Migration[6.0]
440
+ class ExecuteSQL < ActiveRecord::Migration[6.1]
370
441
  def change
371
442
  safety_assured { execute "..." }
372
443
  end
@@ -382,7 +453,7 @@ end
382
453
  In Postgres, adding an index non-concurrently blocks writes.
383
454
 
384
455
  ```ruby
385
- class AddSomeIndexToUsers < ActiveRecord::Migration[6.0]
456
+ class AddSomeIndexToUsers < ActiveRecord::Migration[6.1]
386
457
  def change
387
458
  add_index :users, :some_column
388
459
  end
@@ -394,7 +465,7 @@ end
394
465
  Add indexes concurrently.
395
466
 
396
467
  ```ruby
397
- class AddSomeIndexToUsers < ActiveRecord::Migration[6.0]
468
+ class AddSomeIndexToUsers < ActiveRecord::Migration[6.1]
398
469
  disable_ddl_transaction!
399
470
 
400
471
  def change
@@ -420,7 +491,7 @@ rails g index table column
420
491
  Rails adds an index non-concurrently to references by default, which blocks writes in Postgres.
421
492
 
422
493
  ```ruby
423
- class AddReferenceToUsers < ActiveRecord::Migration[6.0]
494
+ class AddReferenceToUsers < ActiveRecord::Migration[6.1]
424
495
  def change
425
496
  add_reference :users, :city
426
497
  end
@@ -432,7 +503,7 @@ end
432
503
  Make sure the index is added concurrently.
433
504
 
434
505
  ```ruby
435
- class AddReferenceToUsers < ActiveRecord::Migration[6.0]
506
+ class AddReferenceToUsers < ActiveRecord::Migration[6.1]
436
507
  disable_ddl_transaction!
437
508
 
438
509
  def change
@@ -450,7 +521,7 @@ end
450
521
  In Postgres, adding a foreign key blocks writes on both tables.
451
522
 
452
523
  ```ruby
453
- class AddForeignKeyOnUsers < ActiveRecord::Migration[6.0]
524
+ class AddForeignKeyOnUsers < ActiveRecord::Migration[6.1]
454
525
  def change
455
526
  add_foreign_key :users, :orders
456
527
  end
@@ -460,7 +531,7 @@ end
460
531
  or
461
532
 
462
533
  ```ruby
463
- class AddReferenceToUsers < ActiveRecord::Migration[6.0]
534
+ class AddReferenceToUsers < ActiveRecord::Migration[6.1]
464
535
  def change
465
536
  add_reference :users, :order, foreign_key: true
466
537
  end
@@ -474,7 +545,7 @@ Add the foreign key without validating existing rows, then validate them in a se
474
545
  For Rails 5.2+, use:
475
546
 
476
547
  ```ruby
477
- class AddForeignKeyOnUsers < ActiveRecord::Migration[6.0]
548
+ class AddForeignKeyOnUsers < ActiveRecord::Migration[6.1]
478
549
  def change
479
550
  add_foreign_key :users, :orders, validate: false
480
551
  end
@@ -484,7 +555,7 @@ end
484
555
  Then:
485
556
 
486
557
  ```ruby
487
- class ValidateForeignKeyOnUsers < ActiveRecord::Migration[6.0]
558
+ class ValidateForeignKeyOnUsers < ActiveRecord::Migration[6.1]
488
559
  def change
489
560
  validate_foreign_key :users, :orders
490
561
  end
@@ -522,7 +593,7 @@ end
522
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.
523
594
 
524
595
  ```ruby
525
- class AddPropertiesToUsers < ActiveRecord::Migration[6.0]
596
+ class AddPropertiesToUsers < ActiveRecord::Migration[6.1]
526
597
  def change
527
598
  add_column :users, :properties, :json
528
599
  end
@@ -534,7 +605,7 @@ end
534
605
  Use `jsonb` instead.
535
606
 
536
607
  ```ruby
537
- class AddPropertiesToUsers < ActiveRecord::Migration[6.0]
608
+ class AddPropertiesToUsers < ActiveRecord::Migration[6.1]
538
609
  def change
539
610
  add_column :users, :properties, :jsonb
540
611
  end
@@ -548,7 +619,7 @@ end
548
619
  Adding a non-unique index with more than three columns rarely improves performance.
549
620
 
550
621
  ```ruby
551
- class AddSomeIndexToUsers < ActiveRecord::Migration[6.0]
622
+ class AddSomeIndexToUsers < ActiveRecord::Migration[6.1]
552
623
  def change
553
624
  add_index :users, [:a, :b, :c, :d]
554
625
  end
@@ -560,7 +631,7 @@ end
560
631
  Instead, start an index with columns that narrow down the results the most.
561
632
 
562
633
  ```ruby
563
- class AddSomeIndexToUsers < ActiveRecord::Migration[6.0]
634
+ class AddSomeIndexToUsers < ActiveRecord::Migration[6.1]
564
635
  def change
565
636
  add_index :users, [:b, :d]
566
637
  end
@@ -574,7 +645,7 @@ For Postgres, be sure to add them concurrently.
574
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.
575
646
 
576
647
  ```ruby
577
- class MySafeMigration < ActiveRecord::Migration[6.0]
648
+ class MySafeMigration < ActiveRecord::Migration[6.1]
578
649
  def change
579
650
  safety_assured { remove_column :users, :some_column }
580
651
  end
@@ -591,6 +662,7 @@ Make operations safe by default.
591
662
 
592
663
  - adding and removing an index
593
664
  - adding a foreign key
665
+ - adding a check constraint
594
666
  - setting NOT NULL on an existing column
595
667
 
596
668
  Add to `config/initializers/strong_migrations.rb`:
@@ -216,6 +216,30 @@ end",
216
216
 
217
217
  validate_foreign_key:
218
218
  "Validating a foreign key while writes are blocked is dangerous.
219
+ Use disable_ddl_transaction! or a separate migration.",
220
+
221
+ add_check_constraint:
222
+ "Adding a check constraint key blocks reads and writes while every row is checked.
223
+ Instead, add the check constraint without validating existing rows,
224
+ then validate them in a separate migration.
225
+
226
+ class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
227
+ def change
228
+ %{add_check_constraint_code}
229
+ end
230
+ end
231
+
232
+ class Validate%{migration_name} < ActiveRecord::Migration%{migration_suffix}
233
+ def change
234
+ %{validate_check_constraint_code}
235
+ end
236
+ end",
237
+
238
+ add_check_constraint_mysql:
239
+ "Adding a check constraint to an existing table is not safe with your database engine.",
240
+
241
+ validate_check_constraint:
242
+ "Validating a check constraint while writes are blocked is dangerous.
219
243
  Use disable_ddl_transaction! or a separate migration."
220
244
  }
221
245
  self.enabled_checks = (error_messages.keys - [:remove_index]).map { |k| [k, {}] }.to_h
@@ -231,18 +231,38 @@ Then add the foreign key in separate migrations."
231
231
  validate_code = constraint_str("ALTER TABLE %s VALIDATE CONSTRAINT %s", [table, constraint_name])
232
232
  remove_code = constraint_str("ALTER TABLE %s DROP CONSTRAINT %s", [table, constraint_name])
233
233
 
234
- validate_constraint_code = String.new(safety_assured_str(validate_code))
234
+ validate_constraint_code =
235
+ if ar_version >= 6.1
236
+ String.new(command_str(:validate_check_constraint, [table, {name: constraint_name}]))
237
+ else
238
+ String.new(safety_assured_str(validate_code))
239
+ end
240
+
235
241
  if postgresql_version >= Gem::Version.new("12")
236
242
  change_args = [table, column, null]
237
243
 
238
244
  validate_constraint_code << "\n #{command_str(:change_column_null, change_args)}"
239
- validate_constraint_code << "\n #{safety_assured_str(remove_code)}"
245
+
246
+ if ar_version >= 6.1
247
+ validate_constraint_code << "\n #{command_str(:remove_check_constraint, [table, {name: constraint_name}])}"
248
+ else
249
+ validate_constraint_code << "\n #{safety_assured_str(remove_code)}"
250
+ end
240
251
  end
241
252
 
242
253
  return safe_change_column_null(add_code, validate_code, change_args, remove_code) if StrongMigrations.safe_by_default
243
254
 
255
+ add_constraint_code =
256
+ if ar_version >= 6.1
257
+ # only quote when needed
258
+ expr_column = column.to_s =~ /\A[a-z0-9_]+\z/ ? column : connection.quote_column_name(column)
259
+ command_str(:add_check_constraint, [table, "#{expr_column} IS NOT NULL", {name: constraint_name, validate: false}])
260
+ else
261
+ safety_assured_str(add_code)
262
+ end
263
+
244
264
  raise_error :change_column_null_postgresql,
245
- add_constraint_code: safety_assured_str(add_code),
265
+ add_constraint_code: add_constraint_code,
246
266
  validate_constraint_code: validate_constraint_code
247
267
  end
248
268
  elsif mysql? || mariadb?
@@ -257,10 +277,10 @@ Then add the foreign key in separate migrations."
257
277
  options ||= {}
258
278
 
259
279
  # always validated before 5.2
260
- validate = options.fetch(:validate, true) || ActiveRecord::VERSION::STRING < "5.2"
280
+ validate = options.fetch(:validate, true) || ar_version < 5.2
261
281
 
262
282
  if postgresql? && validate
263
- if ActiveRecord::VERSION::STRING < "5.2"
283
+ if ar_version < 5.2
264
284
  # fk name logic from rails
265
285
  primary_key = options[:primary_key] || "id"
266
286
  column = options[:column] || "#{to_table.to_s.singularize}_id"
@@ -287,6 +307,29 @@ Then add the foreign key in separate migrations."
287
307
  if postgresql? && writes_blocked?
288
308
  raise_error :validate_foreign_key
289
309
  end
310
+ when :add_check_constraint
311
+ table, expression, options = args
312
+ options ||= {}
313
+
314
+ if !new_table?(table)
315
+ if postgresql? && options[:validate] != false
316
+ add_options = options.merge(validate: false)
317
+ name = options[:name] || @migration.check_constraint_options(table, expression, options)[:name]
318
+ validate_options = {name: name}
319
+
320
+ return safe_add_check_constraint(table, expression, add_options, validate_options) if StrongMigrations.safe_by_default
321
+
322
+ raise_error :add_check_constraint,
323
+ add_check_constraint_code: command_str("add_check_constraint", [table, expression, add_options]),
324
+ validate_check_constraint_code: command_str("validate_check_constraint", [table, validate_options])
325
+ elsif mysql? || mariadb?
326
+ raise_error :add_check_constraint_mysql
327
+ end
328
+ end
329
+ when :validate_check_constraint
330
+ if postgresql? && writes_blocked?
331
+ raise_error :validate_check_constraint
332
+ end
290
333
  end
291
334
 
292
335
  StrongMigrations.checks.each do |check|
@@ -410,6 +453,10 @@ Then add the foreign key in separate migrations."
410
453
  Gem::Version.new(version)
411
454
  end
412
455
 
456
+ def ar_version
457
+ ActiveRecord::VERSION::STRING.to_f
458
+ end
459
+
413
460
  def check_lock_timeout
414
461
  limit = StrongMigrations.lock_timeout_limit
415
462
 
@@ -1,7 +1,7 @@
1
1
  module StrongMigrations
2
2
  module SafeMethods
3
3
  def safe_by_default_method?(method)
4
- StrongMigrations.safe_by_default && [:add_index, :add_belongs_to, :add_reference, :remove_index, :add_foreign_key, :change_column_null].include?(method)
4
+ StrongMigrations.safe_by_default && [:add_index, :add_belongs_to, :add_reference, :remove_index, :add_foreign_key, :add_check_constraint, :change_column_null].include?(method)
5
5
  end
6
6
 
7
7
  # TODO check if invalid index with expected name exists and remove if needed
@@ -67,6 +67,19 @@ module StrongMigrations
67
67
  end
68
68
  end
69
69
 
70
+ def safe_add_check_constraint(table, expression, add_options, validate_options)
71
+ @migration.reversible do |dir|
72
+ dir.up do
73
+ @migration.add_check_constraint(table, expression, **add_options)
74
+ disable_transaction
75
+ @migration.validate_check_constraint(table, **validate_options)
76
+ end
77
+ dir.down do
78
+ @migration.remove_check_constraint(table, expression, **add_options)
79
+ end
80
+ end
81
+ end
82
+
70
83
  def safe_change_column_null(add_code, validate_code, change_args, remove_code)
71
84
  @migration.reversible do |dir|
72
85
  dir.up do
@@ -1,3 +1,3 @@
1
1
  module StrongMigrations
2
- VERSION = "0.7.4"
2
+ VERSION = "0.7.5"
3
3
  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
4
+ version: 0.7.5
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-12-16 00:00:00.000000000 Z
13
+ date: 2021-01-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -138,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
138
  - !ruby/object:Gem::Version
139
139
  version: '0'
140
140
  requirements: []
141
- rubygems_version: 3.2.0.rc.1
141
+ rubygems_version: 3.2.3
142
142
  signing_key:
143
143
  specification_version: 4
144
144
  summary: Catch unsafe migrations in development