dynamic_migrations 3.8.6 → 3.8.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/lib/dynamic_migrations/postgres/generator/enum.rb +13 -9
  4. data/lib/dynamic_migrations/postgres/generator/fragment.rb +1 -1
  5. data/lib/dynamic_migrations/postgres/generator/function.rb +13 -13
  6. data/lib/dynamic_migrations/postgres/generator/migration.rb +45 -7
  7. data/lib/dynamic_migrations/postgres/generator/table_migration.rb +2 -0
  8. data/lib/dynamic_migrations/postgres/generator.rb +100 -46
  9. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/extensions.rb +2 -2
  10. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/enums.rb +10 -10
  11. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/functions.rb +11 -11
  12. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/columns.rb +11 -11
  13. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/foreign_key_constraints.rb +11 -11
  14. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/indexes.rb +11 -11
  15. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/primary_key.rb +6 -6
  16. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/triggers.rb +11 -11
  17. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/unique_constraints.rb +11 -11
  18. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/validations.rb +11 -11
  19. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables.rb +8 -8
  20. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas.rb +3 -3
  21. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations.rb +4 -4
  22. data/lib/dynamic_migrations/postgres/server/database/differences.rb +17 -17
  23. data/lib/dynamic_migrations/postgres/server/database/schema/enum.rb +7 -0
  24. data/lib/dynamic_migrations/postgres/server/database/schema/table.rb +61 -1
  25. data/lib/dynamic_migrations/version.rb +1 -1
  26. data/sig/dynamic_migrations/postgres/generator/enum.rbs +2 -0
  27. data/sig/dynamic_migrations/postgres/generator/function.rbs +1 -0
  28. data/sig/dynamic_migrations/postgres/generator/migration.rbs +1 -0
  29. data/sig/dynamic_migrations/postgres/generator/schema_migration.rbs +2 -0
  30. data/sig/dynamic_migrations/postgres/generator/table_migration.rbs +3 -0
  31. data/sig/dynamic_migrations/postgres/generator.rbs +3 -1
  32. data/sig/dynamic_migrations/postgres/server/database/schema/enum.rbs +3 -0
  33. data/sig/dynamic_migrations/postgres/server/database/schema/table.rbs +3 -0
  34. metadata +2 -2
@@ -10,10 +10,10 @@ module DynamicMigrations
10
10
  module Tables
11
11
  def process_tables schema_name, configuration_tables, database_tables
12
12
  # process all the tables
13
- log.info " Processing Tables..."
13
+ log.debug " Processing Tables"
14
14
  table_names = (configuration_tables.keys + database_tables.keys).uniq
15
15
  table_names.each do |table_name|
16
- log.info " Processing Table #{table_name}..."
16
+ log.debug " Processing Table #{table_name}"
17
17
  process_table schema_name, table_name, configuration_tables[table_name] || {}, database_tables[table_name] || {}
18
18
  end
19
19
  end
@@ -22,7 +22,7 @@ module DynamicMigrations
22
22
  # If the table exists in the configuration but not in the database
23
23
  # then we have to create it.
24
24
  if configuration_table[:exists] == true && !database_table[:exists]
25
- log.info " Table `#{table_name}` exists in configuration but not in the database"
25
+ log.debug " Table `#{table_name}` exists in configuration but not in the database"
26
26
 
27
27
  # a migration to create the table
28
28
  table = @database.configured_schema(schema_name).table(table_name)
@@ -35,7 +35,7 @@ module DynamicMigrations
35
35
  # If the schema exists in the database but not in the configuration
36
36
  # then we need to delete it.
37
37
  elsif database_table[:exists] == true && !configuration_table[:exists]
38
- log.info " Table `#{table_name}` exists in database but not in the configuration"
38
+ log.debug " Table `#{table_name}` exists in database but not in the configuration"
39
39
 
40
40
  # we process everything else before we drop the table, because the other
41
41
  # database objects are dependent on the table
@@ -48,15 +48,15 @@ module DynamicMigrations
48
48
  # If the table exists in both the configuration and database representations
49
49
  # but the description is different then we need to update the description.
50
50
  elsif configuration_table[:description][:matches] == false
51
- log.info " Table `#{table_name}` exists in both configuration and the database"
51
+ log.debug " Table `#{table_name}` exists in both configuration and the database"
52
52
 
53
53
  table = @database.configured_schema(schema_name).table(table_name)
54
54
  # if the description was removed
55
55
  if configuration_table[:description].nil?
56
- log.info " Table `#{table_name}` description exists in database but not in the configuration"
56
+ log.debug " Table `#{table_name}` description exists in database but not in the configuration"
57
57
  @generator.remove_table_comment table
58
58
  else
59
- log.info " Table `#{table_name}` description does not match"
59
+ log.debug " Table `#{table_name}` description does not match"
60
60
  @generator.set_table_comment table
61
61
  end
62
62
 
@@ -64,7 +64,7 @@ module DynamicMigrations
64
64
  process_dependents schema_name, table_name, configuration_table, database_table
65
65
 
66
66
  else
67
- log.info " Table `#{table_name}` exists in both configuration and the database"
67
+ log.debug " Table `#{table_name}` exists in both configuration and the database"
68
68
  # process everything else
69
69
  process_dependents schema_name, table_name, configuration_table, database_table
70
70
 
@@ -11,7 +11,7 @@ module DynamicMigrations
11
11
  # if the schema exists in the configuration but not in the database
12
12
  # then we have to create it
13
13
  if configuration_schema[:exists] == true && !database_schema[:exists]
14
- log.info "Schema `#{schema_name}` exists in configuration but not in the database"
14
+ log.debug "Schema `#{schema_name}` exists in configuration but not in the database"
15
15
 
16
16
  # a migration to create the schema
17
17
  schema = @database.configured_schema schema_name
@@ -26,7 +26,7 @@ module DynamicMigrations
26
26
  # if the schema exists in the database but not in the configuration
27
27
  # then we need to delete it
28
28
  elsif database_schema[:exists] == true && !configuration_schema[:exists]
29
- log.info "Schema `#{schema_name}` exists in database but not in the configuration"
29
+ log.debug "Schema `#{schema_name}` exists in database but not in the configuration"
30
30
  # we process the tables and functions before we drop the schema
31
31
  # as this will drop any dependencies on the schema
32
32
  process_functions schema_name, {}, database_schema[:functions]
@@ -40,7 +40,7 @@ module DynamicMigrations
40
40
  # if the schema exists in both the configuration and database representations
41
41
  # then we just need to process the tables and functions
42
42
  else
43
- log.info "Schema `#{schema_name}` exists in both configuration and the database"
43
+ log.debug "Schema `#{schema_name}` exists in both configuration and the database"
44
44
  process_functions schema_name, configuration_schema[:functions], database_schema[:functions]
45
45
  process_enums schema_name, configuration_schema[:enums], database_schema[:enums]
46
46
  process_tables schema_name, configuration_schema[:tables], database_schema[:tables]
@@ -40,19 +40,19 @@ module DynamicMigrations
40
40
 
41
41
  def migrations
42
42
  # process all the extensions
43
- log.info "Processing Extensions..."
43
+ log.debug "Processing Extensions"
44
44
  extension_names = differences[:configuration][:extensions].keys
45
45
  extension_names.each do |extension_name|
46
- log.info "Processing Extension `#{extension_name}`..."
46
+ log.debug "Processing Extension `#{extension_name}`"
47
47
  process_extension extension_name, differences[:configuration][:extensions][extension_name], differences[:database][:extensions][extension_name]
48
48
  end
49
49
 
50
50
  # process all the schemas (we can fetch the schema names from either the
51
51
  # configuration or the database object)
52
- log.info "Processing Schemas..."
52
+ log.debug "Processing Schemas"
53
53
  schema_names = differences[:configuration][:schemas].keys
54
54
  schema_names.each do |schema_name|
55
- log.info "Processing Schema `#{schema_name}`..."
55
+ log.debug "Processing Schema `#{schema_name}`"
56
56
  process_schema schema_name, differences[:configuration][:schemas][schema_name], differences[:database][:schemas][schema_name]
57
57
  end
58
58
 
@@ -33,18 +33,18 @@ module DynamicMigrations
33
33
  # return a hash representing any differenced betweek the loaded and configured
34
34
  # versions of the current database
35
35
  def to_h
36
- log.info "Building differences between configured and loaded database structure..."
36
+ log.info "Building differences between configured and loaded database structure"
37
37
 
38
38
  # build progressively, so we can add logging around the two different opperations
39
39
  results = {}
40
40
 
41
- log.info "Comparing configured database structure to loaded database structure..."
41
+ log.info "Comparing configured database structure to loaded database structure"
42
42
  results[:configuration] = {
43
43
  schemas: self.class.compare_schemas(@database.configured_schemas_hash, @database.loaded_schemas_hash),
44
44
  extensions: self.class.compare_extensions(@database.configured_extensions, @database.loaded_extensions)
45
45
  }
46
46
 
47
- log.info "Comparing loaded database structure to configured database structure..."
47
+ log.info "Comparing loaded database structure to configured database structure"
48
48
  results[:database] = {
49
49
  schemas: self.class.compare_schemas(@database.loaded_schemas_hash, @database.configured_schemas_hash),
50
50
  extensions: self.class.compare_extensions(@database.loaded_extensions, @database.configured_extensions)
@@ -53,7 +53,7 @@ module DynamicMigrations
53
53
  end
54
54
 
55
55
  def self.compare_extensions extensions, comparison_extensions
56
- log.info "Comparing Extensions..."
56
+ log.info "Comparing Extensions"
57
57
 
58
58
  result = {}
59
59
  # the extensions
@@ -76,7 +76,7 @@ module DynamicMigrations
76
76
  end
77
77
 
78
78
  def self.compare_schemas schemas, comparison_schemas
79
- log.info "Comparing Schemas..."
79
+ log.info "Comparing Schemas"
80
80
 
81
81
  result = {}
82
82
  # the base schemas
@@ -118,7 +118,7 @@ module DynamicMigrations
118
118
  # an object which represents the provided `tables` and any differences
119
119
  # between it and the `comparison_tables`
120
120
  def self.compare_tables tables, comparison_tables
121
- log.info "Comparing Tables..."
121
+ log.debug "Comparing Tables"
122
122
 
123
123
  result = {}
124
124
  # the base tables
@@ -143,7 +143,7 @@ module DynamicMigrations
143
143
  def self.compare_table table, comparison_table
144
144
  raise TableRequiredError if table.nil?
145
145
 
146
- log.info "Comparing Table `#{table.name}`"
146
+ log.debug "Comparing Table `#{table.name}`"
147
147
 
148
148
  primary_key = table.has_primary_key? ? table.primary_key : nil
149
149
  if comparison_table
@@ -187,7 +187,7 @@ module DynamicMigrations
187
187
  # an object which represents the provided `functions` and any differences
188
188
  # between it and the `comparison_functions`
189
189
  def self.compare_functions functions, comparison_functions
190
- log.info "Comparing Functions..."
190
+ log.debug "Comparing Functions"
191
191
 
192
192
  result = {}
193
193
  # the base functions
@@ -212,7 +212,7 @@ module DynamicMigrations
212
212
  # an object which represents the provided `enums` and any differences
213
213
  # between it and the `comparison_enums`
214
214
  def self.compare_enums enums, comparison_enums
215
- log.info "Comparing Enums..."
215
+ log.debug "Comparing Enums"
216
216
 
217
217
  result = {}
218
218
  # the base enums
@@ -237,7 +237,7 @@ module DynamicMigrations
237
237
  # an object which represents the provided `columns` and any differences
238
238
  # between it and the `comparison_columns`
239
239
  def self.compare_columns columns, comparison_columns
240
- log.info "Comparing Columns..."
240
+ log.debug "Comparing Columns"
241
241
 
242
242
  result = {}
243
243
  # the base columns
@@ -266,7 +266,7 @@ module DynamicMigrations
266
266
  # an object which represents the provided `triggers` and any differences
267
267
  # between it and the `comparison_triggers`
268
268
  def self.compare_triggers triggers, comparison_triggers
269
- log.info "Comparing Triggers..."
269
+ log.debug "Comparing Triggers"
270
270
 
271
271
  result = {}
272
272
  # the base triggers
@@ -299,7 +299,7 @@ module DynamicMigrations
299
299
  # an object which represents the provided `unique_constraints` and any differences
300
300
  # between it and the `comparison_unique_constraints`
301
301
  def self.compare_unique_constraints unique_constraints, comparison_unique_constraints
302
- log.info "Comparing Unique Constraints..."
302
+ log.debug "Comparing Unique Constraints"
303
303
 
304
304
  result = {}
305
305
  # the base unique_constraints
@@ -327,7 +327,7 @@ module DynamicMigrations
327
327
  # an object which represents the provided `indexes` and any differences
328
328
  # between it and the `comparison_indexes`
329
329
  def self.compare_indexes indexes, comparison_indexes
330
- log.info "Comparing Indexes..."
330
+ log.debug "Comparing Indexes"
331
331
 
332
332
  result = {}
333
333
  # the base indexes
@@ -358,7 +358,7 @@ module DynamicMigrations
358
358
  # an object which represents the provided `validations` and any differences
359
359
  # between it and the `comparison_validations`
360
360
  def self.compare_validations validations, comparison_validations
361
- log.info "Comparing Validations..."
361
+ log.debug "Comparing Validations"
362
362
 
363
363
  result = {}
364
364
  # the base validations
@@ -387,7 +387,7 @@ module DynamicMigrations
387
387
  # an object which represents the provided `foreign_key_constraints` and any differences
388
388
  # between it and the `comparison_foreign_key_constraints`
389
389
  def self.compare_foreign_key_constraints foreign_key_constraints, comparison_foreign_key_constraints
390
- log.info "Comparing Foreign Key Constraints..."
390
+ log.debug "Comparing Foreign Key Constraints"
391
391
 
392
392
  result = {}
393
393
  # the base foreign_key_constraints
@@ -428,11 +428,11 @@ module DynamicMigrations
428
428
  else
429
429
  type = base.class.name.split("::").last
430
430
  name = base.is_a?(Schema::Table::PrimaryKey) ? nil : base.name
431
- log.info " Comparing #{type} `#{name}`"
431
+ log.debug " Comparing #{type} `#{name}`"
432
432
 
433
433
  result = {}
434
434
  method_list.each do |method_name|
435
- log.info " Comparing `#{method_name}`"
435
+ log.debug " Comparing `#{method_name}`"
436
436
 
437
437
  matches = (comparison && comparison.send(method_name) == base.send(method_name)) || false
438
438
  result[method_name] = {
@@ -19,6 +19,9 @@ module DynamicMigrations
19
19
  class ValueMustBeStringError < StandardError
20
20
  end
21
21
 
22
+ class EnumValueTooLongError < StandardError
23
+ end
24
+
22
25
  attr_reader :schema
23
26
  attr_reader :name
24
27
  attr_reader :values
@@ -61,6 +64,10 @@ module DynamicMigrations
61
64
  raise ValueAlreadyExistsError, "Value `#{value}` already exists in enum `#{name}`"
62
65
  end
63
66
 
67
+ if value.length > 63
68
+ raise EnumValueTooLongError, "Value `#{value}` must be less than 64 characters"
69
+ end
70
+
64
71
  @values << value
65
72
  end
66
73
 
@@ -16,6 +16,9 @@ module DynamicMigrations
16
16
  class PrimaryKeyAlreadyExistsError < StandardError
17
17
  end
18
18
 
19
+ class MissingExtensionError < StandardError
20
+ end
21
+
19
22
  include Columns
20
23
  include Validations
21
24
  include Indexes
@@ -116,7 +119,64 @@ module DynamicMigrations
116
119
  end
117
120
 
118
121
  # in case any of the columnbs are citext columns
119
- connection.exec("CREATE EXTENSION IF NOT EXISTS citext;")
122
+ # in case any of the columns use the citext data type
123
+ required_extensions = []
124
+ if columns.any? { |column| column.data_type.start_with? "citext" }
125
+ required_extensions << "citext"
126
+ end
127
+ if columns.any? { |column| column.data_type.start_with? "postgis" }
128
+ required_extensions << "postgis"
129
+ end
130
+
131
+ required_extensions.each do |extension_name|
132
+ extension_result = connection.exec(<<~SQL)
133
+ SELECT
134
+ (
135
+ SELECT 1
136
+ FROM pg_available_extensions
137
+ WHERE name = '#{extension_name}'
138
+ ) as is_available,
139
+ (
140
+ SELECT 1
141
+ FROM pg_extension
142
+ WHERE extname = '#{extension_name}'
143
+ ) as is_installed
144
+ SQL
145
+
146
+ row = extension_result.first
147
+ raise MissingExtensionError, "unexpected error" if row.nil?
148
+
149
+ unless row["is_installed"]
150
+ detail = if row["is_available"]
151
+ <<~DETAIL
152
+ The `#{extension_name}` extension is available for installation,
153
+ but has not been installed for this database.
154
+ DETAIL
155
+ else
156
+ <<~DETAIL
157
+ The `#{extension_name}` extension is not installed, and does not
158
+ appear to be available for installation.
159
+ DETAIL
160
+ end
161
+ raise MissingExtensionError, <<~ERROR.tr!("\n", " ")
162
+ This table uses the `#{extension_name}` data type. #{detail}
163
+ Add the extension, then generate and run the migrations which will
164
+ enable the extension for your database before defining validations
165
+ or triggers which rely on it.
166
+
167
+ Note, the `#{extension_name}` extension is required even for defining
168
+ some validations and triggers. This library needs to connect to postgres
169
+ and gererate normalized versions of validation check clauses and trigger
170
+ action conditions before it can even compare them to validations or triggers
171
+ which may or may not already exist in the database.
172
+ ERROR
173
+ end
174
+ end
175
+
176
+ # if any of the columns require postgis
177
+ if required_extensions.include? "postgis"
178
+ connection.exec("SET search_path TO public,postgis;")
179
+ end
120
180
 
121
181
  # note, this is not actually a TEMP TABLE, it is created within a transaction
122
182
  # and rolled back.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DynamicMigrations
4
- VERSION = "3.8.6"
4
+ VERSION = "3.8.7"
5
5
  end
@@ -10,6 +10,8 @@ module DynamicMigrations
10
10
  def drop_enum: (Server::Database::Schema::Enum enum, ?String? code_comment) -> Fragment
11
11
  def set_enum_comment: (Server::Database::Schema::Enum enum, ?String? code_comment) -> Fragment
12
12
  def remove_enum_comment: (Server::Database::Schema::Enum enum, ?String? code_comment) -> Fragment
13
+ def optional_enum_table: (Postgres::Server::Database::Schema::Enum enum) -> Server::Database::Schema::Table?
14
+
13
15
  # these come from the generator object (which this module is included into)
14
16
  def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
15
17
  def indent: (String migration, ?Integer levels) -> String
@@ -10,6 +10,7 @@ module DynamicMigrations
10
10
  def drop_function: (Postgres::Server::Database::Schema::Function function, ?String? code_comment) -> Fragment
11
11
  def set_function_comment: (Postgres::Server::Database::Schema::Function function, ?String? code_comment) -> Fragment
12
12
  def remove_function_comment: (Postgres::Server::Database::Schema::Function function, ?String? code_comment) -> Fragment
13
+ def optional_function_table: (Postgres::Server::Database::Schema::Function function) -> Server::Database::Schema::Table?
13
14
 
14
15
  # these come from the generator object (which this module is included into)
15
16
  def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
@@ -22,6 +22,7 @@ module DynamicMigrations
22
22
  def enum_dependencies: -> Array[{schema_name: Symbol, enum_name: Symbol}]
23
23
  def function_dependencies: -> Array[{schema_name: Symbol, function_name: Symbol}]
24
24
 
25
+ def fragments_with_table_dependency_count: (Symbol schema_name, Symbol table_name) -> Integer
25
26
  def extract_fragments_with_table_dependency: (Symbol schema_name, Symbol table_name) -> Array[Fragment]
26
27
 
27
28
  def content: -> String
@@ -5,6 +5,8 @@ module DynamicMigrations
5
5
  module Postgres
6
6
  class Generator
7
7
  class SchemaMigration < Migration
8
+ def schema_name: -> Symbol
9
+
8
10
  def initialize: (Symbol schema_name) -> void
9
11
 
10
12
  end
@@ -5,6 +5,9 @@ module DynamicMigrations
5
5
  module Postgres
6
6
  class Generator
7
7
  class TableMigration < Migration
8
+ def schema_name: -> Symbol
9
+ def table_name: -> Symbol
10
+
8
11
  def initialize: (Symbol schema_name, Symbol table_name) -> void
9
12
  end
10
13
  end
@@ -7,6 +7,7 @@ module DynamicMigrations
7
7
  include TSort
8
8
 
9
9
  @fragments: Array[Fragment]
10
+ @logger: Logging::Logger
10
11
 
11
12
  include Schema
12
13
  include Table
@@ -27,13 +28,14 @@ module DynamicMigrations
27
28
  }]
28
29
 
29
30
  private
30
- def circular_dependency?: (Symbol schema_name, Symbol table_name, {schema_name: Symbol, table_name: Symbol} dependency, Array[TableMigration] all_table_migrations) -> bool
31
+ def resolve_circular_dependencies: (TableMigration table_migration, Array[TableMigration] all_table_migrations, Hash[Symbol, untyped] database_migrations, Array[TableMigration] completed_table_migrations, ?Array[String] stack) -> void
31
32
  def supported_migration_method?: (Symbol migration_method) -> bool
32
33
  def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
33
34
  def indent: (String migration, ?Integer levels) -> String
34
35
  def tsort_each_node: -> Enumerator[untyped, untyped]
35
36
  def tsort_each_child: (untyped node) -> untyped
36
37
  def trim_lines: (String migration) -> String
38
+ def log: -> Logging::Logger
37
39
 
38
40
  class ExpectedSymbolError < StandardError
39
41
  end
@@ -30,6 +30,9 @@ module DynamicMigrations
30
30
 
31
31
  class ValueMustBeStringError < StandardError
32
32
  end
33
+
34
+ class EnumValueTooLongError < StandardError
35
+ end
33
36
  end
34
37
  end
35
38
  end
@@ -31,6 +31,9 @@ module DynamicMigrations
31
31
 
32
32
  class PrimaryKeyAlreadyExistsError < StandardError
33
33
  end
34
+
35
+ class MissingExtensionError < StandardError
36
+ end
34
37
  end
35
38
  end
36
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamic_migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.6
4
+ version: 3.8.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Craig Ulliott
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-08 00:00:00.000000000 Z
11
+ date: 2023-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg