strong_migrations 2.3.0 → 2.5.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3538811c535186c2757c2e92a56ec753c77842a99728a727aabe323dd8852182
4
- data.tar.gz: 6d33a69582e57e3035d7ef540894ce0020957aef8d4e081e693552615ac9af8b
3
+ metadata.gz: 971d5d1eabb91dc04c72cc99a24f8b92f1b0d31d8d28369577f48c283b8d8624
4
+ data.tar.gz: '08a413578f564ada7f9768aeaf469719ca051e4c37057be6324e593c73fb3144'
5
5
  SHA512:
6
- metadata.gz: 50a4b8ea0d0677bc0d5a3fa740f9f2e8b00acee0e673abaf7197c0c89540165ecb0cad913ed4244b61e3ac23342d4c44b8209991dea3841ee6dd7d7fbef827e3
7
- data.tar.gz: fd6d44273d6365ca9e33a246e072a24da93191bfc73b5d425df22c0b3b6523ce218d6aa6360dd6a8fcbcf88b5a06bf41c7221ccdceb69f26b734510cd38876f7
6
+ metadata.gz: b8ca27268e166609ec8253ce686c6fe9cbe6d7c4b298f8c80ce7f1690e76a2c997fad2806cce52c9765f6ee92e7e389fdf6c830d3ca8ebb0241574adc02c4b57
7
+ data.tar.gz: 18731d2b1bdd12698d6b860a470249a24ea12aaa0b5b74b6510d41527ef2126c46b27ef4aa7c7adb1437bd7a006d0bb7c46490d24ec15720009723e5b0d8eca4
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## 2.5.0 (2025-07-27)
2
+
3
+ - Added check for `rename_schema`
4
+ - Made `auto_analyze` apply to `add_reference`
5
+
6
+ ## 2.4.0 (2025-06-23)
7
+
8
+ - Added `remove_invalid_indexes` option to install generator
9
+ - Added experimental `transaction_timeout` option
10
+ - Dropped support for Ruby < 3.2 and Active Record < 7.1
11
+
1
12
  ## 2.3.0 (2025-04-03)
2
13
 
3
14
  - Added check for `change_column` for columns with check constraints with Postgres
data/README.md CHANGED
@@ -80,6 +80,7 @@ Postgres-specific checks:
80
80
  - [adding a json column](#adding-a-json-column)
81
81
  - [setting NOT NULL on an existing column](#setting-not-null-on-an-existing-column)
82
82
  - [adding a column with a volatile default value](#adding-a-column-with-a-volatile-default-value)
83
+ - [renaming a schema](#renaming-a-schema)
83
84
 
84
85
  Config-specific checks:
85
86
 
@@ -658,6 +659,31 @@ end
658
659
 
659
660
  Then [backfill the data](#backfilling-data).
660
661
 
662
+ ### Renaming a schema
663
+
664
+ #### Bad
665
+
666
+ Renaming a schema that’s in use will cause errors in your application.
667
+
668
+ ```ruby
669
+ class RenameUsersToCustomers < ActiveRecord::Migration[8.1]
670
+ def change
671
+ rename_schema :users, :customers
672
+ end
673
+ end
674
+ ```
675
+
676
+ #### Good
677
+
678
+ A safer approach is to:
679
+
680
+ 1. Create a new schema
681
+ 2. Write to both schemas
682
+ 3. Backfill data from the old schema to the new schema
683
+ 4. Move reads from the old schema to the new schema
684
+ 5. Stop writing to the old schema
685
+ 6. Drop the old schema
686
+
661
687
  ### Changing the default value of a column
662
688
 
663
689
  #### Bad
@@ -882,8 +908,6 @@ To automatically remove the invalid index when the migration runs again, use:
882
908
  StrongMigrations.remove_invalid_indexes = true
883
909
  ```
884
910
 
885
- Note: This feature is experimental.
886
-
887
911
  ## Lock Timeout Retries
888
912
 
889
913
  Note: This feature is experimental.
@@ -20,6 +20,9 @@ StrongMigrations.auto_analyze = true
20
20
  # end
21
21
  # end<% if postgresql? %>
22
22
 
23
+ # Remove invalid indexes when rerunning migrations
24
+ # StrongMigrations.remove_invalid_indexes = true
25
+
23
26
  # Make some operations safe by default
24
27
  # See https://github.com/ankane/strong_migrations#safe-by-default
25
28
  # StrongMigrations.safe_by_default = true<% end %>
@@ -16,6 +16,10 @@ module StrongMigrations
16
16
  # do nothing
17
17
  end
18
18
 
19
+ def set_transaction_timeout(timeout)
20
+ # do nothing
21
+ end
22
+
19
23
  def set_lock_timeout(timeout)
20
24
  # do nothing
21
25
  end
@@ -23,6 +23,11 @@ module StrongMigrations
23
23
  set_timeout("statement_timeout", timeout)
24
24
  end
25
25
 
26
+ def set_transaction_timeout(timeout)
27
+ # TODO make sure true version supports it as well?
28
+ set_timeout("transaction_timeout", timeout) if server_version >= Gem::Version.new("17")
29
+ end
30
+
26
31
  def set_lock_timeout(timeout)
27
32
  set_timeout("lock_timeout", timeout)
28
33
  end
@@ -127,21 +132,6 @@ module StrongMigrations
127
132
  safe
128
133
  end
129
134
 
130
- # TODO remove when Active Record < 7.1 is no longer supported
131
- def index_invalid?(table_name, index_name)
132
- query = <<~SQL
133
- SELECT
134
- indisvalid
135
- FROM
136
- pg_index
137
- WHERE
138
- indrelid = to_regclass(#{connection.quote(connection.quote_table_name(table_name))}) AND
139
- indexrelid = to_regclass(#{connection.quote(connection.quote_table_name(index_name))}) AND
140
- indisvalid = false
141
- SQL
142
- select_all(query.squish).any?
143
- end
144
-
145
135
  def writes_blocked?
146
136
  query = <<~SQL
147
137
  SELECT
@@ -79,6 +79,8 @@ module StrongMigrations
79
79
  check_remove_index(*args)
80
80
  when :rename_column
81
81
  check_rename_column
82
+ when :rename_schema
83
+ check_rename_schema
82
84
  when :rename_table
83
85
  check_rename_table
84
86
  when :validate_check_constraint
@@ -111,7 +113,7 @@ module StrongMigrations
111
113
  end
112
114
 
113
115
  # outdated statistics + a new index can hurt performance of existing queries
114
- if StrongMigrations.auto_analyze && direction == :up && method == :add_index
116
+ if StrongMigrations.auto_analyze && direction == :up && adds_index?(method, *args)
115
117
  adapter.analyze_table(args[0])
116
118
  end
117
119
 
@@ -181,6 +183,9 @@ module StrongMigrations
181
183
  if StrongMigrations.statement_timeout
182
184
  adapter.set_statement_timeout(StrongMigrations.statement_timeout)
183
185
  end
186
+ if StrongMigrations.transaction_timeout
187
+ adapter.set_transaction_timeout(StrongMigrations.transaction_timeout)
188
+ end
184
189
  if StrongMigrations.lock_timeout
185
190
  adapter.set_lock_timeout(StrongMigrations.lock_timeout)
186
191
  end
@@ -253,6 +258,18 @@ module StrongMigrations
253
258
  end
254
259
  end
255
260
 
261
+ def adds_index?(method, *args)
262
+ case method
263
+ when :add_index
264
+ true
265
+ when :add_reference, :add_belongs_to
266
+ options = args.extract_options!
267
+ !!options.fetch(:index, true)
268
+ else
269
+ false
270
+ end
271
+ end
272
+
256
273
  # REINDEX INDEX CONCURRENTLY leaves a new invalid index if it fails, so use remove_index instead
257
274
  def remove_invalid_index_if_needed(*args)
258
275
  options = args.extract_options!
@@ -264,9 +281,6 @@ module StrongMigrations
264
281
  table, columns = args
265
282
  index_name = options.fetch(:name, connection.index_name(table, columns))
266
283
 
267
- # valid option is ignored for Active Record < 7.1, so check name as well
268
- return if ar_version < 7.1 && !adapter.index_invalid?(table, index_name)
269
-
270
284
  @migration.say("Attempting to remove invalid index")
271
285
  without_retries do
272
286
  # TODO pass index schema for extra safety?
@@ -384,6 +384,10 @@ module StrongMigrations
384
384
  raise_error :rename_column
385
385
  end
386
386
 
387
+ def check_rename_schema
388
+ raise_error :rename_schema
389
+ end
390
+
387
391
  def check_rename_table
388
392
  raise_error :rename_table
389
393
  end
@@ -102,6 +102,17 @@ in your application. A safer approach is to:
102
102
  5. Stop writing to the old column
103
103
  6. Drop the old column",
104
104
 
105
+ rename_schema:
106
+ "Renaming a schema that's in use will cause errors
107
+ in your application. A safer approach is to:
108
+
109
+ 1. Create a new schema
110
+ 2. Write to both schemas
111
+ 3. Backfill data from the old schema to the new schema
112
+ 4. Move reads from the old schema to the new schema
113
+ 5. Stop writing to the old schema
114
+ 6. Drop the old schema",
115
+
105
116
  rename_table:
106
117
  "Renaming a table that's in use will cause errors
107
118
  in your application. A safer approach is to:
@@ -7,10 +7,7 @@ module StrongMigrations
7
7
  end
8
8
 
9
9
  def method_missing(method, *args)
10
- return super if is_a?(ActiveRecord::Schema)
11
-
12
- # Active Record 7.0.2+ versioned schema
13
- return super if defined?(ActiveRecord::Schema::Definition) && is_a?(ActiveRecord::Schema::Definition)
10
+ return super if is_a?(ActiveRecord::Schema) || is_a?(ActiveRecord::Schema::Definition)
14
11
 
15
12
  catch(:safe) do
16
13
  strong_migrations_checker.perform(method, *args) do
@@ -4,7 +4,7 @@ module StrongMigrations
4
4
  return super unless StrongMigrations.lock_timeout_retries > 0 && use_transaction?(migration)
5
5
 
6
6
  # handle MigrationProxy class
7
- migration = migration.send(:migration) if migration.respond_to?(:migration, true)
7
+ migration = migration.send(:migration) if !migration.is_a?(ActiveRecord::Migration) && migration.respond_to?(:migration, true)
8
8
 
9
9
  checker = migration.send(:strong_migrations_checker)
10
10
  return super if checker.skip?
@@ -46,8 +46,6 @@ module StrongMigrations
46
46
  def safe_add_foreign_key(from_table, to_table, *args, **options)
47
47
  @migration.reversible do |dir|
48
48
  dir.up do
49
- # validate option is unintentionally ignored for Active Record < 7.1
50
- # https://github.com/rails/rails/pull/45896
51
49
  if !connection.foreign_key_exists?(from_table, to_table, **options.merge(validate: false))
52
50
  @migration.add_foreign_key(from_table, to_table, *args, **options.merge(validate: false))
53
51
  end
@@ -1,3 +1,3 @@
1
1
  module StrongMigrations
2
- VERSION = "2.3.0"
2
+ VERSION = "2.5.0"
3
3
  end
@@ -29,7 +29,7 @@ module StrongMigrations
29
29
  :target_postgresql_version, :target_mysql_version, :target_mariadb_version,
30
30
  :enabled_checks, :lock_timeout, :statement_timeout, :check_down, :target_version,
31
31
  :safe_by_default, :target_sql_mode, :lock_timeout_retries, :lock_timeout_retry_delay,
32
- :alphabetize_schema, :skipped_databases, :remove_invalid_indexes
32
+ :alphabetize_schema, :skipped_databases, :remove_invalid_indexes, :transaction_timeout
33
33
  attr_writer :lock_timeout_limit
34
34
  end
35
35
  self.auto_analyze = false
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: 2.3.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
@@ -9,7 +9,7 @@ authors:
9
9
  - David Waller
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-04-03 00:00:00.000000000 Z
12
+ date: 1980-01-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: '7'
20
+ version: '7.1'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: '7'
27
+ version: '7.1'
28
28
  email:
29
29
  - andrew@ankane.org
30
30
  - bob.remeika@gmail.com
@@ -65,14 +65,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '3.1'
68
+ version: '3.2'
69
69
  required_rubygems_version: !ruby/object:Gem::Requirement
70
70
  requirements:
71
71
  - - ">="
72
72
  - !ruby/object:Gem::Version
73
73
  version: '0'
74
74
  requirements: []
75
- rubygems_version: 3.6.2
75
+ rubygems_version: 3.6.9
76
76
  specification_version: 4
77
77
  summary: Catch unsafe migrations in development
78
78
  test_files: []