activerecord 7.0.6 → 7.1.1

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.
Files changed (231) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1424 -1390
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +15 -16
  5. data/lib/active_record/aggregations.rb +16 -13
  6. data/lib/active_record/association_relation.rb +1 -1
  7. data/lib/active_record/associations/association.rb +18 -3
  8. data/lib/active_record/associations/association_scope.rb +16 -9
  9. data/lib/active_record/associations/belongs_to_association.rb +14 -6
  10. data/lib/active_record/associations/builder/association.rb +3 -3
  11. data/lib/active_record/associations/builder/belongs_to.rb +21 -8
  12. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
  13. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  14. data/lib/active_record/associations/collection_association.rb +16 -10
  15. data/lib/active_record/associations/collection_proxy.rb +20 -10
  16. data/lib/active_record/associations/foreign_association.rb +10 -3
  17. data/lib/active_record/associations/has_many_association.rb +20 -13
  18. data/lib/active_record/associations/has_many_through_association.rb +10 -6
  19. data/lib/active_record/associations/has_one_association.rb +10 -7
  20. data/lib/active_record/associations/join_dependency.rb +10 -8
  21. data/lib/active_record/associations/preloader/association.rb +27 -6
  22. data/lib/active_record/associations/preloader.rb +13 -10
  23. data/lib/active_record/associations/singular_association.rb +6 -8
  24. data/lib/active_record/associations/through_association.rb +22 -11
  25. data/lib/active_record/associations.rb +295 -199
  26. data/lib/active_record/attribute_assignment.rb +0 -2
  27. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
  28. data/lib/active_record/attribute_methods/dirty.rb +40 -26
  29. data/lib/active_record/attribute_methods/primary_key.rb +76 -24
  30. data/lib/active_record/attribute_methods/query.rb +28 -16
  31. data/lib/active_record/attribute_methods/read.rb +18 -5
  32. data/lib/active_record/attribute_methods/serialization.rb +150 -31
  33. data/lib/active_record/attribute_methods/write.rb +3 -3
  34. data/lib/active_record/attribute_methods.rb +105 -21
  35. data/lib/active_record/attributes.rb +3 -3
  36. data/lib/active_record/autosave_association.rb +60 -18
  37. data/lib/active_record/base.rb +7 -2
  38. data/lib/active_record/callbacks.rb +10 -24
  39. data/lib/active_record/coders/column_serializer.rb +61 -0
  40. data/lib/active_record/coders/json.rb +1 -1
  41. data/lib/active_record/coders/yaml_column.rb +70 -42
  42. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +163 -88
  43. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
  44. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
  45. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +63 -43
  46. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
  47. data/lib/active_record/connection_adapters/abstract/database_statements.rb +128 -32
  48. data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
  49. data/lib/active_record/connection_adapters/abstract/quoting.rb +41 -6
  50. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  51. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
  52. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
  53. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +289 -124
  54. data/lib/active_record/connection_adapters/abstract/transaction.rb +287 -58
  55. data/lib/active_record/connection_adapters/abstract_adapter.rb +496 -102
  56. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +214 -113
  57. data/lib/active_record/connection_adapters/column.rb +9 -0
  58. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  59. data/lib/active_record/connection_adapters/mysql/database_statements.rb +23 -144
  60. data/lib/active_record/connection_adapters/mysql/quoting.rb +21 -14
  61. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  62. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
  63. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
  64. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +18 -13
  65. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
  66. data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
  67. data/lib/active_record/connection_adapters/pool_config.rb +14 -5
  68. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  69. data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
  70. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +71 -40
  71. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
  72. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
  73. data/lib/active_record/connection_adapters/postgresql/quoting.rb +15 -8
  74. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
  75. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
  76. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
  77. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
  78. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +349 -55
  79. data/lib/active_record/connection_adapters/postgresql_adapter.rb +338 -176
  80. data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
  81. data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
  82. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +45 -39
  83. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +9 -5
  84. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
  85. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +28 -9
  86. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +210 -83
  87. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  88. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
  89. data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
  90. data/lib/active_record/connection_adapters.rb +3 -1
  91. data/lib/active_record/connection_handling.rb +71 -94
  92. data/lib/active_record/core.rb +136 -148
  93. data/lib/active_record/counter_cache.rb +46 -25
  94. data/lib/active_record/database_configurations/database_config.rb +9 -3
  95. data/lib/active_record/database_configurations/hash_config.rb +22 -12
  96. data/lib/active_record/database_configurations/url_config.rb +17 -11
  97. data/lib/active_record/database_configurations.rb +86 -33
  98. data/lib/active_record/delegated_type.rb +8 -3
  99. data/lib/active_record/deprecator.rb +7 -0
  100. data/lib/active_record/destroy_association_async_job.rb +2 -0
  101. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  102. data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
  103. data/lib/active_record/encryption/config.rb +25 -1
  104. data/lib/active_record/encryption/configurable.rb +12 -19
  105. data/lib/active_record/encryption/context.rb +10 -3
  106. data/lib/active_record/encryption/contexts.rb +5 -1
  107. data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
  108. data/lib/active_record/encryption/encryptable_record.rb +36 -18
  109. data/lib/active_record/encryption/encrypted_attribute_type.rb +17 -6
  110. data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -54
  111. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
  112. data/lib/active_record/encryption/key_generator.rb +12 -1
  113. data/lib/active_record/encryption/message_serializer.rb +2 -0
  114. data/lib/active_record/encryption/properties.rb +3 -3
  115. data/lib/active_record/encryption/scheme.rb +19 -22
  116. data/lib/active_record/encryption.rb +1 -0
  117. data/lib/active_record/enum.rb +113 -26
  118. data/lib/active_record/errors.rb +108 -15
  119. data/lib/active_record/explain.rb +23 -3
  120. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  121. data/lib/active_record/fixture_set/render_context.rb +2 -0
  122. data/lib/active_record/fixture_set/table_row.rb +29 -8
  123. data/lib/active_record/fixtures.rb +119 -71
  124. data/lib/active_record/future_result.rb +30 -5
  125. data/lib/active_record/gem_version.rb +3 -3
  126. data/lib/active_record/inheritance.rb +30 -16
  127. data/lib/active_record/insert_all.rb +55 -8
  128. data/lib/active_record/integration.rb +8 -8
  129. data/lib/active_record/internal_metadata.rb +120 -30
  130. data/lib/active_record/locking/pessimistic.rb +5 -2
  131. data/lib/active_record/log_subscriber.rb +29 -12
  132. data/lib/active_record/marshalling.rb +56 -0
  133. data/lib/active_record/message_pack.rb +124 -0
  134. data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
  135. data/lib/active_record/middleware/database_selector.rb +5 -7
  136. data/lib/active_record/middleware/shard_selector.rb +3 -1
  137. data/lib/active_record/migration/command_recorder.rb +104 -5
  138. data/lib/active_record/migration/compatibility.rb +142 -58
  139. data/lib/active_record/migration/default_strategy.rb +23 -0
  140. data/lib/active_record/migration/execution_strategy.rb +19 -0
  141. data/lib/active_record/migration.rb +265 -112
  142. data/lib/active_record/model_schema.rb +60 -40
  143. data/lib/active_record/nested_attributes.rb +21 -3
  144. data/lib/active_record/normalization.rb +159 -0
  145. data/lib/active_record/persistence.rb +187 -35
  146. data/lib/active_record/promise.rb +84 -0
  147. data/lib/active_record/query_cache.rb +3 -21
  148. data/lib/active_record/query_logs.rb +77 -52
  149. data/lib/active_record/query_logs_formatter.rb +41 -0
  150. data/lib/active_record/querying.rb +15 -2
  151. data/lib/active_record/railtie.rb +109 -47
  152. data/lib/active_record/railties/controller_runtime.rb +12 -8
  153. data/lib/active_record/railties/databases.rake +139 -145
  154. data/lib/active_record/railties/job_runtime.rb +23 -0
  155. data/lib/active_record/readonly_attributes.rb +32 -5
  156. data/lib/active_record/reflection.rb +162 -44
  157. data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
  158. data/lib/active_record/relation/batches.rb +190 -61
  159. data/lib/active_record/relation/calculations.rb +160 -63
  160. data/lib/active_record/relation/delegation.rb +22 -8
  161. data/lib/active_record/relation/finder_methods.rb +77 -16
  162. data/lib/active_record/relation/merger.rb +2 -0
  163. data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -2
  164. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
  165. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  166. data/lib/active_record/relation/predicate_builder.rb +27 -16
  167. data/lib/active_record/relation/query_attribute.rb +25 -1
  168. data/lib/active_record/relation/query_methods.rb +378 -70
  169. data/lib/active_record/relation/spawn_methods.rb +18 -1
  170. data/lib/active_record/relation.rb +76 -35
  171. data/lib/active_record/result.rb +19 -5
  172. data/lib/active_record/runtime_registry.rb +10 -1
  173. data/lib/active_record/sanitization.rb +51 -11
  174. data/lib/active_record/schema.rb +2 -3
  175. data/lib/active_record/schema_dumper.rb +46 -7
  176. data/lib/active_record/schema_migration.rb +68 -33
  177. data/lib/active_record/scoping/default.rb +15 -5
  178. data/lib/active_record/scoping/named.rb +2 -2
  179. data/lib/active_record/scoping.rb +2 -1
  180. data/lib/active_record/secure_password.rb +60 -0
  181. data/lib/active_record/secure_token.rb +21 -3
  182. data/lib/active_record/signed_id.rb +7 -5
  183. data/lib/active_record/store.rb +8 -8
  184. data/lib/active_record/suppressor.rb +3 -1
  185. data/lib/active_record/table_metadata.rb +11 -2
  186. data/lib/active_record/tasks/database_tasks.rb +127 -105
  187. data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
  188. data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
  189. data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
  190. data/lib/active_record/test_fixtures.rb +113 -96
  191. data/lib/active_record/timestamp.rb +27 -15
  192. data/lib/active_record/token_for.rb +113 -0
  193. data/lib/active_record/touch_later.rb +11 -6
  194. data/lib/active_record/transactions.rb +39 -13
  195. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  196. data/lib/active_record/type/internal/timezone.rb +7 -2
  197. data/lib/active_record/type/serialized.rb +4 -0
  198. data/lib/active_record/type/time.rb +4 -0
  199. data/lib/active_record/validations/absence.rb +1 -1
  200. data/lib/active_record/validations/numericality.rb +5 -4
  201. data/lib/active_record/validations/presence.rb +5 -28
  202. data/lib/active_record/validations/uniqueness.rb +47 -2
  203. data/lib/active_record/validations.rb +8 -4
  204. data/lib/active_record/version.rb +1 -1
  205. data/lib/active_record.rb +121 -16
  206. data/lib/arel/errors.rb +10 -0
  207. data/lib/arel/factory_methods.rb +4 -0
  208. data/lib/arel/nodes/and.rb +4 -0
  209. data/lib/arel/nodes/binary.rb +6 -1
  210. data/lib/arel/nodes/bound_sql_literal.rb +61 -0
  211. data/lib/arel/nodes/cte.rb +36 -0
  212. data/lib/arel/nodes/fragments.rb +35 -0
  213. data/lib/arel/nodes/homogeneous_in.rb +0 -8
  214. data/lib/arel/nodes/leading_join.rb +8 -0
  215. data/lib/arel/nodes/node.rb +111 -2
  216. data/lib/arel/nodes/sql_literal.rb +6 -0
  217. data/lib/arel/nodes/table_alias.rb +4 -0
  218. data/lib/arel/nodes.rb +4 -0
  219. data/lib/arel/predications.rb +2 -0
  220. data/lib/arel/table.rb +9 -5
  221. data/lib/arel/visitors/mysql.rb +8 -1
  222. data/lib/arel/visitors/to_sql.rb +81 -17
  223. data/lib/arel/visitors/visitor.rb +2 -2
  224. data/lib/arel.rb +16 -2
  225. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  226. data/lib/rails/generators/active_record/migration.rb +3 -1
  227. data/lib/rails/generators/active_record/model/USAGE +113 -0
  228. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  229. metadata +50 -15
  230. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  231. data/lib/active_record/null_relation.rb +0 -63
@@ -2,13 +2,17 @@
2
2
 
3
3
  module ActiveRecord
4
4
  class Migration
5
- # <tt>ActiveRecord::Migration::CommandRecorder</tt> records commands done during
5
+ # = \Migration Command Recorder
6
+ #
7
+ # +ActiveRecord::Migration::CommandRecorder+ records commands done during
6
8
  # a migration and knows how to reverse those commands. The CommandRecorder
7
9
  # knows how to invert the following commands:
8
10
  #
9
11
  # * add_column
10
12
  # * add_foreign_key
11
13
  # * add_check_constraint
14
+ # * add_exclusion_constraint
15
+ # * add_unique_constraint
12
16
  # * add_index
13
17
  # * add_reference
14
18
  # * add_timestamps
@@ -16,9 +20,11 @@ module ActiveRecord
16
20
  # * change_column_null
17
21
  # * change_column_comment (must supply a +:from+ and +:to+ option)
18
22
  # * change_table_comment (must supply a +:from+ and +:to+ option)
23
+ # * create_enum
19
24
  # * create_join_table
20
25
  # * create_table
21
26
  # * disable_extension
27
+ # * drop_enum (must supply a list of values)
22
28
  # * drop_join_table
23
29
  # * drop_table (must supply a block)
24
30
  # * enable_extension
@@ -26,10 +32,14 @@ module ActiveRecord
26
32
  # * remove_columns (must supply a +:type+ option)
27
33
  # * remove_foreign_key (must supply a second table)
28
34
  # * remove_check_constraint
35
+ # * remove_exclusion_constraint
36
+ # * remove_unique_constraint
29
37
  # * remove_index
30
38
  # * remove_reference
31
39
  # * remove_timestamps
32
40
  # * rename_column
41
+ # * rename_enum (must supply a +:to+ option)
42
+ # * rename_enum_value (must supply a +:from+ and +:to+ option)
33
43
  # * rename_index
34
44
  # * rename_table
35
45
  class CommandRecorder
@@ -41,7 +51,10 @@ module ActiveRecord
41
51
  :change_column, :execute, :remove_columns, :change_column_null,
42
52
  :add_foreign_key, :remove_foreign_key,
43
53
  :change_column_comment, :change_table_comment,
44
- :add_check_constraint, :remove_check_constraint
54
+ :add_check_constraint, :remove_check_constraint,
55
+ :add_exclusion_constraint, :remove_exclusion_constraint,
56
+ :add_unique_constraint, :remove_unique_constraint,
57
+ :create_enum, :drop_enum, :rename_enum, :add_enum_value, :rename_enum_value,
45
58
  ]
46
59
  include JoinTable
47
60
 
@@ -117,7 +130,15 @@ module ActiveRecord
117
130
  alias :remove_belongs_to :remove_reference
118
131
 
119
132
  def change_table(table_name, **options) # :nodoc:
120
- yield delegate.update_table_definition(table_name, self)
133
+ if delegate.supports_bulk_alter? && options[:bulk]
134
+ recorder = self.class.new(self.delegate)
135
+ recorder.reverting = @reverting
136
+ yield recorder.delegate.update_table_definition(table_name, recorder)
137
+ commands = recorder.commands
138
+ @commands << [:change_table, [table_name], -> t { bulk_change_table(table_name, commands) }]
139
+ else
140
+ yield delegate.update_table_definition(table_name, self)
141
+ end
121
142
  end
122
143
 
123
144
  def replay(migration)
@@ -139,7 +160,10 @@ module ActiveRecord
139
160
  add_reference: :remove_reference,
140
161
  add_foreign_key: :remove_foreign_key,
141
162
  add_check_constraint: :remove_check_constraint,
142
- enable_extension: :disable_extension
163
+ add_exclusion_constraint: :remove_exclusion_constraint,
164
+ add_unique_constraint: :remove_unique_constraint,
165
+ enable_extension: :disable_extension,
166
+ create_enum: :drop_enum
143
167
  }.each do |cmd, inv|
144
168
  [[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
145
169
  class_eval <<-EOV, __FILE__, __LINE__ + 1
@@ -164,7 +188,17 @@ module ActiveRecord
164
188
  [:transaction, args, invertions_proc]
165
189
  end
166
190
 
191
+ def invert_create_table(args, &block)
192
+ if args.last.is_a?(Hash)
193
+ args.last.delete(:if_not_exists)
194
+ end
195
+ super
196
+ end
197
+
167
198
  def invert_drop_table(args, &block)
199
+ if args.last.is_a?(Hash)
200
+ args.last.delete(:if_exists)
201
+ end
168
202
  if args.size == 1 && block == nil
169
203
  raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
170
204
  end
@@ -172,7 +206,10 @@ module ActiveRecord
172
206
  end
173
207
 
174
208
  def invert_rename_table(args)
175
- [:rename_table, args.reverse]
209
+ old_name, new_name, options = args
210
+ args = [new_name, old_name]
211
+ args << options if options
212
+ [:rename_table, args]
176
213
  end
177
214
 
178
215
  def invert_remove_column(args)
@@ -234,6 +271,11 @@ module ActiveRecord
234
271
  [:change_column_null, args]
235
272
  end
236
273
 
274
+ def invert_add_foreign_key(args)
275
+ args.last.delete(:validate) if args.last.is_a?(Hash)
276
+ super
277
+ end
278
+
237
279
  def invert_remove_foreign_key(args)
238
280
  options = args.extract_options!
239
281
  from_table, to_table = args
@@ -268,11 +310,68 @@ module ActiveRecord
268
310
  [:change_table_comment, [table, from: options[:to], to: options[:from]]]
269
311
  end
270
312
 
313
+ def invert_add_check_constraint(args)
314
+ if (options = args.last).is_a?(Hash)
315
+ options.delete(:validate)
316
+ options[:if_exists] = options.delete(:if_not_exists) if options.key?(:if_not_exists)
317
+ end
318
+ super
319
+ end
320
+
271
321
  def invert_remove_check_constraint(args)
272
322
  raise ActiveRecord::IrreversibleMigration, "remove_check_constraint is only reversible if given an expression." if args.size < 2
323
+
324
+ if (options = args.last).is_a?(Hash)
325
+ options[:if_not_exists] = options.delete(:if_exists) if options.key?(:if_exists)
326
+ end
327
+ super
328
+ end
329
+
330
+ def invert_remove_exclusion_constraint(args)
331
+ raise ActiveRecord::IrreversibleMigration, "remove_exclusion_constraint is only reversible if given an expression." if args.size < 2
332
+ super
333
+ end
334
+
335
+ def invert_add_unique_constraint(args)
336
+ options = args.dup.extract_options!
337
+
338
+ raise ActiveRecord::IrreversibleMigration, "add_unique_constraint is not reversible if given an using_index." if options[:using_index]
273
339
  super
274
340
  end
275
341
 
342
+ def invert_remove_unique_constraint(args)
343
+ _table, columns = args.dup.tap(&:extract_options!)
344
+
345
+ raise ActiveRecord::IrreversibleMigration, "remove_unique_constraint is only reversible if given an column_name." if columns.blank?
346
+ super
347
+ end
348
+
349
+ def invert_drop_enum(args)
350
+ _enum, values = args.dup.tap(&:extract_options!)
351
+ raise ActiveRecord::IrreversibleMigration, "drop_enum is only reversible if given a list of enum values." unless values
352
+ super
353
+ end
354
+
355
+ def invert_rename_enum(args)
356
+ name, options = args
357
+
358
+ unless options.is_a?(Hash) && options.has_key?(:to)
359
+ raise ActiveRecord::IrreversibleMigration, "rename_enum is only reversible if given a :to option."
360
+ end
361
+
362
+ [:rename_enum, [options[:to], to: name]]
363
+ end
364
+
365
+ def invert_rename_enum_value(args)
366
+ type_name, options = args
367
+
368
+ unless options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
369
+ raise ActiveRecord::IrreversibleMigration, "rename_enum_value is only reversible if given a :from and :to option."
370
+ end
371
+
372
+ [:rename_enum_value, [type_name, from: options[:to], to: options[:from]]]
373
+ end
374
+
276
375
  def respond_to_missing?(method, _)
277
376
  super || delegate.respond_to?(method)
278
377
  end
@@ -21,8 +21,8 @@ module ActiveRecord
21
21
  # New migration functionality that will never be backward compatible should be added directly to `ActiveRecord::Migration`.
22
22
  #
23
23
  # There are classes for each prior Rails version. Each class descends from the *next* Rails version, so:
24
- # 6.1 < 7.0
25
- # 5.2 < 6.0 < 6.1 < 7.0
24
+ # 7.0 < 7.1
25
+ # 5.2 < 6.0 < 6.1 < 7.0 < 7.1
26
26
  #
27
27
  # If you are introducing new migration functionality that should only apply from Rails 7 onward, then you should
28
28
  # find the class that immediately precedes it (6.1), and override the relevant migration methods to undo your changes.
@@ -30,7 +30,117 @@ module ActiveRecord
30
30
  # For example, Rails 6 added a default value for the `precision` option on datetime columns. So in this file, the `V5_2`
31
31
  # class sets the value of `precision` to `nil` if it's not explicitly provided. This way, the default value will not apply
32
32
  # for migrations written for 5.2, but will for migrations written for 6.0.
33
- V7_0 = Current
33
+ V7_1 = Current
34
+
35
+ class V7_0 < V7_1
36
+ module LegacyIndexName
37
+ private
38
+ def legacy_index_name(table_name, options)
39
+ if Hash === options
40
+ if options[:column]
41
+ "index_#{table_name}_on_#{Array(options[:column]) * '_and_'}"
42
+ elsif options[:name]
43
+ options[:name]
44
+ else
45
+ raise ArgumentError, "You must specify the index name"
46
+ end
47
+ else
48
+ legacy_index_name(table_name, index_name_options(options))
49
+ end
50
+ end
51
+
52
+ def index_name_options(column_names)
53
+ if expression_column_name?(column_names)
54
+ column_names = column_names.scan(/\w+/).join("_")
55
+ end
56
+
57
+ { column: column_names }
58
+ end
59
+
60
+ def expression_column_name?(column_name)
61
+ column_name.is_a?(String) && /\W/.match?(column_name)
62
+ end
63
+ end
64
+ module TableDefinition
65
+ include LegacyIndexName
66
+ def column(name, type, **options)
67
+ options[:_skip_validate_options] = true
68
+ super
69
+ end
70
+
71
+ def change(name, type, **options)
72
+ options[:_skip_validate_options] = true
73
+ super
74
+ end
75
+
76
+ def index(column_name, **options)
77
+ options[:name] = legacy_index_name(name, column_name) if options[:name].nil?
78
+ super
79
+ end
80
+
81
+ private
82
+ def raise_on_if_exist_options(options)
83
+ end
84
+ end
85
+
86
+ include LegacyIndexName
87
+
88
+ def add_column(table_name, column_name, type, **options)
89
+ options[:_skip_validate_options] = true
90
+ super
91
+ end
92
+
93
+ def add_index(table_name, column_name, **options)
94
+ options[:name] = legacy_index_name(table_name, column_name) if options[:name].nil?
95
+ super
96
+ end
97
+
98
+ def create_table(table_name, **options)
99
+ options[:_uses_legacy_table_name] = true
100
+ options[:_skip_validate_options] = true
101
+
102
+ super
103
+ end
104
+
105
+ def rename_table(table_name, new_name, **options)
106
+ options[:_uses_legacy_table_name] = true
107
+ super
108
+ end
109
+
110
+ def change_column(table_name, column_name, type, **options)
111
+ options[:_skip_validate_options] = true
112
+ if connection.adapter_name == "Mysql2" || connection.adapter_name == "Trilogy"
113
+ options[:collation] ||= :no_collation
114
+ end
115
+ super
116
+ end
117
+
118
+ def change_column_null(table_name, column_name, null, default = nil)
119
+ super(table_name, column_name, !!null, default)
120
+ end
121
+
122
+ def disable_extension(name, **options)
123
+ if connection.adapter_name == "PostgreSQL"
124
+ options[:force] = :cascade
125
+ end
126
+ super
127
+ end
128
+
129
+ def add_foreign_key(from_table, to_table, **options)
130
+ if connection.adapter_name == "PostgreSQL" && options[:deferrable] == true
131
+ options[:deferrable] = :immediate
132
+ end
133
+ super
134
+ end
135
+
136
+ private
137
+ def compatible_table_definition(t)
138
+ class << t
139
+ prepend TableDefinition
140
+ end
141
+ super
142
+ end
143
+ end
34
144
 
35
145
  class V6_1 < V7_0
36
146
  class PostgreSQLCompat
@@ -56,12 +166,13 @@ module ActiveRecord
56
166
  super
57
167
  end
58
168
 
59
- def create_table(table_name, **options)
60
- if block_given?
61
- super { |t| yield compatible_table_definition(t) }
62
- else
63
- super
169
+ def change_column(table_name, column_name, type, **options)
170
+ if type == :datetime
171
+ options[:precision] ||= nil
64
172
  end
173
+
174
+ type = PostgreSQLCompat.compatible_timestamp_type(type, connection)
175
+ super
65
176
  end
66
177
 
67
178
  module TableDefinition
@@ -70,10 +181,19 @@ module ActiveRecord
70
181
  super
71
182
  end
72
183
 
184
+ def change(name, type, index: nil, **options)
185
+ options[:precision] ||= nil
186
+ super
187
+ end
188
+
73
189
  def column(name, type, index: nil, **options)
74
190
  options[:precision] ||= nil
75
191
  super
76
192
  end
193
+
194
+ private
195
+ def raise_on_if_exist_options(options)
196
+ end
77
197
  end
78
198
 
79
199
  private
@@ -81,7 +201,7 @@ module ActiveRecord
81
201
  class << t
82
202
  prepend TableDefinition
83
203
  end
84
- t
204
+ super
85
205
  end
86
206
  end
87
207
 
@@ -103,30 +223,10 @@ module ActiveRecord
103
223
  options[:precision] ||= nil
104
224
  super
105
225
  end
106
- end
107
-
108
- def create_table(table_name, **options)
109
- if block_given?
110
- super { |t| yield compatible_table_definition(t) }
111
- else
112
- super
113
- end
114
- end
115
226
 
116
- def change_table(table_name, **options)
117
- if block_given?
118
- super { |t| yield compatible_table_definition(t) }
119
- else
120
- super
121
- end
122
- end
123
-
124
- def create_join_table(table_1, table_2, **options)
125
- if block_given?
126
- super { |t| yield compatible_table_definition(t) }
127
- else
128
- super
129
- end
227
+ private
228
+ def raise_on_if_exist_options(options)
229
+ end
130
230
  end
131
231
 
132
232
  def add_reference(table_name, ref_name, **options)
@@ -182,30 +282,6 @@ module ActiveRecord
182
282
  end
183
283
  end
184
284
 
185
- def create_table(table_name, **options)
186
- if block_given?
187
- super { |t| yield compatible_table_definition(t) }
188
- else
189
- super
190
- end
191
- end
192
-
193
- def change_table(table_name, **options)
194
- if block_given?
195
- super { |t| yield compatible_table_definition(t) }
196
- else
197
- super
198
- end
199
- end
200
-
201
- def create_join_table(table_1, table_2, **options)
202
- if block_given?
203
- super { |t| yield compatible_table_definition(t) }
204
- else
205
- super
206
- end
207
- end
208
-
209
285
  def add_timestamps(table_name, **options)
210
286
  options[:precision] ||= nil
211
287
  super
@@ -241,7 +317,7 @@ module ActiveRecord
241
317
  end
242
318
 
243
319
  def create_table(table_name, **options)
244
- if connection.adapter_name == "Mysql2"
320
+ if connection.adapter_name == "Mysql2" || connection.adapter_name == "Trilogy"
245
321
  super(table_name, options: "ENGINE=InnoDB", **options)
246
322
  else
247
323
  super
@@ -260,6 +336,10 @@ module ActiveRecord
260
336
  super(*args, type: :integer, **options)
261
337
  end
262
338
  alias :belongs_to :references
339
+
340
+ private
341
+ def raise_on_if_exist_options(options)
342
+ end
263
343
  end
264
344
 
265
345
  def create_table(table_name, **options)
@@ -269,7 +349,7 @@ module ActiveRecord
269
349
  end
270
350
  end
271
351
 
272
- unless connection.adapter_name == "Mysql2" && options[:id] == :bigint
352
+ unless ["Mysql2", "Trilogy"].include?(connection.adapter_name) && options[:id] == :bigint
273
353
  if [:integer, :bigint].include?(options[:id]) && !options.key?(:default)
274
354
  options[:default] = nil
275
355
  end
@@ -326,6 +406,10 @@ module ActiveRecord
326
406
  options[:null] = true if options[:null].nil?
327
407
  super
328
408
  end
409
+
410
+ private
411
+ def raise_on_if_exist_options(options)
412
+ end
329
413
  end
330
414
 
331
415
  def add_reference(table_name, ref_name, **options)
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class Migration
5
+ # The default strategy for executing migrations. Delegates method calls
6
+ # to the connection adapter.
7
+ class DefaultStrategy < ExecutionStrategy # :nodoc:
8
+ private
9
+ def method_missing(method, *arguments, &block)
10
+ connection.send(method, *arguments, &block)
11
+ end
12
+ ruby2_keywords(:method_missing)
13
+
14
+ def respond_to_missing?(method, *)
15
+ connection.respond_to?(method) || super
16
+ end
17
+
18
+ def connection
19
+ migration.connection
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class Migration
5
+ # ExecutionStrategy is used by the migration to respond to any method calls
6
+ # that the migration class does not implement directly. This is the base strategy.
7
+ # All strategies should inherit from this class.
8
+ #
9
+ # The ExecutionStrategy receives the current +migration+ when initialized.
10
+ class ExecutionStrategy # :nodoc:
11
+ def initialize(migration)
12
+ @migration = migration
13
+ end
14
+
15
+ private
16
+ attr_reader :migration
17
+ end
18
+ end
19
+ end