strong_migrations 1.8.0 → 2.0.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: f6462f35144a092664bb7456db2a1ad402695c6b5b1ba7001c1f1f977ea88d3e
4
- data.tar.gz: fc71c84ae237b8dbbd3413af7b47ab4fa9962dcbbdd6b3e99b9edd816d3ae009
3
+ metadata.gz: c963e6ef1e6a07f02f06e4a9838738df97014adaa3892bb8a8f11de2eb640455
4
+ data.tar.gz: f50bf92538e55ce8059340adc77ee4697656824b2ad2ca3f5a34a5b1ceb82bc5
5
5
  SHA512:
6
- metadata.gz: 2c4e5bf21e4bb42046fc2d4a530e40d9fc5f843db7c630779789934ec1a47965398e6b637707dc6a7106eb339ef26231ecfea73c312fd9a04f66f96504fcdc6a
7
- data.tar.gz: 542be70454fa38a8ad0c29e6bedcf670e54323ff8d9ae8f5eb59756476bbbaca6092a15f09c54163714e3db83261a8554e1fe51b00da8ad05ca7667a4612c3c8
6
+ metadata.gz: 04e219c413e77a0ac48465b9387f780d0c15e7e18871f9dfcddb6a8fb2a1cad990d0e612b22e141fdca2da8ead445d5fe8622fcf56648d1b3ff45bcdcfd18788
7
+ data.tar.gz: 95e7d2ef43b677e975f8ac1ee5ad81b165ea6e0558acbd60448addc085b1a96e39cbf37b288ffd92ae8862e2dbf53f0abb3f21de6f208b806b3c18c9d64977f0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 2.0.0 (2024-06-28)
2
+
3
+ - Improved install generator for Trilogy
4
+ - Fixed charset check for MariaDB 11.4
5
+ - Dropped support for Ruby < 3.1 and Active Record < 6.1
6
+ - Dropped support for Postgres < 12, MySQL < 8.0, and MariaDB < 10.5
7
+
1
8
  ## 1.8.0 (2024-03-11)
2
9
 
3
10
  - Added check for `add_column` with auto-incrementing columns
data/README.md CHANGED
@@ -64,7 +64,7 @@ Potentially dangerous operations:
64
64
  - [renaming a column](#renaming-a-column)
65
65
  - [renaming a table](#renaming-a-table)
66
66
  - [creating a table with the force option](#creating-a-table-with-the-force-option)
67
- - [adding an auto-incrementing column](#adding-an-auto-incrementing-column) [unreleased]
67
+ - [adding an auto-incrementing column](#adding-an-auto-incrementing-column)
68
68
  - [adding a stored generated column](#adding-a-stored-generated-column)
69
69
  - [adding a check constraint](#adding-a-check-constraint)
70
70
  - [executing SQL directly](#executing-SQL-directly)
@@ -79,7 +79,7 @@ Postgres-specific checks:
79
79
  - [adding an exclusion constraint](#adding-an-exclusion-constraint)
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
- - [adding a column with a default value](#adding-a-column-with-a-default-value)
82
+ - [adding a column with a volatile default value](#adding-a-column-with-a-volatile-default-value)
83
83
 
84
84
  Config-specific checks:
85
85
 
@@ -506,7 +506,7 @@ end
506
506
  In Postgres, adding a unique constraint creates a unique index, which blocks reads and writes.
507
507
 
508
508
  ```ruby
509
- class AddUniqueContraint < ActiveRecord::Migration[7.1]
509
+ class AddUniqueConstraint < ActiveRecord::Migration[7.1]
510
510
  def change
511
511
  add_unique_constraint :users, :some_column
512
512
  end
@@ -518,7 +518,7 @@ end
518
518
  Create a unique index concurrently, then use it for the constraint.
519
519
 
520
520
  ```ruby
521
- class AddUniqueContraint < ActiveRecord::Migration[7.1]
521
+ class AddUniqueConstraint < ActiveRecord::Migration[7.1]
522
522
  disable_ddl_transaction!
523
523
 
524
524
  def up
@@ -539,7 +539,7 @@ end
539
539
  In Postgres, adding an exclusion constraint blocks reads and writes while every row is checked.
540
540
 
541
541
  ```ruby
542
- class AddExclusionContraint < ActiveRecord::Migration[7.1]
542
+ class AddExclusionConstraint < ActiveRecord::Migration[7.1]
543
543
  def change
544
544
  add_exclusion_constraint :users, "number WITH =", using: :gist
545
545
  end
@@ -596,8 +596,6 @@ end
596
596
 
597
597
  Instead, add a check constraint.
598
598
 
599
- For Rails 6.1+, use:
600
-
601
599
  ```ruby
602
600
  class SetSomeColumnNotNull < ActiveRecord::Migration[7.1]
603
601
  def change
@@ -606,68 +604,32 @@ class SetSomeColumnNotNull < ActiveRecord::Migration[7.1]
606
604
  end
607
605
  ```
608
606
 
609
- For Rails < 6.1, use:
610
-
611
- ```ruby
612
- class SetSomeColumnNotNull < ActiveRecord::Migration[6.0]
613
- def change
614
- safety_assured do
615
- execute 'ALTER TABLE "users" ADD CONSTRAINT "users_some_column_null" CHECK ("some_column" IS NOT NULL) NOT VALID'
616
- end
617
- end
618
- end
619
- ```
620
-
621
- 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.
622
-
623
- For Rails 6.1+, use:
607
+ Then validate it in a separate migration. Once the check constraint is validated, you can safely set `NOT NULL` on the column and drop the check constraint.
624
608
 
625
609
  ```ruby
626
610
  class ValidateSomeColumnNotNull < ActiveRecord::Migration[7.1]
627
611
  def change
628
612
  validate_check_constraint :users, name: "users_some_column_null"
629
-
630
- # in Postgres 12+, you can then safely set NOT NULL on the column
631
613
  change_column_null :users, :some_column, false
632
614
  remove_check_constraint :users, name: "users_some_column_null"
633
615
  end
634
616
  end
635
617
  ```
636
618
 
637
- For Rails < 6.1, use:
638
-
639
- ```ruby
640
- class ValidateSomeColumnNotNull < ActiveRecord::Migration[6.0]
641
- def change
642
- safety_assured do
643
- execute 'ALTER TABLE "users" VALIDATE CONSTRAINT "users_some_column_null"'
644
- end
645
-
646
- # in Postgres 12+, you can then safely set NOT NULL on the column
647
- change_column_null :users, :some_column, false
648
- safety_assured do
649
- execute 'ALTER TABLE "users" DROP CONSTRAINT "users_some_column_null"'
650
- end
651
- end
652
- end
653
- ```
654
-
655
- ### Adding a column with a default value
619
+ ### Adding a column with a volatile default value
656
620
 
657
621
  #### Bad
658
622
 
659
- In earlier versions of Postgres, 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.
623
+ Adding a column with a volatile default value to an existing table causes the entire table to be rewritten. During this time, reads and writes are blocked.
660
624
 
661
625
  ```ruby
662
626
  class AddSomeColumnToUsers < ActiveRecord::Migration[7.1]
663
627
  def change
664
- add_column :users, :some_column, :text, default: "default_value"
628
+ add_column :users, :some_column, :uuid, default: "gen_random_uuid()"
665
629
  end
666
630
  end
667
631
  ```
668
632
 
669
- In Postgres 11+, this no longer requires a table rewrite and is safe (except for volatile functions like `gen_random_uuid()`).
670
-
671
633
  #### Good
672
634
 
673
635
  Instead, add the column without a default value, then change the default.
@@ -675,8 +637,8 @@ Instead, add the column without a default value, then change the default.
675
637
  ```ruby
676
638
  class AddSomeColumnToUsers < ActiveRecord::Migration[7.1]
677
639
  def up
678
- add_column :users, :some_column, :text
679
- change_column_default :users, :some_column, "default_value"
640
+ add_column :users, :some_column, :uuid
641
+ change_column_default :users, :some_column, from: nil, to: "gen_random_uuid()"
680
642
  end
681
643
 
682
644
  def down
@@ -738,7 +700,7 @@ Instead, start an index with columns that narrow down the results the most.
738
700
  ```ruby
739
701
  class AddSomeIndexToUsers < ActiveRecord::Migration[7.1]
740
702
  def change
741
- add_index :users, [:b, :d]
703
+ add_index :users, [:d, :b]
742
704
  end
743
705
  end
744
706
  ```
@@ -925,14 +887,14 @@ Use the version from your latest migration.
925
887
  If your development database version is different from production, you can specify the production version so the right checks run in development.
926
888
 
927
889
  ```ruby
928
- StrongMigrations.target_version = 10 # or "8.0.12", "10.3.2", etc
890
+ StrongMigrations.target_version = 10 # or 8.0, 10.5, etc
929
891
  ```
930
892
 
931
- The major version works well for Postgres, while the full version is recommended for MySQL and MariaDB.
893
+ The major version works well for Postgres, while the major and minor version is recommended for MySQL and MariaDB.
932
894
 
933
895
  For safety, this option only affects development and test environments. In other environments, the actual server version is always used.
934
896
 
935
- If your app has multiple databases with different versions, with Rails 6.1+, you can use:
897
+ If your app has multiple databases with different versions, you can use:
936
898
 
937
899
  ```ruby
938
900
  StrongMigrations.target_version = {primary: 13, catalog: 15}
@@ -21,21 +21,17 @@ module StrongMigrations
21
21
 
22
22
  def target_version
23
23
  case adapter
24
- when /mysql/
24
+ when /mysql|trilogy/
25
25
  # could try to connect to database and check for MariaDB
26
26
  # but this should be fine
27
- '"8.0.12"'
27
+ "8.0"
28
28
  else
29
29
  "10"
30
30
  end
31
31
  end
32
32
 
33
33
  def adapter
34
- if ActiveRecord::VERSION::STRING.to_f >= 6.1
35
- ActiveRecord::Base.connection_db_config.adapter.to_s
36
- else
37
- ActiveRecord::Base.connection_config[:adapter].to_s
38
- end
34
+ ActiveRecord::Base.connection_db_config.adapter.to_s
39
35
  end
40
36
 
41
37
  def postgresql?
@@ -55,14 +55,6 @@ module StrongMigrations
55
55
  version =
56
56
  if target_version && StrongMigrations.developer_env?
57
57
  if target_version.is_a?(Hash)
58
- # Active Record 6.0 supports multiple databases
59
- # but connection.pool.spec.name always returns "primary"
60
- # in migrations with rails db:migrate
61
- if ActiveRecord::VERSION::STRING.to_f < 6.1
62
- # error class is not shown in db:migrate output so ensure message is descriptive
63
- raise StrongMigrations::Error, "StrongMigrations.target_version does not support multiple databases for Active Record < 6.1"
64
- end
65
-
66
58
  db_config_name = connection.pool.db_config.name
67
59
  target_version.stringify_keys.fetch(db_config_name) do
68
60
  # error class is not shown in db:migrate output so ensure message is descriptive
@@ -6,7 +6,7 @@ module StrongMigrations
6
6
  end
7
7
 
8
8
  def min_version
9
- "10.2"
9
+ "10.5"
10
10
  end
11
11
 
12
12
  def server_version
@@ -8,7 +8,7 @@ module StrongMigrations
8
8
  end
9
9
 
10
10
  def min_version
11
- "5.7"
11
+ "8.0"
12
12
  end
13
13
 
14
14
  def server_version
@@ -65,9 +65,10 @@ module StrongMigrations
65
65
  sql = <<~SQL
66
66
  SELECT cs.MAXLEN
67
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)}
68
+ INNER JOIN INFORMATION_SCHEMA.COLUMNS c ON c.CHARACTER_SET_NAME = cs.CHARACTER_SET_NAME
69
+ WHERE c.TABLE_SCHEMA = database() AND
70
+ c.TABLE_NAME = #{connection.quote(table)} AND
71
+ c.COLUMN_NAME = #{connection.quote(column)}
71
72
  SQL
72
73
  row = connection.select_all(sql).first
73
74
  if row
@@ -6,7 +6,7 @@ module StrongMigrations
6
6
  end
7
7
 
8
8
  def min_version
9
- "10"
9
+ "12"
10
10
  end
11
11
 
12
12
  def server_version
@@ -42,7 +42,7 @@ module StrongMigrations
42
42
  end
43
43
 
44
44
  def add_column_default_safe?
45
- server_version >= Gem::Version.new("11")
45
+ true
46
46
  end
47
47
 
48
48
  def change_type_safe?(table, column, type, options, existing_column, existing_type)
@@ -95,7 +95,7 @@ module StrongMigrations
95
95
  "timestamp" => "timestamp without time zone",
96
96
  "timestamptz" => "timestamp with time zone"
97
97
  }
98
- maybe_safe = type_map.values.include?(existing_type) && precision >= existing_precision
98
+ maybe_safe = type_map.value?(existing_type) && precision >= existing_precision
99
99
 
100
100
  if maybe_safe
101
101
  new_type = type.to_s == "datetime" ? datetime_type : type.to_s
@@ -103,7 +103,7 @@ module StrongMigrations
103
103
  # resolve with fallback
104
104
  new_type = type_map[new_type] || new_type
105
105
 
106
- safe = new_type == existing_type || (server_version >= Gem::Version.new("12") && time_zone == "UTC")
106
+ safe = new_type == existing_type || time_zone == "UTC"
107
107
  end
108
108
  when "time"
109
109
  precision = options[:precision] || options[:limit] || 6
@@ -39,27 +39,20 @@ module StrongMigrations
39
39
  #
40
40
  # Also, Active Record has special case for uuid columns that allows function default values
41
41
  # https://github.com/rails/rails/blob/v7.0.3.1/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb#L92-L93
42
- if options.key?(:default) && (!adapter.add_column_default_safe? || (volatile = (postgresql? && type.to_s == "uuid" && default.to_s.include?("()") && adapter.default_volatile?(default))))
42
+ if !default.nil? && (!adapter.add_column_default_safe? || (volatile = (postgresql? && type.to_s == "uuid" && default.to_s.include?("()") && adapter.default_volatile?(default))))
43
43
  if options[:null] == false
44
44
  options = options.except(:null)
45
45
  append = "\n\nThen add the NOT NULL constraint in separate migrations."
46
46
  end
47
47
 
48
- if default.nil?
49
- raise_error :add_column_default_null,
50
- command: command_str("add_column", [table, column, type, options.except(:default)]),
51
- append: append,
52
- rewrite_blocks: adapter.rewrite_blocks
53
- else
54
- raise_error :add_column_default,
55
- add_command: command_str("add_column", [table, column, type, options.except(:default)]),
56
- change_command: command_str("change_column_default", [table, column, default]),
57
- remove_command: command_str("remove_column", [table, column]),
58
- code: backfill_code(table, column, default, volatile),
59
- append: append,
60
- rewrite_blocks: adapter.rewrite_blocks,
61
- default_type: (volatile ? "volatile" : "non-null")
62
- end
48
+ raise_error :add_column_default,
49
+ add_command: command_str("add_column", [table, column, type, options.except(:default)]),
50
+ change_command: command_str("change_column_default", [table, column, default]),
51
+ remove_command: command_str("remove_column", [table, column]),
52
+ code: backfill_code(table, column, default, volatile),
53
+ append: append,
54
+ rewrite_blocks: adapter.rewrite_blocks,
55
+ default_type: (volatile ? "volatile" : "non-null")
63
56
  elsif default.is_a?(Proc) && postgresql?
64
57
  # adding a column with a VOLATILE default is not safe
65
58
  # https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-NOTES
@@ -235,11 +228,7 @@ module StrongMigrations
235
228
  table, column, null, default = args
236
229
  if !null
237
230
  if postgresql?
238
- safe = false
239
- safe_with_check_constraint = adapter.server_version >= Gem::Version.new("12")
240
- if safe_with_check_constraint
241
- safe = adapter.constraints(table).any? { |c| c["def"] == "CHECK ((#{column} IS NOT NULL))" || c["def"] == "CHECK ((#{connection.quote_column_name(column)} IS NOT NULL))" }
242
- end
231
+ safe = adapter.constraints(table).any? { |c| c["def"] == "CHECK ((#{column} IS NOT NULL))" || c["def"] == "CHECK ((#{connection.quote_column_name(column)} IS NOT NULL))" }
243
232
 
244
233
  unless safe
245
234
  # match https://github.com/nullobject/rein
@@ -249,46 +238,22 @@ module StrongMigrations
249
238
  validate_code = constraint_str("ALTER TABLE %s VALIDATE CONSTRAINT %s", [table, constraint_name])
250
239
  remove_code = constraint_str("ALTER TABLE %s DROP CONSTRAINT %s", [table, constraint_name])
251
240
 
252
- constraint_methods = ar_version >= 6.1
253
-
254
- validate_constraint_code =
255
- if constraint_methods
256
- String.new(command_str(:validate_check_constraint, [table, {name: constraint_name}]))
257
- else
258
- String.new(safety_assured_str(validate_code))
259
- end
241
+ validate_constraint_code = String.new(command_str(:validate_check_constraint, [table, {name: constraint_name}]))
260
242
 
261
- if safe_with_check_constraint
262
- change_args = [table, column, null]
243
+ change_args = [table, column, null]
263
244
 
264
- validate_constraint_code << "\n #{command_str(:change_column_null, change_args)}"
265
-
266
- if constraint_methods
267
- validate_constraint_code << "\n #{command_str(:remove_check_constraint, [table, {name: constraint_name}])}"
268
- else
269
- validate_constraint_code << "\n #{safety_assured_str(remove_code)}"
270
- end
271
- end
245
+ validate_constraint_code << "\n #{command_str(:change_column_null, change_args)}"
246
+ validate_constraint_code << "\n #{command_str(:remove_check_constraint, [table, {name: constraint_name}])}"
272
247
 
273
248
  if StrongMigrations.safe_by_default
274
249
  safe_change_column_null(add_code, validate_code, change_args, remove_code, default)
275
250
  throw :safe
276
251
  end
277
252
 
278
- add_constraint_code =
279
- if constraint_methods
280
- command_str(:add_check_constraint, [table, "#{quote_column_if_needed(column)} IS NOT NULL", {name: constraint_name, validate: false}])
281
- else
282
- safety_assured_str(add_code)
283
- end
284
-
285
- validate_constraint_code =
286
- if safe_with_check_constraint
287
- down_code = "#{add_constraint_code}\n #{command_str(:change_column_null, [table, column, true])}"
288
- "def up\n #{validate_constraint_code}\n end\n\n def down\n #{down_code}\n end"
289
- else
290
- "def change\n #{validate_constraint_code}\n end"
291
- end
253
+ add_constraint_code = command_str(:add_check_constraint, [table, "#{quote_column_if_needed(column)} IS NOT NULL", {name: constraint_name, validate: false}])
254
+
255
+ down_code = "#{add_constraint_code}\n #{command_str(:change_column_null, [table, column, true])}"
256
+ validate_constraint_code = "def up\n #{validate_constraint_code}\n end\n\n def down\n #{down_code}\n end"
292
257
 
293
258
  raise_error :change_column_null_postgresql,
294
259
  add_constraint_code: add_constraint_code,
@@ -373,12 +338,6 @@ module StrongMigrations
373
338
  # avoid suggesting extra (invalid) args
374
339
  args = args[0..1] unless StrongMigrations.safe_by_default
375
340
 
376
- # Active Record < 6.1 only supports two arguments (including options)
377
- if args.size == 2 && ar_version < 6.1
378
- # arg takes precedence over option
379
- options[:column] = args.pop
380
- end
381
-
382
341
  if StrongMigrations.safe_by_default
383
342
  safe_remove_index(*args, **options)
384
343
  throw :safe
@@ -487,7 +446,7 @@ module StrongMigrations
487
446
  # only quote when needed
488
447
  # important! only use for display purposes
489
448
  def quote_column_if_needed(column)
490
- column.to_s =~ /\A[a-z0-9_]+\z/ ? column : connection.quote_column_name(column)
449
+ /\A[a-z0-9_]+\z/.match?(column.to_s) ? column : connection.quote_column_name(column)
491
450
  end
492
451
 
493
452
  def new_table?(table)
@@ -25,16 +25,6 @@ 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
-
38
28
  add_column_default_callable:
39
29
  "Strong Migrations does not support inspecting callable default values.
40
30
  Please make really sure you're not calling a VOLATILE function,
@@ -50,19 +50,11 @@ module StrongMigrations
50
50
  @migration.add_foreign_key(from_table, to_table, *args, **options.merge(validate: false))
51
51
  disable_transaction
52
52
  validate_options = options.slice(:column, :name)
53
- if ActiveRecord::VERSION::MAJOR >= 6
54
- @migration.validate_foreign_key(from_table, to_table, **validate_options)
55
- else
56
- @migration.validate_foreign_key(from_table, validate_options.any? ? validate_options : to_table)
57
- end
53
+ @migration.validate_foreign_key(from_table, to_table, **validate_options)
58
54
  end
59
55
  dir.down do
60
56
  remove_options = options.slice(:column, :name)
61
- if ActiveRecord::VERSION::MAJOR >= 6
62
- @migration.remove_foreign_key(from_table, to_table, **remove_options)
63
- else
64
- @migration.remove_foreign_key(from_table, remove_options.any? ? remove_options : to_table)
65
- end
57
+ @migration.remove_foreign_key(from_table, to_table, **remove_options)
66
58
  end
67
59
  end
68
60
  end
@@ -1,3 +1,3 @@
1
1
  module StrongMigrations
2
- VERSION = "1.8.0"
2
+ VERSION = "2.0.0"
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: 1.8.0
4
+ version: 2.0.0
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: 2024-03-12 00:00:00.000000000 Z
13
+ date: 2024-06-28 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: '5.2'
21
+ version: '6.1'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: '5.2'
28
+ version: '6.1'
29
29
  description:
30
30
  email:
31
31
  - andrew@ankane.org
@@ -68,14 +68,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
68
68
  requirements:
69
69
  - - ">="
70
70
  - !ruby/object:Gem::Version
71
- version: '2.6'
71
+ version: '3.1'
72
72
  required_rubygems_version: !ruby/object:Gem::Requirement
73
73
  requirements:
74
74
  - - ">="
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0'
77
77
  requirements: []
78
- rubygems_version: 3.5.3
78
+ rubygems_version: 3.5.11
79
79
  signing_key:
80
80
  specification_version: 4
81
81
  summary: Catch unsafe migrations in development