activerecord 6.1.7.4 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (238) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1055 -1170
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_record/aggregations.rb +1 -1
  6. data/lib/active_record/association_relation.rb +0 -10
  7. data/lib/active_record/associations/association.rb +33 -17
  8. data/lib/active_record/associations/association_scope.rb +1 -3
  9. data/lib/active_record/associations/belongs_to_association.rb +15 -4
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
  11. data/lib/active_record/associations/builder/association.rb +8 -2
  12. data/lib/active_record/associations/builder/belongs_to.rb +19 -6
  13. data/lib/active_record/associations/builder/collection_association.rb +10 -3
  14. data/lib/active_record/associations/builder/has_many.rb +3 -2
  15. data/lib/active_record/associations/builder/has_one.rb +2 -1
  16. data/lib/active_record/associations/builder/singular_association.rb +2 -2
  17. data/lib/active_record/associations/collection_association.rb +18 -19
  18. data/lib/active_record/associations/collection_proxy.rb +8 -3
  19. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  20. data/lib/active_record/associations/has_many_association.rb +1 -1
  21. data/lib/active_record/associations/has_many_through_association.rb +2 -1
  22. data/lib/active_record/associations/has_one_association.rb +10 -7
  23. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  24. data/lib/active_record/associations/join_dependency.rb +6 -2
  25. data/lib/active_record/associations/preloader/association.rb +186 -52
  26. data/lib/active_record/associations/preloader/batch.rb +48 -0
  27. data/lib/active_record/associations/preloader/branch.rb +147 -0
  28. data/lib/active_record/associations/preloader/through_association.rb +49 -13
  29. data/lib/active_record/associations/preloader.rb +39 -113
  30. data/lib/active_record/associations/singular_association.rb +8 -2
  31. data/lib/active_record/associations/through_association.rb +3 -3
  32. data/lib/active_record/associations.rb +90 -82
  33. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  34. data/lib/active_record/attribute_assignment.rb +1 -1
  35. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
  36. data/lib/active_record/attribute_methods/dirty.rb +49 -16
  37. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  38. data/lib/active_record/attribute_methods/query.rb +2 -2
  39. data/lib/active_record/attribute_methods/read.rb +7 -5
  40. data/lib/active_record/attribute_methods/serialization.rb +66 -12
  41. data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
  42. data/lib/active_record/attribute_methods/write.rb +7 -10
  43. data/lib/active_record/attribute_methods.rb +13 -14
  44. data/lib/active_record/attributes.rb +24 -35
  45. data/lib/active_record/autosave_association.rb +6 -21
  46. data/lib/active_record/base.rb +19 -1
  47. data/lib/active_record/callbacks.rb +2 -2
  48. data/lib/active_record/coders/yaml_column.rb +2 -14
  49. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
  50. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
  52. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +47 -561
  53. data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
  54. data/lib/active_record/connection_adapters/abstract/database_statements.rb +46 -22
  55. data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
  56. data/lib/active_record/connection_adapters/abstract/quoting.rb +43 -82
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +34 -13
  59. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +69 -18
  60. data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -22
  61. data/lib/active_record/connection_adapters/abstract_adapter.rb +149 -74
  62. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +97 -81
  63. data/lib/active_record/connection_adapters/column.rb +4 -0
  64. data/lib/active_record/connection_adapters/mysql/database_statements.rb +35 -23
  65. data/lib/active_record/connection_adapters/mysql/quoting.rb +35 -21
  66. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
  67. data/lib/active_record/connection_adapters/pool_config.rb +7 -7
  68. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -1
  69. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -12
  70. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  71. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  73. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
  74. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +28 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  77. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  78. data/lib/active_record/connection_adapters/postgresql/quoting.rb +50 -76
  79. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
  80. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
  81. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -1
  82. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
  83. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +27 -16
  84. data/lib/active_record/connection_adapters/postgresql_adapter.rb +207 -107
  85. data/lib/active_record/connection_adapters/schema_cache.rb +39 -38
  86. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +25 -19
  87. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +15 -16
  88. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
  89. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -30
  90. data/lib/active_record/connection_adapters.rb +6 -5
  91. data/lib/active_record/connection_handling.rb +47 -53
  92. data/lib/active_record/core.rb +121 -146
  93. data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -1
  94. data/lib/active_record/database_configurations/database_config.rb +12 -9
  95. data/lib/active_record/database_configurations/hash_config.rb +63 -5
  96. data/lib/active_record/database_configurations/url_config.rb +2 -2
  97. data/lib/active_record/database_configurations.rb +15 -32
  98. data/lib/active_record/delegated_type.rb +52 -11
  99. data/lib/active_record/destroy_association_async_job.rb +1 -1
  100. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  101. data/lib/active_record/dynamic_matchers.rb +1 -1
  102. data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
  103. data/lib/active_record/encryption/cipher.rb +53 -0
  104. data/lib/active_record/encryption/config.rb +44 -0
  105. data/lib/active_record/encryption/configurable.rb +61 -0
  106. data/lib/active_record/encryption/context.rb +35 -0
  107. data/lib/active_record/encryption/contexts.rb +72 -0
  108. data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
  109. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  110. data/lib/active_record/encryption/encryptable_record.rb +208 -0
  111. data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
  112. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  113. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  114. data/lib/active_record/encryption/encryptor.rb +155 -0
  115. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  116. data/lib/active_record/encryption/errors.rb +15 -0
  117. data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
  118. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  119. data/lib/active_record/encryption/key.rb +28 -0
  120. data/lib/active_record/encryption/key_generator.rb +42 -0
  121. data/lib/active_record/encryption/key_provider.rb +46 -0
  122. data/lib/active_record/encryption/message.rb +33 -0
  123. data/lib/active_record/encryption/message_serializer.rb +90 -0
  124. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  125. data/lib/active_record/encryption/properties.rb +76 -0
  126. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  127. data/lib/active_record/encryption/scheme.rb +99 -0
  128. data/lib/active_record/encryption.rb +55 -0
  129. data/lib/active_record/enum.rb +49 -42
  130. data/lib/active_record/errors.rb +67 -4
  131. data/lib/active_record/explain_registry.rb +11 -6
  132. data/lib/active_record/fixture_set/file.rb +15 -1
  133. data/lib/active_record/fixture_set/table_row.rb +41 -6
  134. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  135. data/lib/active_record/fixtures.rb +17 -20
  136. data/lib/active_record/future_result.rb +139 -0
  137. data/lib/active_record/gem_version.rb +4 -4
  138. data/lib/active_record/inheritance.rb +55 -17
  139. data/lib/active_record/insert_all.rb +80 -14
  140. data/lib/active_record/integration.rb +4 -3
  141. data/lib/active_record/internal_metadata.rb +1 -5
  142. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  143. data/lib/active_record/locking/optimistic.rb +10 -9
  144. data/lib/active_record/locking/pessimistic.rb +9 -3
  145. data/lib/active_record/log_subscriber.rb +14 -3
  146. data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
  147. data/lib/active_record/middleware/database_selector.rb +8 -3
  148. data/lib/active_record/middleware/shard_selector.rb +60 -0
  149. data/lib/active_record/migration/command_recorder.rb +4 -4
  150. data/lib/active_record/migration/compatibility.rb +89 -10
  151. data/lib/active_record/migration/join_table.rb +1 -1
  152. data/lib/active_record/migration.rb +110 -80
  153. data/lib/active_record/model_schema.rb +45 -58
  154. data/lib/active_record/nested_attributes.rb +13 -12
  155. data/lib/active_record/no_touching.rb +3 -3
  156. data/lib/active_record/null_relation.rb +2 -6
  157. data/lib/active_record/persistence.rb +219 -52
  158. data/lib/active_record/query_cache.rb +2 -2
  159. data/lib/active_record/query_logs.rb +138 -0
  160. data/lib/active_record/querying.rb +15 -5
  161. data/lib/active_record/railtie.rb +127 -17
  162. data/lib/active_record/railties/controller_runtime.rb +1 -1
  163. data/lib/active_record/railties/databases.rake +66 -129
  164. data/lib/active_record/readonly_attributes.rb +11 -0
  165. data/lib/active_record/reflection.rb +67 -50
  166. data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
  167. data/lib/active_record/relation/batches.rb +3 -3
  168. data/lib/active_record/relation/calculations.rb +40 -36
  169. data/lib/active_record/relation/delegation.rb +6 -6
  170. data/lib/active_record/relation/finder_methods.rb +31 -35
  171. data/lib/active_record/relation/merger.rb +20 -13
  172. data/lib/active_record/relation/predicate_builder.rb +1 -6
  173. data/lib/active_record/relation/query_attribute.rb +5 -11
  174. data/lib/active_record/relation/query_methods.rb +235 -63
  175. data/lib/active_record/relation/record_fetch_warning.rb +7 -9
  176. data/lib/active_record/relation/spawn_methods.rb +2 -2
  177. data/lib/active_record/relation/where_clause.rb +10 -19
  178. data/lib/active_record/relation.rb +169 -84
  179. data/lib/active_record/result.rb +17 -7
  180. data/lib/active_record/runtime_registry.rb +9 -13
  181. data/lib/active_record/sanitization.rb +11 -7
  182. data/lib/active_record/schema_dumper.rb +10 -3
  183. data/lib/active_record/schema_migration.rb +4 -4
  184. data/lib/active_record/scoping/default.rb +61 -12
  185. data/lib/active_record/scoping/named.rb +3 -11
  186. data/lib/active_record/scoping.rb +64 -34
  187. data/lib/active_record/serialization.rb +1 -1
  188. data/lib/active_record/signed_id.rb +1 -1
  189. data/lib/active_record/store.rb +1 -6
  190. data/lib/active_record/suppressor.rb +11 -15
  191. data/lib/active_record/tasks/database_tasks.rb +116 -58
  192. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  193. data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -12
  194. data/lib/active_record/test_databases.rb +1 -1
  195. data/lib/active_record/test_fixtures.rb +9 -13
  196. data/lib/active_record/timestamp.rb +3 -4
  197. data/lib/active_record/transactions.rb +9 -14
  198. data/lib/active_record/translation.rb +2 -2
  199. data/lib/active_record/type/adapter_specific_registry.rb +32 -7
  200. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  201. data/lib/active_record/type/internal/timezone.rb +2 -2
  202. data/lib/active_record/type/serialized.rb +1 -1
  203. data/lib/active_record/type/type_map.rb +17 -20
  204. data/lib/active_record/type.rb +1 -2
  205. data/lib/active_record/validations/associated.rb +1 -1
  206. data/lib/active_record/validations/uniqueness.rb +1 -1
  207. data/lib/active_record.rb +204 -28
  208. data/lib/arel/attributes/attribute.rb +0 -8
  209. data/lib/arel/crud.rb +28 -22
  210. data/lib/arel/delete_manager.rb +18 -4
  211. data/lib/arel/filter_predications.rb +9 -0
  212. data/lib/arel/insert_manager.rb +2 -3
  213. data/lib/arel/nodes/casted.rb +1 -1
  214. data/lib/arel/nodes/delete_statement.rb +12 -13
  215. data/lib/arel/nodes/filter.rb +10 -0
  216. data/lib/arel/nodes/function.rb +1 -0
  217. data/lib/arel/nodes/insert_statement.rb +2 -2
  218. data/lib/arel/nodes/select_core.rb +2 -2
  219. data/lib/arel/nodes/select_statement.rb +2 -2
  220. data/lib/arel/nodes/update_statement.rb +8 -3
  221. data/lib/arel/nodes.rb +1 -0
  222. data/lib/arel/predications.rb +11 -3
  223. data/lib/arel/select_manager.rb +10 -4
  224. data/lib/arel/table.rb +0 -1
  225. data/lib/arel/tree_manager.rb +0 -12
  226. data/lib/arel/update_manager.rb +18 -4
  227. data/lib/arel/visitors/dot.rb +80 -90
  228. data/lib/arel/visitors/mysql.rb +8 -2
  229. data/lib/arel/visitors/postgresql.rb +0 -10
  230. data/lib/arel/visitors/to_sql.rb +58 -2
  231. data/lib/arel.rb +2 -1
  232. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  233. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  234. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  235. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  236. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  237. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  238. metadata +58 -14
@@ -39,17 +39,23 @@ module ActiveRecord
39
39
  ##
40
40
  # :singleton-method:
41
41
  # Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:schema:dump
42
+ # It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
43
+ # Example:
44
+ # ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
45
+ # mysql2: ['--no-defaults', '--skip-add-drop-table'],
46
+ # postgres: '--no-tablespaces'
47
+ # }
42
48
  mattr_accessor :structure_dump_flags, instance_accessor: false
43
49
 
44
50
  ##
45
51
  # :singleton-method:
46
52
  # Extra flags passed to database CLI tool when calling db:schema:load
53
+ # It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
47
54
  mattr_accessor :structure_load_flags, instance_accessor: false
48
55
 
49
56
  extend self
50
57
 
51
- attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
52
- deprecate :current_config=
58
+ attr_writer :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
53
59
  attr_accessor :database_configuration
54
60
 
55
61
  LOCAL_HOSTS = ["127.0.0.1", "localhost"]
@@ -103,11 +109,6 @@ module ActiveRecord
103
109
  @env ||= Rails.env
104
110
  end
105
111
 
106
- def spec
107
- @spec ||= "primary"
108
- end
109
- deprecate spec: "please use name instead"
110
-
111
112
  def name
112
113
  @name ||= "primary"
113
114
  end
@@ -116,18 +117,6 @@ module ActiveRecord
116
117
  @seed_loader ||= Rails.application
117
118
  end
118
119
 
119
- def current_config(options = {})
120
- if options.has_key?(:config)
121
- @current_config = options[:config]
122
- else
123
- env_name = options[:env] || env
124
- name = options[:spec] || "primary"
125
-
126
- @current_config ||= ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: name)&.configuration_hash
127
- end
128
- end
129
- deprecate :current_config
130
-
131
120
  def create(configuration, *arguments)
132
121
  db_config = resolve_configuration(configuration)
133
122
  database_adapter_for(db_config, *arguments).create
@@ -154,7 +143,7 @@ module ActiveRecord
154
143
  begin
155
144
  Rails.application.config.load_database_yaml
156
145
  rescue
157
- unless ActiveRecord::Base.suppress_multiple_database_warning
146
+ unless ActiveRecord.suppress_multiple_database_warning
158
147
  $stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB."
159
148
  end
160
149
 
@@ -171,12 +160,14 @@ module ActiveRecord
171
160
  return if database_configs.count == 1
172
161
 
173
162
  database_configs.each do |db_config|
163
+ next unless db_config.database_tasks?
164
+
174
165
  yield db_config.name
175
166
  end
176
167
  end
177
168
 
178
169
  def raise_for_multi_db(environment = env, command:)
179
- db_configs = ActiveRecord::Base.configurations.configs_for(env_name: environment)
170
+ db_configs = configs_for(env_name: environment)
180
171
 
181
172
  if db_configs.count > 1
182
173
  dbs_list = []
@@ -194,6 +185,38 @@ module ActiveRecord
194
185
  ActiveRecord::Base.establish_connection(environment.to_sym)
195
186
  end
196
187
 
188
+ def prepare_all
189
+ seed = false
190
+
191
+ configs_for(env_name: env).each do |db_config|
192
+ ActiveRecord::Base.establish_connection(db_config)
193
+
194
+ # Skipped when no database
195
+ migrate
196
+
197
+ if ActiveRecord.dump_schema_after_migration
198
+ dump_schema(db_config, ActiveRecord.schema_format)
199
+ end
200
+ rescue ActiveRecord::NoDatabaseError
201
+ create_current(db_config.env_name, db_config.name)
202
+
203
+ if File.exist?(schema_dump_path(db_config))
204
+ load_schema(
205
+ db_config,
206
+ ActiveRecord.schema_format,
207
+ nil
208
+ )
209
+ else
210
+ migrate
211
+ end
212
+
213
+ seed = true
214
+ end
215
+
216
+ ActiveRecord::Base.establish_connection
217
+ load_seed if seed
218
+ end
219
+
197
220
  def drop(configuration, *arguments)
198
221
  db_config = resolve_configuration(configuration)
199
222
  database_adapter_for(db_config, *arguments).drop
@@ -223,19 +246,21 @@ module ActiveRecord
223
246
  private :truncate_tables
224
247
 
225
248
  def truncate_all(environment = env)
226
- ActiveRecord::Base.configurations.configs_for(env_name: environment).each do |db_config|
249
+ configs_for(env_name: environment).each do |db_config|
227
250
  truncate_tables(db_config)
228
251
  end
229
252
  end
230
253
 
231
- def migrate
254
+ def migrate(version = nil)
232
255
  check_target_version
233
256
 
234
257
  scope = ENV["SCOPE"]
235
258
  verbose_was, Migration.verbose = Migration.verbose, verbose?
236
259
 
237
- Base.connection.migration_context.migrate(target_version) do |migration|
260
+ Base.connection.migration_context.migrate(target_version || version) do |migration|
238
261
  scope.blank? || scope == migration.scope
262
+ end.tap do |migrations_ran|
263
+ Migration.write("No migrations ran. (using #{scope} scope)") if scope.present? && migrations_ran.empty?
239
264
  end
240
265
 
241
266
  ActiveRecord::Base.clear_cache!
@@ -243,6 +268,23 @@ module ActiveRecord
243
268
  Migration.verbose = verbose_was
244
269
  end
245
270
 
271
+ def db_configs_with_versions(db_configs) # :nodoc:
272
+ db_configs_with_versions = Hash.new { |h, k| h[k] = [] }
273
+
274
+ db_configs.each do |db_config|
275
+ ActiveRecord::Base.establish_connection(db_config)
276
+ versions_to_run = ActiveRecord::Base.connection.migration_context.pending_migration_versions
277
+ target_version = ActiveRecord::Tasks::DatabaseTasks.target_version
278
+
279
+ versions_to_run.each do |version|
280
+ next if target_version && target_version != version
281
+ db_configs_with_versions[version] << db_config
282
+ end
283
+ end
284
+
285
+ db_configs_with_versions
286
+ end
287
+
246
288
  def migrate_status
247
289
  unless ActiveRecord::Base.connection.schema_migration.table_exists?
248
290
  Kernel.abort "Schema migrations table does not exist yet."
@@ -269,7 +311,7 @@ module ActiveRecord
269
311
  end
270
312
 
271
313
  def charset_current(env_name = env, db_name = name)
272
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: db_name)
314
+ db_config = configs_for(env_name: env_name, name: db_name)
273
315
  charset(db_config)
274
316
  end
275
317
 
@@ -279,7 +321,7 @@ module ActiveRecord
279
321
  end
280
322
 
281
323
  def collation_current(env_name = env, db_name = name)
282
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: db_name)
324
+ db_config = configs_for(env_name: env_name, name: db_name)
283
325
  collation(db_config)
284
326
  end
285
327
 
@@ -305,17 +347,19 @@ module ActiveRecord
305
347
  def structure_dump(configuration, *arguments)
306
348
  db_config = resolve_configuration(configuration)
307
349
  filename = arguments.delete_at(0)
308
- database_adapter_for(db_config, *arguments).structure_dump(filename, structure_dump_flags)
350
+ flags = structure_dump_flags_for(db_config.adapter)
351
+ database_adapter_for(db_config, *arguments).structure_dump(filename, flags)
309
352
  end
310
353
 
311
354
  def structure_load(configuration, *arguments)
312
355
  db_config = resolve_configuration(configuration)
313
356
  filename = arguments.delete_at(0)
314
- database_adapter_for(db_config, *arguments).structure_load(filename, structure_load_flags)
357
+ flags = structure_load_flags_for(db_config.adapter)
358
+ database_adapter_for(db_config, *arguments).structure_load(filename, flags)
315
359
  end
316
360
 
317
- def load_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
318
- file ||= dump_filename(db_config.name, format)
361
+ def load_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
362
+ file ||= schema_dump_path(db_config, format)
319
363
 
320
364
  verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
321
365
  check_schema_file(file)
@@ -336,16 +380,10 @@ module ActiveRecord
336
380
  Migration.verbose = verbose_was
337
381
  end
338
382
 
339
- def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = nil, name = nil)
383
+ def schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil)
340
384
  db_config = resolve_configuration(configuration)
341
385
 
342
- if environment || name
343
- ActiveSupport::Deprecation.warn("`environment` and `name` will be removed as parameters in 7.0.0, you may now pass an ActiveRecord::DatabaseConfigurations::DatabaseConfig as `configuration` instead.")
344
- end
345
-
346
- name ||= db_config.name
347
-
348
- file ||= dump_filename(name, format)
386
+ file ||= schema_dump_path(db_config)
349
387
 
350
388
  return true unless File.exist?(file)
351
389
 
@@ -357,8 +395,8 @@ module ActiveRecord
357
395
  ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
358
396
  end
359
397
 
360
- def reconstruct_from_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
361
- file ||= dump_filename(db_config.name, format)
398
+ def reconstruct_from_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
399
+ file ||= schema_dump_path(db_config, format)
362
400
 
363
401
  check_schema_file(file)
364
402
 
@@ -375,9 +413,9 @@ module ActiveRecord
375
413
  load_schema(db_config, format, file)
376
414
  end
377
415
 
378
- def dump_schema(db_config, format = ActiveRecord::Base.schema_format) # :nodoc:
416
+ def dump_schema(db_config, format = ActiveRecord.schema_format) # :nodoc:
379
417
  require "active_record/schema_dumper"
380
- filename = dump_filename(db_config.name, format)
418
+ filename = schema_dump_path(db_config, format)
381
419
  connection = ActiveRecord::Base.connection
382
420
 
383
421
  FileUtils.mkdir_p(db_dir)
@@ -397,11 +435,7 @@ module ActiveRecord
397
435
  end
398
436
  end
399
437
 
400
- def schema_file(format = ActiveRecord::Base.schema_format)
401
- File.join(db_dir, schema_file_type(format))
402
- end
403
-
404
- def schema_file_type(format = ActiveRecord::Base.schema_format)
438
+ def schema_file_type(format = ActiveRecord.schema_format)
405
439
  case format
406
440
  when :ruby
407
441
  "schema.rb"
@@ -409,15 +443,19 @@ module ActiveRecord
409
443
  "structure.sql"
410
444
  end
411
445
  end
446
+ deprecate :schema_file_type
412
447
 
413
- def dump_filename(db_config_name, format = ActiveRecord::Base.schema_format)
414
- filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
415
- schema_file_type(format)
448
+ def schema_dump_path(db_config, format = ActiveRecord.schema_format)
449
+ return ENV["SCHEMA"] if ENV["SCHEMA"]
450
+
451
+ filename = db_config.schema_dump(format)
452
+ return unless filename
453
+
454
+ if File.dirname(filename) == ActiveRecord::Tasks::DatabaseTasks.db_dir
455
+ filename
416
456
  else
417
- "#{db_config_name}_#{schema_file_type(format)}"
457
+ File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
418
458
  end
419
-
420
- ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
421
459
  end
422
460
 
423
461
  def cache_dump_filename(db_config_name, schema_cache_path: nil)
@@ -430,7 +468,7 @@ module ActiveRecord
430
468
  schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
431
469
  end
432
470
 
433
- def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
471
+ def load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env)
434
472
  each_current_configuration(environment) do |db_config|
435
473
  load_schema(db_config, format, file)
436
474
  end
@@ -468,6 +506,10 @@ module ActiveRecord
468
506
  end
469
507
 
470
508
  private
509
+ def configs_for(**options)
510
+ Base.configurations.configs_for(**options)
511
+ end
512
+
471
513
  def resolve_configuration(configuration)
472
514
  Base.configurations.resolve(configuration)
473
515
  end
@@ -488,7 +530,7 @@ module ActiveRecord
488
530
  end
489
531
 
490
532
  def class_for_adapter(adapter)
491
- _key, task = @tasks.each_pair.detect { |pattern, _task| adapter[pattern] }
533
+ _key, task = @tasks.reverse_each.detect { |pattern, _task| adapter[pattern] }
492
534
  unless task
493
535
  raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
494
536
  end
@@ -500,7 +542,7 @@ module ActiveRecord
500
542
  environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
501
543
 
502
544
  environments.each do |env|
503
- ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
545
+ configs_for(env_name: env).each do |db_config|
504
546
  next if name && name != db_config.name
505
547
 
506
548
  yield db_config
@@ -509,7 +551,7 @@ module ActiveRecord
509
551
  end
510
552
 
511
553
  def each_local_configuration
512
- ActiveRecord::Base.configurations.configs_for.each do |db_config|
554
+ configs_for.each do |db_config|
513
555
  next unless db_config.database
514
556
 
515
557
  if local_database?(db_config)
@@ -526,7 +568,23 @@ module ActiveRecord
526
568
  end
527
569
 
528
570
  def schema_sha1(file)
529
- Digest::SHA1.hexdigest(File.read(file))
571
+ OpenSSL::Digest::SHA1.hexdigest(File.read(file))
572
+ end
573
+
574
+ def structure_dump_flags_for(adapter)
575
+ if structure_dump_flags.is_a?(Hash)
576
+ structure_dump_flags[adapter.to_sym]
577
+ else
578
+ structure_dump_flags
579
+ end
580
+ end
581
+
582
+ def structure_load_flags_for(adapter)
583
+ if structure_load_flags.is_a?(Hash)
584
+ structure_load_flags[adapter.to_sym]
585
+ else
586
+ structure_load_flags
587
+ end
530
588
  end
531
589
  end
532
590
  end
@@ -94,7 +94,7 @@ module ActiveRecord
94
94
  sslcapath: "--ssl-capath",
95
95
  sslcipher: "--ssl-cipher",
96
96
  sslkey: "--ssl-key"
97
- }.map { |opt, arg| "#{arg}=#{configuration_hash[opt]}" if configuration_hash[opt] }.compact
97
+ }.filter_map { |opt, arg| "#{arg}=#{configuration_hash[opt]}" if configuration_hash[opt] }
98
98
 
99
99
  args
100
100
  end
@@ -47,20 +47,22 @@ module ActiveRecord
47
47
  end
48
48
 
49
49
  def structure_dump(filename, extra_flags)
50
- set_psql_env
51
-
52
50
  search_path = \
53
- case ActiveRecord::Base.dump_schemas
51
+ case ActiveRecord.dump_schemas
54
52
  when :schema_search_path
55
53
  configuration_hash[:schema_search_path]
56
54
  when :all
57
55
  nil
58
56
  when String
59
- ActiveRecord::Base.dump_schemas
57
+ ActiveRecord.dump_schemas
60
58
  end
61
59
 
62
- args = ["--schema-only", "--no-privileges", "--no-owner", "--file", filename]
60
+ args = ["--schema-only", "--no-privileges", "--no-owner"]
61
+ args << "--no-comment" if connection.database_version >= 110_000
62
+ args.concat(["--file", filename])
63
+
63
64
  args.concat(Array(extra_flags)) if extra_flags
65
+
64
66
  unless search_path.blank?
65
67
  args += search_path.split(",").map do |part|
66
68
  "--schema=#{part.strip}"
@@ -79,7 +81,6 @@ module ActiveRecord
79
81
  end
80
82
 
81
83
  def structure_load(filename, extra_flags)
82
- set_psql_env
83
84
  args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--file", filename]
84
85
  args.concat(Array(extra_flags)) if extra_flags
85
86
  args << db_config.database
@@ -100,15 +101,21 @@ module ActiveRecord
100
101
  )
101
102
  end
102
103
 
103
- def set_psql_env
104
- ENV["PGHOST"] = db_config.host if db_config.host
105
- ENV["PGPORT"] = configuration_hash[:port].to_s if configuration_hash[:port]
106
- ENV["PGPASSWORD"] = configuration_hash[:password].to_s if configuration_hash[:password]
107
- ENV["PGUSER"] = configuration_hash[:username].to_s if configuration_hash[:username]
104
+ def psql_env
105
+ {}.tap do |env|
106
+ env["PGHOST"] = db_config.host if db_config.host
107
+ env["PGPORT"] = configuration_hash[:port].to_s if configuration_hash[:port]
108
+ env["PGPASSWORD"] = configuration_hash[:password].to_s if configuration_hash[:password]
109
+ env["PGUSER"] = configuration_hash[:username].to_s if configuration_hash[:username]
110
+ env["PGSSLMODE"] = configuration_hash[:sslmode].to_s if configuration_hash[:sslmode]
111
+ env["PGSSLCERT"] = configuration_hash[:sslcert].to_s if configuration_hash[:sslcert]
112
+ env["PGSSLKEY"] = configuration_hash[:sslkey].to_s if configuration_hash[:sslkey]
113
+ env["PGSSLROOTCERT"] = configuration_hash[:sslrootcert].to_s if configuration_hash[:sslrootcert]
114
+ end
108
115
  end
109
116
 
110
117
  def run_cmd(cmd, args, action)
111
- fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
118
+ fail run_cmd_error(cmd, args, action) unless Kernel.system(psql_env, cmd, *args)
112
119
  end
113
120
 
114
121
  def run_cmd_error(cmd, args, action)
@@ -14,7 +14,7 @@ module ActiveRecord
14
14
  ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
15
15
  db_config._database = "#{db_config.database}-#{i}"
16
16
 
17
- ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, ActiveRecord::Base.schema_format, nil)
17
+ ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, ActiveRecord.schema_format, nil)
18
18
  end
19
19
  ensure
20
20
  ActiveRecord::Base.establish_connection
@@ -134,7 +134,7 @@ module ActiveRecord
134
134
  @connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
135
135
  spec_name = payload[:spec_name] if payload.key?(:spec_name)
136
136
  shard = payload[:shard] if payload.key?(:shard)
137
- setup_shared_connection_pool if ActiveRecord::Base.legacy_connection_handling
137
+ setup_shared_connection_pool
138
138
 
139
139
  if spec_name
140
140
  begin
@@ -143,14 +143,10 @@ module ActiveRecord
143
143
  connection = nil
144
144
  end
145
145
 
146
- if connection
147
- setup_shared_connection_pool unless ActiveRecord::Base.legacy_connection_handling
148
-
149
- if !@fixture_connections.include?(connection)
150
- connection.begin_transaction joinable: false, _lazy: false
151
- connection.pool.lock_thread = true if lock_threads
152
- @fixture_connections << connection
153
- end
146
+ if connection && !@fixture_connections.include?(connection)
147
+ connection.begin_transaction joinable: false, _lazy: false
148
+ connection.pool.lock_thread = true if lock_threads
149
+ @fixture_connections << connection
154
150
  end
155
151
  end
156
152
  end
@@ -197,8 +193,8 @@ module ActiveRecord
197
193
  # need to share a connection pool so that the reading connection
198
194
  # can see data in the open transaction on the writing connection.
199
195
  def setup_shared_connection_pool
200
- if ActiveRecord::Base.legacy_connection_handling
201
- writing_handler = ActiveRecord::Base.connection_handlers[ActiveRecord::Base.writing_role]
196
+ if ActiveRecord.legacy_connection_handling
197
+ writing_handler = ActiveRecord::Base.connection_handlers[ActiveRecord.writing_role]
202
198
 
203
199
  ActiveRecord::Base.connection_handlers.values.each do |handler|
204
200
  if handler != writing_handler
@@ -225,7 +221,7 @@ module ActiveRecord
225
221
  handler.connection_pool_names.each do |name|
226
222
  pool_manager = handler.send(:owner_to_pool_manager)[name]
227
223
  pool_manager.shard_names.each do |shard_name|
228
- writing_pool_config = pool_manager.get_pool_config(ActiveRecord::Base.writing_role, shard_name)
224
+ writing_pool_config = pool_manager.get_pool_config(ActiveRecord.writing_role, shard_name)
229
225
  @saved_pool_configs[name][shard_name] ||= {}
230
226
  pool_manager.role_names.each do |role|
231
227
  next unless pool_config = pool_manager.get_pool_config(role, shard_name)
@@ -240,7 +236,7 @@ module ActiveRecord
240
236
  end
241
237
 
242
238
  def teardown_shared_connection_pool
243
- if ActiveRecord::Base.legacy_connection_handling
239
+ if ActiveRecord.legacy_connection_handling
244
240
  @legacy_saved_pool_configs.each_pair do |handler, names|
245
241
  names.each_pair do |name, shards|
246
242
  shards.each_pair do |shard_name, pool_config|
@@ -75,7 +75,7 @@ module ActiveRecord
75
75
  end
76
76
 
77
77
  def current_time_from_proper_timezone
78
- default_timezone == :utc ? Time.now.utc : Time.now
78
+ ActiveRecord.default_timezone == :utc ? Time.now.utc : Time.now
79
79
  end
80
80
 
81
81
  private
@@ -127,7 +127,7 @@ module ActiveRecord
127
127
  end
128
128
 
129
129
  def should_record_timestamps?
130
- record_timestamps && (!partial_writes? || has_changes_to_save?)
130
+ record_timestamps && (!partial_updates? || has_changes_to_save?)
131
131
  end
132
132
 
133
133
  def timestamp_attributes_for_create_in_model
@@ -148,8 +148,7 @@ module ActiveRecord
148
148
 
149
149
  def max_updated_column_timestamp
150
150
  timestamp_attributes_for_update_in_model
151
- .map { |attr| self[attr]&.to_time }
152
- .compact
151
+ .filter_map { |attr| self[attr]&.to_time }
153
152
  .max
154
153
  end
155
154
 
@@ -4,7 +4,7 @@ module ActiveRecord
4
4
  # See ActiveRecord::Transactions::ClassMethods for documentation.
5
5
  module Transactions
6
6
  extend ActiveSupport::Concern
7
- #:nodoc:
7
+ # :nodoc:
8
8
  ACTIONS = [:create, :destroy, :update]
9
9
 
10
10
  included do
@@ -290,19 +290,19 @@ module ActiveRecord
290
290
  self.class.transaction(**options, &block)
291
291
  end
292
292
 
293
- def destroy #:nodoc:
293
+ def destroy # :nodoc:
294
294
  with_transaction_returning_status { super }
295
295
  end
296
296
 
297
- def save(**) #:nodoc:
297
+ def save(**) # :nodoc:
298
298
  with_transaction_returning_status { super }
299
299
  end
300
300
 
301
- def save!(**) #:nodoc:
301
+ def save!(**) # :nodoc:
302
302
  with_transaction_returning_status { super }
303
303
  end
304
304
 
305
- def touch(*, **) #:nodoc:
305
+ def touch(*, **) # :nodoc:
306
306
  with_transaction_returning_status { super }
307
307
  end
308
308
 
@@ -314,8 +314,8 @@ module ActiveRecord
314
314
  #
315
315
  # Ensure that it is not called if the object was never persisted (failed create),
316
316
  # but call it after the commit of a destroyed object.
317
- def committed!(should_run_callbacks: true) #:nodoc:
318
- force_clear_transaction_record_state
317
+ def committed!(should_run_callbacks: true) # :nodoc:
318
+ @_start_transaction_state = nil
319
319
  if should_run_callbacks
320
320
  @_committed_already_called = true
321
321
  _run_commit_callbacks
@@ -326,7 +326,7 @@ module ActiveRecord
326
326
 
327
327
  # Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record
328
328
  # state should be rolled back to the beginning or just to the last savepoint.
329
- def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
329
+ def rolledback!(force_restore_state: false, should_run_callbacks: true) # :nodoc:
330
330
  if should_run_callbacks
331
331
  _run_rollback_callbacks
332
332
  end
@@ -389,12 +389,7 @@ module ActiveRecord
389
389
  def clear_transaction_record_state
390
390
  return unless @_start_transaction_state
391
391
  @_start_transaction_state[:level] -= 1
392
- force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
393
- end
394
-
395
- # Force to clear the transaction record state.
396
- def force_clear_transaction_record_state
397
- @_start_transaction_state = nil
392
+ @_start_transaction_state = nil if @_start_transaction_state[:level] < 1
398
393
  end
399
394
 
400
395
  # Restore the new record state and id of a record that was previously saved by a call to save_record_state.
@@ -5,7 +5,7 @@ module ActiveRecord
5
5
  include ActiveModel::Translation
6
6
 
7
7
  # Set the lookup ancestors for ActiveModel.
8
- def lookup_ancestors #:nodoc:
8
+ def lookup_ancestors # :nodoc:
9
9
  klass = self
10
10
  classes = [klass]
11
11
  return classes if klass == ActiveRecord::Base
@@ -17,7 +17,7 @@ module ActiveRecord
17
17
  end
18
18
 
19
19
  # Set the i18n scope to overwrite ActiveModel.
20
- def i18n_scope #:nodoc:
20
+ def i18n_scope # :nodoc:
21
21
  :activerecord
22
22
  end
23
23
  end
@@ -5,15 +5,40 @@ require "active_model/type/registry"
5
5
  module ActiveRecord
6
6
  # :stopdoc:
7
7
  module Type
8
- class AdapterSpecificRegistry < ActiveModel::Type::Registry
8
+ class AdapterSpecificRegistry # :nodoc:
9
+ def initialize
10
+ @registrations = []
11
+ end
12
+
13
+ def initialize_copy(other)
14
+ @registrations = @registrations.dup
15
+ super
16
+ end
17
+
9
18
  def add_modifier(options, klass, **args)
10
19
  registrations << DecorationRegistration.new(options, klass, **args)
11
20
  end
12
21
 
13
- private
14
- def registration_klass
15
- Registration
22
+ def register(type_name, klass = nil, **options, &block)
23
+ unless block_given?
24
+ block = proc { |_, *args| klass.new(*args) }
25
+ block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
16
26
  end
27
+ registrations << Registration.new(type_name, block, **options)
28
+ end
29
+
30
+ def lookup(symbol, *args, **kwargs)
31
+ registration = find_registration(symbol, *args, **kwargs)
32
+
33
+ if registration
34
+ registration.call(self, symbol, *args, **kwargs)
35
+ else
36
+ raise ArgumentError, "Unknown type #{symbol.inspect}"
37
+ end
38
+ end
39
+
40
+ private
41
+ attr_reader :registrations
17
42
 
18
43
  def find_registration(symbol, *args, **kwargs)
19
44
  registrations
@@ -22,7 +47,7 @@ module ActiveRecord
22
47
  end
23
48
  end
24
49
 
25
- class Registration
50
+ class Registration # :nodoc:
26
51
  def initialize(name, block, adapter: nil, override: nil)
27
52
  @name = name
28
53
  @block = block
@@ -89,7 +114,7 @@ module ActiveRecord
89
114
  end
90
115
  end
91
116
 
92
- class DecorationRegistration < Registration
117
+ class DecorationRegistration < Registration # :nodoc:
93
118
  def initialize(options, klass, adapter: nil)
94
119
  @options = options
95
120
  @klass = klass
@@ -120,7 +145,7 @@ module ActiveRecord
120
145
  end
121
146
  end
122
147
 
123
- class TypeConflictError < StandardError
148
+ class TypeConflictError < StandardError # :nodoc:
124
149
  end
125
150
  # :startdoc:
126
151
  end