online_migrations 0.8.2 → 0.9.0

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: b4f89ce12461dd3b786e98ecbc1afc315a5013a0967e90b9307d47b080924723
4
- data.tar.gz: 797f19c861514e843a7d6e6f3222d19f36b77fc30ff3cc1ac2808591fa339f75
3
+ metadata.gz: 3f7396712072756a2c7de52a7057f0c46da8ce26bf59270f0f2dea42bf43d0b3
4
+ data.tar.gz: a3a26397aa2a279e996e8af2e7c698ebabc73ee38bad89b84e98cbddb609feb4
5
5
  SHA512:
6
- metadata.gz: c4458f5096fc180bb27411fc800db6dce588473373c0945abf2121b67591dc031badb498582681e55128055a85105600be1de8851818e93bf1108f42d43dd24c
7
- data.tar.gz: ec49dd203d5ded9638d623af2b35b6ca1980a182a54ecf57bcbaf9d910cfe8f3e2cbd0f90c7e4d94f76236be91ef373b50e29a65e59be6e12ef6b55ad21de91b
6
+ metadata.gz: d897c787f1b4e23436ecc362dd49a97eba529e7f0613fe71d38b4fde1cd740a40e0fa6ba2ef59d32f0ab6c1050ebc98728a1830d22679f98671305e1d82d6eb3
7
+ data.tar.gz: 10c2d6cc695042052c994111f71df5e19d17cf2b81a72b4ca2bce835ecced1a91dad0bfe5d2091079661c1d97dbbf066e641b80ceca196be7dd5c0e859f8ea09
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  ## master (unreleased)
2
2
 
3
+ ## 0.9.0 (2023-10-27)
4
+
5
+ - Add ability to use custom raw sql for `backfill_column_for_type_change`'s `type_cast_function`
6
+
7
+ ```ruby
8
+ backfill_column_for_type_change(:users, :company_id, type_cast_function: Arel.sql("company_id::integer"))
9
+ ```
10
+
11
+ - Fix version safety with `revert`
12
+
3
13
  ## 0.8.2 (2023-09-26)
4
14
 
5
15
  - Promote check constraint to `NOT NULL` on PostgreSQL >= 12 when changing column type
data/README.md CHANGED
@@ -55,7 +55,7 @@ An operation is classified as dangerous if it either:
55
55
  Consider the following migration:
56
56
 
57
57
  ```ruby
58
- class AddAdminToUsers < ActiveRecord::Migration[7.0]
58
+ class AddAdminToUsers < ActiveRecord::Migration[7.1]
59
59
  def change
60
60
  add_column :users, :admin, :boolean, default: false, null: false
61
61
  end
@@ -67,7 +67,7 @@ If the `users` table is large, running this migration on a live PostgreSQL < 11
67
67
  A safer approach would be to run something like the following:
68
68
 
69
69
  ```ruby
70
- class AddAdminToUsers < ActiveRecord::Migration[7.0]
70
+ class AddAdminToUsers < ActiveRecord::Migration[7.1]
71
71
  # Do not wrap the migration in a transaction so that locks are held for a shorter time.
72
72
  disable_ddl_transaction!
73
73
 
@@ -112,7 +112,7 @@ A safer approach is to:
112
112
 
113
113
  add_column_with_default takes care of all this steps:
114
114
 
115
- class AddAdminToUsers < ActiveRecord::Migration[7.0]
115
+ class AddAdminToUsers < ActiveRecord::Migration[7.1]
116
116
  disable_ddl_transaction!
117
117
 
118
118
  def change
@@ -166,7 +166,7 @@ You can also add [custom checks](#custom-checks) or [disable specific checks](#d
166
166
  Active Record caches database columns at runtime, so if you drop a column, it can cause exceptions until your app reboots.
167
167
 
168
168
  ```ruby
169
- class RemoveNameFromUsers < ActiveRecord::Migration[7.0]
169
+ class RemoveNameFromUsers < ActiveRecord::Migration[7.1]
170
170
  def change
171
171
  remove_column :users, :name
172
172
  end
@@ -195,7 +195,7 @@ end
195
195
  3. Wrap column removing in a `safety_assured` block:
196
196
 
197
197
  ```ruby
198
- class RemoveNameFromUsers < ActiveRecord::Migration[7.0]
198
+ class RemoveNameFromUsers < ActiveRecord::Migration[7.1]
199
199
  def change
200
200
  safety_assured { remove_column :users, :name }
201
201
  end
@@ -212,7 +212,7 @@ end
212
212
  In earlier versions of PostgreSQL adding a column with a non-null default value to an existing table blocks reads and writes while the entire table is rewritten.
213
213
 
214
214
  ```ruby
215
- class AddAdminToUsers < ActiveRecord::Migration[7.0]
215
+ class AddAdminToUsers < ActiveRecord::Migration[7.1]
216
216
  def change
217
217
  add_column :users, :admin, :boolean, default: false
218
218
  end
@@ -232,7 +232,7 @@ A safer approach is to:
232
232
  `add_column_with_default` helper takes care of all this steps:
233
233
 
234
234
  ```ruby
235
- class AddAdminToUsers < ActiveRecord::Migration[7.0]
235
+ class AddAdminToUsers < ActiveRecord::Migration[7.1]
236
236
  disable_ddl_transaction!
237
237
 
238
238
  def change
@@ -250,7 +250,7 @@ end
250
250
  Active Record wraps each migration in a transaction, 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/).
251
251
 
252
252
  ```ruby
253
- class AddAdminToUsers < ActiveRecord::Migration[7.0]
253
+ class AddAdminToUsers < ActiveRecord::Migration[7.1]
254
254
  def change
255
255
  add_column :users, :admin, :boolean
256
256
  User.update_all(admin: false)
@@ -265,13 +265,13 @@ Also, running a single query to update data can cause issues for large tables.
265
265
  There are three keys to backfilling safely: batching, throttling, and running it outside a transaction. Use a `update_column_in_batches` helper in a separate migration with `disable_ddl_transaction!`.
266
266
 
267
267
  ```ruby
268
- class AddAdminToUsers < ActiveRecord::Migration[7.0]
268
+ class AddAdminToUsers < ActiveRecord::Migration[7.1]
269
269
  def change
270
270
  add_column :users, :admin, :boolean
271
271
  end
272
272
  end
273
273
 
274
- class BackfillUsersAdminColumn < ActiveRecord::Migration[7.0]
274
+ class BackfillUsersAdminColumn < ActiveRecord::Migration[7.1]
275
275
  disable_ddl_transaction!
276
276
 
277
277
  def up
@@ -290,7 +290,7 @@ end
290
290
  Changing the type of an existing column blocks reads and writes while the entire table is rewritten.
291
291
 
292
292
  ```ruby
293
- class ChangeFilesSizeType < ActiveRecord::Migration[7.0]
293
+ class ChangeFilesSizeType < ActiveRecord::Migration[7.1]
294
294
  def change
295
295
  change_column :files, :size, :bigint
296
296
  end
@@ -323,7 +323,7 @@ A safer approach can be accomplished in several steps:
323
323
  1. Create a new column and keep column's data in sync:
324
324
 
325
325
  ```ruby
326
- class InitializeChangeFilesSizeType < ActiveRecord::Migration[7.0]
326
+ class InitializeChangeFilesSizeType < ActiveRecord::Migration[7.1]
327
327
  def change
328
328
  initialize_column_type_change :files, :size, :bigint
329
329
  end
@@ -336,7 +336,7 @@ which will be passed to `add_column` when creating a new column, so you can over
336
336
  2. Backfill data from the old column to the new column:
337
337
 
338
338
  ```ruby
339
- class BackfillChangeFilesSizeType < ActiveRecord::Migration[7.0]
339
+ class BackfillChangeFilesSizeType < ActiveRecord::Migration[7.1]
340
340
  disable_ddl_transaction!
341
341
 
342
342
  def up
@@ -352,7 +352,7 @@ which will be passed to `add_column` when creating a new column, so you can over
352
352
  3. Copy indexes, foreign keys, check constraints, NOT NULL constraint, swap new column in place:
353
353
 
354
354
  ```ruby
355
- class FinalizeChangeFilesSizeType < ActiveRecord::Migration[7.0]
355
+ class FinalizeChangeFilesSizeType < ActiveRecord::Migration[7.1]
356
356
  disable_ddl_transaction!
357
357
 
358
358
  def change
@@ -365,7 +365,7 @@ which will be passed to `add_column` when creating a new column, so you can over
365
365
  5. Finally, if everything is working as expected, remove copy trigger and old column:
366
366
 
367
367
  ```ruby
368
- class CleanupChangeFilesSizeType < ActiveRecord::Migration[7.0]
368
+ class CleanupChangeFilesSizeType < ActiveRecord::Migration[7.1]
369
369
  def up
370
370
  cleanup_column_type_change :files, :size
371
371
  end
@@ -385,7 +385,7 @@ which will be passed to `add_column` when creating a new column, so you can over
385
385
  Renaming a column that's in use will cause errors in your application.
386
386
 
387
387
  ```ruby
388
- class RenameUsersNameToFirstName < ActiveRecord::Migration[7.0]
388
+ class RenameUsersNameToFirstName < ActiveRecord::Migration[7.1]
389
389
  def change
390
390
  rename_column :users, :name, :first_name
391
391
  end
@@ -454,7 +454,7 @@ nor any data/indexes/foreign keys copying will be made, so will be instantaneous
454
454
  It will use a combination of a VIEW and column aliasing to work with both column names simultaneously
455
455
 
456
456
  ```ruby
457
- class InitializeRenameUsersNameToFirstName < ActiveRecord::Migration[7.0]
457
+ class InitializeRenameUsersNameToFirstName < ActiveRecord::Migration[7.1]
458
458
  def change
459
459
  initialize_column_rename :users, :name, :first_name
460
460
  end
@@ -485,7 +485,7 @@ end
485
485
  9. Remove the VIEW created in step 3 and finally rename the column:
486
486
 
487
487
  ```ruby
488
- class FinalizeRenameUsersNameToFirstName < ActiveRecord::Migration[7.0]
488
+ class FinalizeRenameUsersNameToFirstName < ActiveRecord::Migration[7.1]
489
489
  def change
490
490
  finalize_column_rename :users, :name, :first_name
491
491
  end
@@ -501,7 +501,7 @@ end
501
501
  Renaming a table that's in use will cause errors in your application.
502
502
 
503
503
  ```ruby
504
- class RenameClientsToUsers < ActiveRecord::Migration[7.0]
504
+ class RenameClientsToUsers < ActiveRecord::Migration[7.1]
505
505
  def change
506
506
  rename_table :clients, :users
507
507
  end
@@ -556,7 +556,7 @@ OnlineMigrations.config.table_renames = {
556
556
  3. Create a VIEW:
557
557
 
558
558
  ```ruby
559
- class InitializeRenameClientsToUsers < ActiveRecord::Migration[7.0]
559
+ class InitializeRenameClientsToUsers < ActiveRecord::Migration[7.1]
560
560
  def change
561
561
  initialize_table_rename :clients, :users
562
562
  end
@@ -569,7 +569,7 @@ end
569
569
  7. Remove the VIEW created in step 3:
570
570
 
571
571
  ```ruby
572
- class FinalizeRenameClientsToUsers < ActiveRecord::Migration[7.0]
572
+ class FinalizeRenameClientsToUsers < ActiveRecord::Migration[7.1]
573
573
  def change
574
574
  finalize_table_rename :clients, :users
575
575
  end
@@ -585,7 +585,7 @@ end
585
585
  The `force` option can drop an existing table.
586
586
 
587
587
  ```ruby
588
- class CreateUsers < ActiveRecord::Migration[7.0]
588
+ class CreateUsers < ActiveRecord::Migration[7.1]
589
589
  def change
590
590
  create_table :users, force: true do |t|
591
591
  # ...
@@ -599,7 +599,7 @@ end
599
599
  Create tables without the `force` option.
600
600
 
601
601
  ```ruby
602
- class CreateUsers < ActiveRecord::Migration[7.0]
602
+ class CreateUsers < ActiveRecord::Migration[7.1]
603
603
  def change
604
604
  create_table :users do |t|
605
605
  # ...
@@ -617,7 +617,7 @@ If you intend to drop an existing table, run `drop_table` first.
617
617
  Adding a check constraint blocks reads and writes while every row is checked.
618
618
 
619
619
  ```ruby
620
- class AddCheckConstraint < ActiveRecord::Migration[7.0]
620
+ class AddCheckConstraint < ActiveRecord::Migration[7.1]
621
621
  def change
622
622
  add_check_constraint :users, "char_length(name) >= 1", name: "name_check"
623
623
  end
@@ -629,7 +629,7 @@ end
629
629
  Add the check constraint without validating existing rows, and then validate them in a separate transaction:
630
630
 
631
631
  ```ruby
632
- class AddCheckConstraint < ActiveRecord::Migration[7.0]
632
+ class AddCheckConstraint < ActiveRecord::Migration[7.1]
633
633
  disable_ddl_transaction!
634
634
 
635
635
  def change
@@ -648,7 +648,7 @@ end
648
648
  Setting `NOT NULL` on an existing column blocks reads and writes while every row is checked.
649
649
 
650
650
  ```ruby
651
- class ChangeUsersNameNull < ActiveRecord::Migration[7.0]
651
+ class ChangeUsersNameNull < ActiveRecord::Migration[7.1]
652
652
  def change
653
653
  change_column_null :users, :name, false
654
654
  end
@@ -660,7 +660,7 @@ end
660
660
  Instead, add a check constraint and validate it in a separate transaction:
661
661
 
662
662
  ```ruby
663
- class ChangeUsersNameNull < ActiveRecord::Migration[7.0]
663
+ class ChangeUsersNameNull < ActiveRecord::Migration[7.1]
664
664
  disable_ddl_transaction!
665
665
 
666
666
  def change
@@ -675,7 +675,7 @@ end
675
675
  A `NOT NULL` check constraint is functionally equivalent to setting `NOT NULL` on the column (but it won't show up in `schema.rb` in Rails < 6.1). In PostgreSQL 12+, once the check constraint is validated, you can safely set `NOT NULL` on the column and drop the check constraint.
676
676
 
677
677
  ```ruby
678
- class ChangeUsersNameNullDropCheck < ActiveRecord::Migration[7.0]
678
+ class ChangeUsersNameNullDropCheck < ActiveRecord::Migration[7.1]
679
679
  def change
680
680
  # in PostgreSQL 12+, you can then safely set NOT NULL on the column
681
681
  change_column_null :users, :name, false
@@ -689,7 +689,7 @@ end
689
689
  Online Migrations does not support inspecting what happens inside an `execute` call, so cannot help you here. Make really sure that what you're doing is safe before proceeding, then wrap it in a `safety_assured { ... }` block:
690
690
 
691
691
  ```ruby
692
- class ExecuteSQL < ActiveRecord::Migration[7.0]
692
+ class ExecuteSQL < ActiveRecord::Migration[7.1]
693
693
  def change
694
694
  safety_assured { execute "..." }
695
695
  end
@@ -703,7 +703,7 @@ end
703
703
  Adding an index non-concurrently blocks writes.
704
704
 
705
705
  ```ruby
706
- class AddIndexOnUsersEmail < ActiveRecord::Migration[7.0]
706
+ class AddIndexOnUsersEmail < ActiveRecord::Migration[7.1]
707
707
  def change
708
708
  add_index :users, :email, unique: true
709
709
  end
@@ -715,7 +715,7 @@ end
715
715
  Add indexes concurrently.
716
716
 
717
717
  ```ruby
718
- class AddIndexOnUsersEmail < ActiveRecord::Migration[7.0]
718
+ class AddIndexOnUsersEmail < ActiveRecord::Migration[7.1]
719
719
  disable_ddl_transaction!
720
720
 
721
721
  def change
@@ -733,7 +733,7 @@ end
733
733
  While actual removing of an index is usually fast, removing it non-concurrently tries to obtain an `ACCESS EXCLUSIVE` lock on the table, waiting for all existing queries to complete and blocking all the subsequent queries (even `SELECT`s) on that table until the lock is obtained and index is removed.
734
734
 
735
735
  ```ruby
736
- class RemoveIndexOnUsersEmail < ActiveRecord::Migration[7.0]
736
+ class RemoveIndexOnUsersEmail < ActiveRecord::Migration[7.1]
737
737
  def change
738
738
  remove_index :users, :email
739
739
  end
@@ -745,7 +745,7 @@ end
745
745
  Remove indexes concurrently.
746
746
 
747
747
  ```ruby
748
- class RemoveIndexOnUsersEmail < ActiveRecord::Migration[7.0]
748
+ class RemoveIndexOnUsersEmail < ActiveRecord::Migration[7.1]
749
749
  disable_ddl_transaction!
750
750
 
751
751
  def change
@@ -763,7 +763,7 @@ end
763
763
  Removing an old index before replacing it with the new one might result in slow queries while building the new index.
764
764
 
765
765
  ```ruby
766
- class AddIndexOnCreationToProjects < ActiveRecord::Migration[7.0]
766
+ class AddIndexOnCreationToProjects < ActiveRecord::Migration[7.1]
767
767
  disable_ddl_transaction!
768
768
 
769
769
  def change
@@ -780,7 +780,7 @@ end
780
780
  A safer approach is to create the new index and then delete the old one.
781
781
 
782
782
  ```ruby
783
- class AddIndexOnCreationToProjects < ActiveRecord::Migration[7.0]
783
+ class AddIndexOnCreationToProjects < ActiveRecord::Migration[7.1]
784
784
  disable_ddl_transaction!
785
785
 
786
786
  def change
@@ -797,7 +797,7 @@ end
797
797
  Rails adds an index non-concurrently to references by default, which blocks writes. Additionally, if `foreign_key` option (without `validate: false`) is provided, both tables are blocked while it is validated.
798
798
 
799
799
  ```ruby
800
- class AddUserToProjects < ActiveRecord::Migration[7.0]
800
+ class AddUserToProjects < ActiveRecord::Migration[7.1]
801
801
  def change
802
802
  add_reference :projects, :user, foreign_key: true
803
803
  end
@@ -810,7 +810,7 @@ Make sure the index is added concurrently and the foreign key is added in a sepa
810
810
  Or you can use `add_reference_concurrently` helper. It will create a reference and take care of safely adding index and/or foreign key.
811
811
 
812
812
  ```ruby
813
- class AddUserToProjects < ActiveRecord::Migration[7.0]
813
+ class AddUserToProjects < ActiveRecord::Migration[7.1]
814
814
  disable_ddl_transaction!
815
815
 
816
816
  def change
@@ -828,7 +828,7 @@ end
828
828
  Adding a foreign key blocks writes on both tables.
829
829
 
830
830
  ```ruby
831
- class AddForeignKeyToProjectsUser < ActiveRecord::Migration[7.0]
831
+ class AddForeignKeyToProjectsUser < ActiveRecord::Migration[7.1]
832
832
  def change
833
833
  add_foreign_key :projects, :users
834
834
  end
@@ -838,7 +838,7 @@ end
838
838
  or
839
839
 
840
840
  ```ruby
841
- class AddReferenceToProjectsUser < ActiveRecord::Migration[7.0]
841
+ class AddReferenceToProjectsUser < ActiveRecord::Migration[7.1]
842
842
  def change
843
843
  add_reference :projects, :user, foreign_key: true
844
844
  end
@@ -850,7 +850,7 @@ end
850
850
  Add the foreign key without validating existing rows, and then validate them in a separate transaction.
851
851
 
852
852
  ```ruby
853
- class AddForeignKeyToProjectsUser < ActiveRecord::Migration[7.0]
853
+ class AddForeignKeyToProjectsUser < ActiveRecord::Migration[7.1]
854
854
  disable_ddl_transaction!
855
855
 
856
856
  def change
@@ -927,7 +927,7 @@ end
927
927
  There's no equality operator for the `json` column type, which can cause errors for existing `SELECT DISTINCT` queries in your application.
928
928
 
929
929
  ```ruby
930
- class AddSettingsToProjects < ActiveRecord::Migration[7.0]
930
+ class AddSettingsToProjects < ActiveRecord::Migration[7.1]
931
931
  def change
932
932
  add_column :projects, :settings, :json
933
933
  end
@@ -939,7 +939,7 @@ end
939
939
  Use `jsonb` instead.
940
940
 
941
941
  ```ruby
942
- class AddSettingsToProjects < ActiveRecord::Migration[7.0]
942
+ class AddSettingsToProjects < ActiveRecord::Migration[7.1]
943
943
  def change
944
944
  add_column :projects, :settings, :jsonb
945
945
  end
@@ -953,7 +953,7 @@ end
953
953
  Adding a stored generated column causes the entire table to be rewritten. During this time, reads and writes are blocked.
954
954
 
955
955
  ```ruby
956
- class AddLowerEmailToUsers < ActiveRecord::Migration[7.0]
956
+ class AddLowerEmailToUsers < ActiveRecord::Migration[7.1]
957
957
  def change
958
958
  add_column :users, :lower_email, :virtual, type: :string, as: "LOWER(email)", stored: true
959
959
  end
@@ -971,7 +971,7 @@ Add a non-generated column and use callbacks or triggers instead.
971
971
  When using short integer types as primary key types, [there is a risk](https://m.signalvnoise.com/update-on-basecamp-3-being-stuck-in-read-only-as-of-nov-8-922am-cst/) of running out of IDs on inserts. The default type in Active Record < 5.1 for primary and foreign keys is `INTEGER`, which allows a little over of 2 billion records. Active Record 5.1 changed the default type to `BIGINT`.
972
972
 
973
973
  ```ruby
974
- class CreateUsers < ActiveRecord::Migration[7.0]
974
+ class CreateUsers < ActiveRecord::Migration[7.1]
975
975
  def change
976
976
  create_table :users, id: :integer do |t|
977
977
  # ...
@@ -985,7 +985,7 @@ end
985
985
  Use one of `bigint`, `bigserial`, `uuid` instead.
986
986
 
987
987
  ```ruby
988
- class CreateUsers < ActiveRecord::Migration[7.0]
988
+ class CreateUsers < ActiveRecord::Migration[7.1]
989
989
  def change
990
990
  create_table :users, id: :bigint do |t| # bigint is the default for Active Record >= 5.1
991
991
  # ...
@@ -1001,7 +1001,7 @@ end
1001
1001
  Hash index operations are not WAL-logged, so hash indexes might need to be rebuilt with `REINDEX` after a database crash if there were unwritten changes. Also, changes to hash indexes are not replicated over streaming or file-based replication after the initial base backup, so they give wrong answers to queries that subsequently use them. For these reasons, hash index use is discouraged.
1002
1002
 
1003
1003
  ```ruby
1004
- class AddIndexToUsersOnEmail < ActiveRecord::Migration[7.0]
1004
+ class AddIndexToUsersOnEmail < ActiveRecord::Migration[7.1]
1005
1005
  def change
1006
1006
  add_index :users, :email, unique: true, using: :hash
1007
1007
  end
@@ -1013,7 +1013,7 @@ end
1013
1013
  Use B-tree indexes instead.
1014
1014
 
1015
1015
  ```ruby
1016
- class AddIndexToUsersOnEmail < ActiveRecord::Migration[7.0]
1016
+ class AddIndexToUsersOnEmail < ActiveRecord::Migration[7.1]
1017
1017
  def change
1018
1018
  add_index :users, :email, unique: true # B-tree by default
1019
1019
  end
@@ -1028,7 +1028,7 @@ Adding multiple foreign keys in a single migration blocks reads and writes on al
1028
1028
  Avoid adding foreign key more than once per migration file, unless the source and target tables are identical.
1029
1029
 
1030
1030
  ```ruby
1031
- class CreateUserProjects < ActiveRecord::Migration[7.0]
1031
+ class CreateUserProjects < ActiveRecord::Migration[7.1]
1032
1032
  def change
1033
1033
  create_table :user_projects do |t|
1034
1034
  t.belongs_to :user, foreign_key: true
@@ -1043,7 +1043,7 @@ end
1043
1043
  Add additional foreign keys in separate migration files. See [adding a foreign key](#adding-a-foreign-key) for how to properly add foreign keys.
1044
1044
 
1045
1045
  ```ruby
1046
- class CreateUserProjects < ActiveRecord::Migration[7.0]
1046
+ class CreateUserProjects < ActiveRecord::Migration[7.1]
1047
1047
  def change
1048
1048
  create_table :user_projects do |t|
1049
1049
  t.belongs_to :user, foreign_key: true
@@ -1052,7 +1052,7 @@ class CreateUserProjects < ActiveRecord::Migration[7.0]
1052
1052
  end
1053
1053
  end
1054
1054
 
1055
- class AddForeignKeyFromUserProjectsToProject < ActiveRecord::Migration[7.0]
1055
+ class AddForeignKeyFromUserProjectsToProject < ActiveRecord::Migration[7.1]
1056
1056
  def change
1057
1057
  add_foreign_key :user_projects, :projects
1058
1058
  end
@@ -1069,7 +1069,7 @@ Remove all the foreign keys first.
1069
1069
  Assuming, `projects` has foreign keys on `users.id` and `repositories.id`:
1070
1070
 
1071
1071
  ```ruby
1072
- class DropProjects < ActiveRecord::Migration[7.0]
1072
+ class DropProjects < ActiveRecord::Migration[7.1]
1073
1073
  def change
1074
1074
  drop_table :projects
1075
1075
  end
@@ -1081,13 +1081,13 @@ end
1081
1081
  Remove all the foreign keys first:
1082
1082
 
1083
1083
  ```ruby
1084
- class RemoveProjectsUserFk < ActiveRecord::Migration[7.0]
1084
+ class RemoveProjectsUserFk < ActiveRecord::Migration[7.1]
1085
1085
  def change
1086
1086
  remove_foreign_key :projects, :users
1087
1087
  end
1088
1088
  end
1089
1089
 
1090
- class RemoveProjectsRepositoryFk < ActiveRecord::Migration[7.0]
1090
+ class RemoveProjectsRepositoryFk < ActiveRecord::Migration[7.1]
1091
1091
  def change
1092
1092
  remove_foreign_key :projects, :repositories
1093
1093
  end
@@ -1097,7 +1097,7 @@ end
1097
1097
  Then remove the table:
1098
1098
 
1099
1099
  ```ruby
1100
- class DropProjects < ActiveRecord::Migration[7.0]
1100
+ class DropProjects < ActiveRecord::Migration[7.1]
1101
1101
  def change
1102
1102
  drop_table :projects
1103
1103
  end
@@ -1114,7 +1114,7 @@ Otherwise, there's a risk of bugs caused by IDs representable by one type but no
1114
1114
  Assuming, there is a `users` table with `bigint` primary key type:
1115
1115
 
1116
1116
  ```ruby
1117
- class AddUserIdToProjects < ActiveRecord::Migration[7.0]
1117
+ class AddUserIdToProjects < ActiveRecord::Migration[7.1]
1118
1118
  def change
1119
1119
  add_column :projects, :user_id, :integer
1120
1120
  end
@@ -1128,7 +1128,7 @@ Add a reference column of the same type as a referenced primary key.
1128
1128
  Assuming, there is a `users` table with `bigint` primary key type:
1129
1129
 
1130
1130
  ```ruby
1131
- class AddUserIdToProjects < ActiveRecord::Migration[7.0]
1131
+ class AddUserIdToProjects < ActiveRecord::Migration[7.1]
1132
1132
  def change
1133
1133
  add_column :projects, :user_id, :bigint
1134
1134
  end
@@ -1142,7 +1142,7 @@ end
1142
1142
  Adding a single table inheritance column might cause errors in old instances of your application.
1143
1143
 
1144
1144
  ```ruby
1145
- class AddTypeToUsers < ActiveRecord::Migration[7.0]
1145
+ class AddTypeToUsers < ActiveRecord::Migration[7.1]
1146
1146
  def change
1147
1147
  add_column :users, :string, :type, default: "Member"
1148
1148
  end
@@ -1182,7 +1182,7 @@ A safer approach is to:
1182
1182
  Active Record < 7 enables partial writes by default, which can cause incorrect values to be inserted when changing the default value of a column.
1183
1183
 
1184
1184
  ```ruby
1185
- class ChangeSomeColumnDefault < ActiveRecord::Migration[7.0]
1185
+ class ChangeSomeColumnDefault < ActiveRecord::Migration[7.1]
1186
1186
  def change
1187
1187
  change_column_default :users, :some_column, from: "old", to: "new"
1188
1188
  end
@@ -1210,7 +1210,7 @@ config.active_record.partial_inserts = false
1210
1210
  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.
1211
1211
 
1212
1212
  ```ruby
1213
- class MySafeMigration < ActiveRecord::Migration[7.0]
1213
+ class MySafeMigration < ActiveRecord::Migration[7.1]
1214
1214
  def change
1215
1215
  safety_assured { remove_column :users, :some_column }
1216
1216
  end
data/docs/configuring.md CHANGED
@@ -154,7 +154,7 @@ This is useful to demystify `online_migrations` inner workings, and to better in
154
154
  Consider migration, running on PostgreSQL < 11:
155
155
 
156
156
  ```ruby
157
- class AddAdminToUsers < ActiveRecord::Migration[7.0]
157
+ class AddAdminToUsers < ActiveRecord::Migration[7.1]
158
158
  disable_ddl_transaction!
159
159
 
160
160
  def change
@@ -176,6 +176,7 @@ module OnlineMigrations
176
176
  #
177
177
  # @example With type casting
178
178
  # backfill_column_for_type_change(:users, :settings, type_cast_function: "jsonb")
179
+ # backfill_column_for_type_change(:users, :company_id, type_cast_function: Arel.sql("company_id::integer"))
179
180
  #
180
181
  # @example Additional batch options
181
182
  # backfill_column_for_type_change(:files, :size, batch_size: 10_000)
@@ -202,7 +203,13 @@ module OnlineMigrations
202
203
 
203
204
  old_value = Arel::Table.new(table_name)[column_name]
204
205
  if (type_cast_function = type_cast_functions.with_indifferent_access[column_name])
205
- old_value = Arel::Nodes::NamedFunction.new(type_cast_function.to_s, [old_value])
206
+ old_value =
207
+ case type_cast_function
208
+ when Arel::Nodes::SqlLiteral
209
+ type_cast_function
210
+ else
211
+ Arel::Nodes::NamedFunction.new(type_cast_function.to_s, [old_value])
212
+ end
206
213
  end
207
214
 
208
215
  [tmp_column, old_value]
@@ -48,6 +48,10 @@ module OnlineMigrations
48
48
  end
49
49
  ruby2_keywords(:check) if respond_to?(:ruby2_keywords, true)
50
50
 
51
+ def version_safe?
52
+ version && version <= OnlineMigrations.config.start_after
53
+ end
54
+
51
55
  private
52
56
  def check_database_version
53
57
  return if defined?(@database_version_checked)
@@ -107,7 +111,8 @@ module OnlineMigrations
107
111
  self.class.safe ||
108
112
  ENV["SAFETY_ASSURED"] ||
109
113
  (direction == :down && !OnlineMigrations.config.check_down) ||
110
- version <= OnlineMigrations.config.start_after
114
+ version_safe? ||
115
+ @migration.reverting?
111
116
  end
112
117
 
113
118
  def version
@@ -30,6 +30,15 @@ module OnlineMigrations
30
30
  end
31
31
  ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
32
32
 
33
+ # @private
34
+ def revert(*args)
35
+ if command_checker.version_safe?
36
+ safety_assured { super }
37
+ else
38
+ super
39
+ end
40
+ end
41
+
33
42
  # Mark a command in the migration as safe, despite using a method that might otherwise be dangerous.
34
43
  #
35
44
  # @example
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OnlineMigrations
4
- VERSION = "0.8.2"
4
+ VERSION = "0.9.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: online_migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - fatkodima
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-26 00:00:00.000000000 Z
11
+ date: 2023-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord