activerecord 6.0.5 → 6.1.0.rc1

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 (242) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +764 -888
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_record/aggregations.rb +1 -1
  6. data/lib/active_record/association_relation.rb +22 -14
  7. data/lib/active_record/associations/alias_tracker.rb +19 -15
  8. data/lib/active_record/associations/association.rb +39 -27
  9. data/lib/active_record/associations/association_scope.rb +11 -15
  10. data/lib/active_record/associations/belongs_to_association.rb +15 -5
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
  12. data/lib/active_record/associations/builder/association.rb +9 -3
  13. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  14. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -1
  16. data/lib/active_record/associations/builder/has_many.rb +6 -2
  17. data/lib/active_record/associations/builder/has_one.rb +11 -14
  18. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  19. data/lib/active_record/associations/collection_association.rb +19 -13
  20. data/lib/active_record/associations/collection_proxy.rb +12 -5
  21. data/lib/active_record/associations/foreign_association.rb +13 -0
  22. data/lib/active_record/associations/has_many_association.rb +24 -2
  23. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  24. data/lib/active_record/associations/has_one_association.rb +15 -1
  25. data/lib/active_record/associations/join_dependency/join_association.rb +29 -14
  26. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  27. data/lib/active_record/associations/join_dependency.rb +63 -49
  28. data/lib/active_record/associations/preloader/association.rb +13 -5
  29. data/lib/active_record/associations/preloader/through_association.rb +1 -1
  30. data/lib/active_record/associations/preloader.rb +5 -3
  31. data/lib/active_record/associations/singular_association.rb +1 -1
  32. data/lib/active_record/associations.rb +114 -11
  33. data/lib/active_record/attribute_assignment.rb +10 -8
  34. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
  35. data/lib/active_record/attribute_methods/dirty.rb +1 -11
  36. data/lib/active_record/attribute_methods/primary_key.rb +6 -2
  37. data/lib/active_record/attribute_methods/query.rb +3 -6
  38. data/lib/active_record/attribute_methods/read.rb +8 -11
  39. data/lib/active_record/attribute_methods/serialization.rb +4 -4
  40. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
  41. data/lib/active_record/attribute_methods/write.rb +12 -20
  42. data/lib/active_record/attribute_methods.rb +52 -48
  43. data/lib/active_record/attributes.rb +27 -7
  44. data/lib/active_record/autosave_association.rb +47 -30
  45. data/lib/active_record/base.rb +2 -14
  46. data/lib/active_record/callbacks.rb +32 -22
  47. data/lib/active_record/coders/yaml_column.rb +1 -1
  48. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +180 -134
  49. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  50. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -22
  51. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -7
  52. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  53. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  54. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  55. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +110 -30
  56. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +224 -85
  58. data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -24
  59. data/lib/active_record/connection_adapters/abstract_adapter.rb +31 -70
  60. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +123 -87
  61. data/lib/active_record/connection_adapters/column.rb +15 -1
  62. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  63. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  64. data/lib/active_record/connection_adapters/mysql/database_statements.rb +22 -24
  65. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
  66. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  67. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +33 -6
  68. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  69. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
  70. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +3 -3
  71. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  72. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
  73. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  74. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  75. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  76. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +12 -53
  77. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  78. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  79. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -10
  80. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  84. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  88. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
  90. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
  91. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  92. data/lib/active_record/connection_adapters/postgresql_adapter.rb +72 -55
  93. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  94. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  95. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +30 -5
  96. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
  97. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  98. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +36 -3
  99. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +48 -50
  100. data/lib/active_record/connection_adapters.rb +50 -0
  101. data/lib/active_record/connection_handling.rb +210 -71
  102. data/lib/active_record/core.rb +215 -49
  103. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  104. data/lib/active_record/database_configurations/database_config.rb +52 -9
  105. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  106. data/lib/active_record/database_configurations/url_config.rb +15 -40
  107. data/lib/active_record/database_configurations.rb +124 -85
  108. data/lib/active_record/delegated_type.rb +209 -0
  109. data/lib/active_record/destroy_association_async_job.rb +36 -0
  110. data/lib/active_record/enum.rb +33 -23
  111. data/lib/active_record/errors.rb +47 -12
  112. data/lib/active_record/explain.rb +9 -4
  113. data/lib/active_record/explain_subscriber.rb +1 -1
  114. data/lib/active_record/fixture_set/file.rb +10 -17
  115. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  116. data/lib/active_record/fixture_set/render_context.rb +1 -1
  117. data/lib/active_record/fixture_set/table_row.rb +2 -2
  118. data/lib/active_record/fixtures.rb +54 -8
  119. data/lib/active_record/gem_version.rb +3 -3
  120. data/lib/active_record/inheritance.rb +40 -18
  121. data/lib/active_record/insert_all.rb +32 -5
  122. data/lib/active_record/integration.rb +3 -5
  123. data/lib/active_record/internal_metadata.rb +15 -4
  124. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  125. data/lib/active_record/locking/optimistic.rb +13 -16
  126. data/lib/active_record/locking/pessimistic.rb +6 -2
  127. data/lib/active_record/log_subscriber.rb +26 -8
  128. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  129. data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
  130. data/lib/active_record/middleware/database_selector.rb +4 -1
  131. data/lib/active_record/migration/command_recorder.rb +47 -27
  132. data/lib/active_record/migration/compatibility.rb +67 -17
  133. data/lib/active_record/migration.rb +113 -83
  134. data/lib/active_record/model_schema.rb +88 -42
  135. data/lib/active_record/nested_attributes.rb +2 -3
  136. data/lib/active_record/no_touching.rb +1 -1
  137. data/lib/active_record/persistence.rb +50 -45
  138. data/lib/active_record/query_cache.rb +15 -5
  139. data/lib/active_record/querying.rb +11 -6
  140. data/lib/active_record/railtie.rb +64 -44
  141. data/lib/active_record/railties/databases.rake +253 -98
  142. data/lib/active_record/readonly_attributes.rb +4 -0
  143. data/lib/active_record/reflection.rb +59 -44
  144. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  145. data/lib/active_record/relation/batches.rb +38 -31
  146. data/lib/active_record/relation/calculations.rb +100 -43
  147. data/lib/active_record/relation/finder_methods.rb +44 -14
  148. data/lib/active_record/relation/from_clause.rb +1 -1
  149. data/lib/active_record/relation/merger.rb +20 -23
  150. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  151. data/lib/active_record/relation/predicate_builder/association_query_value.rb +2 -2
  152. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +3 -3
  153. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  154. data/lib/active_record/relation/predicate_builder.rb +57 -33
  155. data/lib/active_record/relation/query_methods.rb +319 -196
  156. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  157. data/lib/active_record/relation/spawn_methods.rb +6 -5
  158. data/lib/active_record/relation/where_clause.rb +104 -57
  159. data/lib/active_record/relation.rb +90 -64
  160. data/lib/active_record/result.rb +41 -33
  161. data/lib/active_record/runtime_registry.rb +2 -2
  162. data/lib/active_record/sanitization.rb +6 -17
  163. data/lib/active_record/schema_dumper.rb +34 -4
  164. data/lib/active_record/schema_migration.rb +0 -4
  165. data/lib/active_record/scoping/named.rb +1 -17
  166. data/lib/active_record/secure_token.rb +16 -8
  167. data/lib/active_record/serialization.rb +5 -3
  168. data/lib/active_record/signed_id.rb +116 -0
  169. data/lib/active_record/statement_cache.rb +20 -4
  170. data/lib/active_record/store.rb +2 -2
  171. data/lib/active_record/suppressor.rb +2 -2
  172. data/lib/active_record/table_metadata.rb +36 -52
  173. data/lib/active_record/tasks/database_tasks.rb +139 -113
  174. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
  175. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
  176. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
  177. data/lib/active_record/test_databases.rb +5 -4
  178. data/lib/active_record/test_fixtures.rb +36 -33
  179. data/lib/active_record/timestamp.rb +4 -6
  180. data/lib/active_record/touch_later.rb +21 -21
  181. data/lib/active_record/transactions.rb +15 -64
  182. data/lib/active_record/type/serialized.rb +6 -2
  183. data/lib/active_record/type.rb +8 -1
  184. data/lib/active_record/type_caster/connection.rb +0 -1
  185. data/lib/active_record/type_caster/map.rb +8 -5
  186. data/lib/active_record/validations/associated.rb +1 -1
  187. data/lib/active_record/validations/numericality.rb +35 -0
  188. data/lib/active_record/validations/uniqueness.rb +24 -4
  189. data/lib/active_record/validations.rb +1 -0
  190. data/lib/active_record.rb +7 -14
  191. data/lib/arel/attributes/attribute.rb +4 -0
  192. data/lib/arel/collectors/bind.rb +5 -0
  193. data/lib/arel/collectors/composite.rb +8 -0
  194. data/lib/arel/collectors/sql_string.rb +7 -0
  195. data/lib/arel/collectors/substitute_binds.rb +7 -0
  196. data/lib/arel/nodes/binary.rb +82 -8
  197. data/lib/arel/nodes/bind_param.rb +8 -0
  198. data/lib/arel/nodes/casted.rb +21 -9
  199. data/lib/arel/nodes/equality.rb +6 -9
  200. data/lib/arel/nodes/grouping.rb +3 -0
  201. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  202. data/lib/arel/nodes/in.rb +8 -1
  203. data/lib/arel/nodes/infix_operation.rb +13 -1
  204. data/lib/arel/nodes/join_source.rb +1 -1
  205. data/lib/arel/nodes/node.rb +7 -6
  206. data/lib/arel/nodes/ordering.rb +27 -0
  207. data/lib/arel/nodes/sql_literal.rb +3 -0
  208. data/lib/arel/nodes/table_alias.rb +7 -3
  209. data/lib/arel/nodes/unary.rb +0 -1
  210. data/lib/arel/nodes.rb +3 -1
  211. data/lib/arel/predications.rb +12 -18
  212. data/lib/arel/select_manager.rb +1 -2
  213. data/lib/arel/table.rb +13 -5
  214. data/lib/arel/visitors/dot.rb +14 -2
  215. data/lib/arel/visitors/mysql.rb +11 -1
  216. data/lib/arel/visitors/postgresql.rb +15 -4
  217. data/lib/arel/visitors/to_sql.rb +89 -78
  218. data/lib/arel/visitors.rb +0 -7
  219. data/lib/arel.rb +5 -13
  220. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  221. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  222. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +3 -3
  223. data/lib/rails/generators/active_record/migration.rb +6 -1
  224. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  225. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  226. metadata +30 -32
  227. data/lib/active_record/advisory_lock_base.rb +0 -18
  228. data/lib/active_record/attribute_decorators.rb +0 -88
  229. data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
  230. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  231. data/lib/active_record/define_callbacks.rb +0 -22
  232. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  233. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  234. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  235. data/lib/arel/attributes.rb +0 -22
  236. data/lib/arel/visitors/depth_first.rb +0 -203
  237. data/lib/arel/visitors/ibm_db.rb +0 -34
  238. data/lib/arel/visitors/informix.rb +0 -62
  239. data/lib/arel/visitors/mssql.rb +0 -156
  240. data/lib/arel/visitors/oracle.rb +0 -158
  241. data/lib/arel/visitors/oracle12.rb +0 -65
  242. data/lib/arel/visitors/where_sql.rb +0 -22
@@ -115,8 +115,17 @@ module ActiveRecord
115
115
  #
116
116
  # Sets the column to sort records by when no explicit order clause is used
117
117
  # during an ordered finder call. Useful when the primary key is not an
118
- # auto-incrementing integer, for example when it's a UUID. Note that using
119
- # a non-unique column can result in non-deterministic results.
118
+ # auto-incrementing integer, for example when it's a UUID. Records are subsorted
119
+ # by the primary key if it exists to ensure deterministic results.
120
+
121
+ ##
122
+ # :singleton-method: immutable_strings_by_default=
123
+ # :call-seq: immutable_strings_by_default=(bool)
124
+ #
125
+ # Determines whether columns should infer their type as `:string` or
126
+ # `:immutable_string`. This setting does not affect the behavior of
127
+ # `attribute :foo, :string`. Defaults to false.
128
+
120
129
  included do
121
130
  mattr_accessor :primary_key_prefix_type, instance_writer: false
122
131
 
@@ -126,12 +135,13 @@ module ActiveRecord
126
135
  class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
127
136
  class_attribute :pluralize_table_names, instance_writer: false, default: true
128
137
  class_attribute :implicit_order_column, instance_accessor: false
138
+ class_attribute :immutable_strings_by_default, instance_accessor: false
129
139
 
130
140
  self.protected_environments = ["production"]
131
141
  self.inheritance_column = "type"
132
142
  self.ignored_columns = [].freeze
133
143
 
134
- delegate :type_for_attribute, to: :class
144
+ delegate :type_for_attribute, :column_for_attribute, to: :class
135
145
 
136
146
  initialize_load_schema_monitor
137
147
  end
@@ -287,37 +297,9 @@ module ActiveRecord
287
297
 
288
298
  # Sets the columns names the model should ignore. Ignored columns won't have attribute
289
299
  # accessors defined, and won't be referenced in SQL queries.
290
- #
291
- # A common usage pattern for this method is to ensure all references to an attribute
292
- # have been removed and deployed, before a migration to drop the column from the database
293
- # has been deployed and run. Using this two step approach to dropping columns ensures there
294
- # is no code that raises errors due to having a cached schema in memory at the time the
295
- # schema migration is run.
296
- #
297
- # For example, given a model where you want to drop the "category" attribute, first mark it
298
- # as ignored:
299
- #
300
- # class Project < ActiveRecord::Base
301
- # # schema:
302
- # # id :bigint
303
- # # name :string, limit: 255
304
- # # category :string, limit: 255
305
- #
306
- # self.ignored_columns = [:category]
307
- # end
308
- #
309
- # The schema still contains `category`, but now the model omits it, so any meta-driven code or
310
- # schema caching will not attempt to use the column:
311
- #
312
- # Project.columns_hash["category"] => nil
313
- #
314
- # You will get an error if accessing that attribute directly, so ensure all usages of the
315
- # column are removed (automated tests can help you find any usages).
316
- #
317
- # user = Project.create!(name: "First Project")
318
- # user.category # => raises NoMethodError
319
300
  def ignored_columns=(columns)
320
- @ignored_columns = columns.map(&:to_s)
301
+ reload_schema_from_cache
302
+ @ignored_columns = columns.map(&:to_s).freeze
321
303
  end
322
304
 
323
305
  def sequence_name
@@ -384,7 +366,7 @@ module ActiveRecord
384
366
 
385
367
  def columns
386
368
  load_schema
387
- @columns ||= columns_hash.values
369
+ @columns ||= columns_hash.values.freeze
388
370
  end
389
371
 
390
372
  def attribute_types # :nodoc:
@@ -409,6 +391,8 @@ module ActiveRecord
409
391
  # a string or a symbol.
410
392
  def type_for_attribute(attr_name, &block)
411
393
  attr_name = attr_name.to_s
394
+ attr_name = attribute_aliases[attr_name] || attr_name
395
+
412
396
  if block
413
397
  attribute_types.fetch(attr_name, &block)
414
398
  else
@@ -416,11 +400,31 @@ module ActiveRecord
416
400
  end
417
401
  end
418
402
 
403
+ # Returns the column object for the named attribute.
404
+ # Returns an +ActiveRecord::ConnectionAdapters::NullColumn+ if the
405
+ # named attribute does not exist.
406
+ #
407
+ # class Person < ActiveRecord::Base
408
+ # end
409
+ #
410
+ # person = Person.new
411
+ # person.column_for_attribute(:name) # the result depends on the ConnectionAdapter
412
+ # # => #<ActiveRecord::ConnectionAdapters::Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>
413
+ #
414
+ # person.column_for_attribute(:nothing)
415
+ # # => #<ActiveRecord::ConnectionAdapters::NullColumn:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...>
416
+ def column_for_attribute(name)
417
+ name = name.to_s
418
+ columns_hash.fetch(name) do
419
+ ConnectionAdapters::NullColumn.new(name)
420
+ end
421
+ end
422
+
419
423
  # Returns a hash where the keys are column names and the values are
420
424
  # default values when instantiating the Active Record object for this table.
421
425
  def column_defaults
422
426
  load_schema
423
- @column_defaults ||= _default_attributes.deep_dup.to_hash
427
+ @column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
424
428
  end
425
429
 
426
430
  def _default_attributes # :nodoc:
@@ -430,7 +434,7 @@ module ActiveRecord
430
434
 
431
435
  # Returns an array of column names as strings.
432
436
  def column_names
433
- @column_names ||= columns.map(&:name)
437
+ @column_names ||= columns.map(&:name).freeze
434
438
  end
435
439
 
436
440
  def symbol_column_to_string(name_symbol) # :nodoc:
@@ -444,9 +448,8 @@ module ActiveRecord
444
448
  @content_columns ||= columns.reject do |c|
445
449
  c.name == primary_key ||
446
450
  c.name == inheritance_column ||
447
- c.name.end_with?("_id") ||
448
- c.name.end_with?("_count")
449
- end
451
+ c.name.end_with?("_id", "_count")
452
+ end.freeze
450
453
  end
451
454
 
452
455
  # Resets all the cached information about columns, which will cause them
@@ -456,7 +459,7 @@ module ActiveRecord
456
459
  # when just after creating a table you want to populate it with some default
457
460
  # values, eg:
458
461
  #
459
- # class CreateJobLevels < ActiveRecord::Migration[5.0]
462
+ # class CreateJobLevels < ActiveRecord::Migration[6.0]
460
463
  # def up
461
464
  # create_table :job_levels do |t|
462
465
  # t.integer :id
@@ -514,11 +517,20 @@ module ActiveRecord
514
517
  end
515
518
 
516
519
  def load_schema!
517
- @columns_hash = connection.schema_cache.columns_hash(table_name).except(*ignored_columns)
520
+ unless table_name
521
+ raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
522
+ end
523
+
524
+ columns_hash = connection.schema_cache.columns_hash(table_name)
525
+ columns_hash = columns_hash.except(*ignored_columns) unless ignored_columns.empty?
526
+ @columns_hash = columns_hash.freeze
518
527
  @columns_hash.each do |name, column|
528
+ type = connection.lookup_cast_type_from_column(column)
529
+ type = _convert_type_from_options(type)
530
+ warn_if_deprecated_type(column)
519
531
  define_attribute(
520
532
  name,
521
- connection.lookup_cast_type_from_column(column),
533
+ type,
522
534
  default: column.default,
523
535
  user_provided_default: false
524
536
  )
@@ -567,6 +579,40 @@ module ActiveRecord
567
579
  base_class.table_name
568
580
  end
569
581
  end
582
+
583
+ def _convert_type_from_options(type)
584
+ if immutable_strings_by_default && type.respond_to?(:to_immutable_string)
585
+ type.to_immutable_string
586
+ else
587
+ type
588
+ end
589
+ end
590
+
591
+ def warn_if_deprecated_type(column)
592
+ return if attributes_to_define_after_schema_loads.key?(column.name)
593
+ return unless column.respond_to?(:oid)
594
+
595
+ if column.array?
596
+ array_arguments = ", array: true"
597
+ else
598
+ array_arguments = ""
599
+ end
600
+
601
+ if column.sql_type.start_with?("interval")
602
+ precision_arguments = column.precision.presence && ", precision: #{column.precision}"
603
+ ActiveSupport::Deprecation.warn(<<~WARNING)
604
+ The behavior of the `:interval` type will be changing in Rails 6.2
605
+ to return an `ActiveSupport::Duration` object. If you'd like to keep
606
+ the old behavior, you can add this line to #{self.name} model:
607
+
608
+ attribute :#{column.name}, :string#{precision_arguments}#{array_arguments}
609
+
610
+ If you'd like the new behavior today, you can add this line:
611
+
612
+ attribute :#{column.name}, :interval#{precision_arguments}#{array_arguments}
613
+ WARNING
614
+ end
615
+ end
570
616
  end
571
617
  end
572
618
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "active_support/core_ext/hash/except"
4
4
  require "active_support/core_ext/module/redefine_method"
5
- require "active_support/core_ext/object/try"
6
5
  require "active_support/core_ext/hash/indifferent_access"
7
6
 
8
7
  module ActiveRecord
@@ -289,7 +288,7 @@ module ActiveRecord
289
288
  # [:allow_destroy]
290
289
  # If true, destroys any members from the attributes hash with a
291
290
  # <tt>_destroy</tt> key and a value that evaluates to +true+
292
- # (eg. 1, '1', true, or 'true'). This option is off by default.
291
+ # (e.g. 1, '1', true, or 'true'). This option is off by default.
293
292
  # [:reject_if]
294
293
  # Allows you to specify a Proc or a Symbol pointing to a method
295
294
  # that checks whether a record should be built for a certain attribute
@@ -510,7 +509,7 @@ module ActiveRecord
510
509
  if target_record
511
510
  existing_record = target_record
512
511
  else
513
- association.add_to_target(existing_record, :skip_callbacks)
512
+ association.add_to_target(existing_record, skip_callbacks: true)
514
513
  end
515
514
 
516
515
  assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
@@ -54,7 +54,7 @@ module ActiveRecord
54
54
  NoTouching.applied_to?(self.class)
55
55
  end
56
56
 
57
- def touch_later(*, **) # :nodoc:
57
+ def touch_later(*) # :nodoc:
58
58
  super unless no_touching?
59
59
  end
60
60
 
@@ -414,8 +414,8 @@ module ActiveRecord
414
414
 
415
415
  def _substitute_values(values)
416
416
  values.map do |name, value|
417
- attr = arel_attribute(name)
418
- bind = predicate_builder.build_bind_attribute(name, value)
417
+ attr = arel_table[name]
418
+ bind = predicate_builder.build_bind_attribute(attr.name, value)
419
419
  [attr, bind]
420
420
  end
421
421
  end
@@ -424,26 +424,30 @@ module ActiveRecord
424
424
  # Returns true if this object hasn't been saved yet -- that is, a record
425
425
  # for the object doesn't exist in the database yet; otherwise, returns false.
426
426
  def new_record?
427
- sync_with_transaction_state if @transaction_state&.finalized?
428
427
  @new_record
429
428
  end
430
429
 
430
+ # Returns true if this object was just created -- that is, prior to the last
431
+ # save, the object didn't exist in the database and new_record? would have
432
+ # returned true.
433
+ def previously_new_record?
434
+ @previously_new_record
435
+ end
436
+
431
437
  # Returns true if this object has been destroyed, otherwise returns false.
432
438
  def destroyed?
433
- sync_with_transaction_state if @transaction_state&.finalized?
434
439
  @destroyed
435
440
  end
436
441
 
437
442
  # Returns true if the record is persisted, i.e. it's not a new record and it was
438
443
  # not destroyed, otherwise returns false.
439
444
  def persisted?
440
- sync_with_transaction_state if @transaction_state&.finalized?
441
445
  !(@new_record || @destroyed)
442
446
  end
443
447
 
444
448
  ##
445
449
  # :call-seq:
446
- # save(*args)
450
+ # save(**options)
447
451
  #
448
452
  # Saves the model.
449
453
  #
@@ -466,15 +470,15 @@ module ActiveRecord
466
470
  #
467
471
  # Attributes marked as readonly are silently ignored if the record is
468
472
  # being updated.
469
- def save(*args, **options, &block)
470
- create_or_update(*args, **options, &block)
473
+ def save(**options, &block)
474
+ create_or_update(**options, &block)
471
475
  rescue ActiveRecord::RecordInvalid
472
476
  false
473
477
  end
474
478
 
475
479
  ##
476
480
  # :call-seq:
477
- # save!(*args)
481
+ # save!(**options)
478
482
  #
479
483
  # Saves the model.
480
484
  #
@@ -499,8 +503,8 @@ module ActiveRecord
499
503
  # being updated.
500
504
  #
501
505
  # Unless an error is raised, returns true.
502
- def save!(*args, **options, &block)
503
- create_or_update(*args, **options, &block) || raise(RecordNotSaved.new("Failed to save the record", self))
506
+ def save!(**options, &block)
507
+ create_or_update(**options, &block) || raise(RecordNotSaved.new("Failed to save the record", self))
504
508
  end
505
509
 
506
510
  # Deletes the record in the database and freezes this instance to
@@ -514,7 +518,7 @@ module ActiveRecord
514
518
  #
515
519
  # To enforce the object's +before_destroy+ and +after_destroy+
516
520
  # callbacks or any <tt>:dependent</tt> association
517
- # options, use <tt>#destroy</tt>.
521
+ # options, use #destroy.
518
522
  def delete
519
523
  _delete_row if persisted?
520
524
  @destroyed = true
@@ -565,12 +569,15 @@ module ActiveRecord
565
569
  # If you want to change the sti column as well, use #becomes! instead.
566
570
  def becomes(klass)
567
571
  became = klass.allocate
568
- became.send(:initialize)
569
- became.instance_variable_set("@attributes", @attributes)
570
- became.instance_variable_set("@mutations_from_database", @mutations_from_database ||= nil)
571
- became.instance_variable_set("@new_record", new_record?)
572
- became.instance_variable_set("@destroyed", destroyed?)
573
- became.errors.copy!(errors)
572
+
573
+ became.send(:initialize) do |becoming|
574
+ becoming.instance_variable_set(:@attributes, @attributes)
575
+ becoming.instance_variable_set(:@mutations_from_database, @mutations_from_database ||= nil)
576
+ becoming.instance_variable_set(:@new_record, new_record?)
577
+ becoming.instance_variable_set(:@destroyed, destroyed?)
578
+ becoming.errors.copy!(errors)
579
+ end
580
+
574
581
  became
575
582
  end
576
583
 
@@ -622,9 +629,6 @@ module ActiveRecord
622
629
  end
623
630
  end
624
631
 
625
- alias update_attributes update
626
- deprecate update_attributes: "please, use update instead"
627
-
628
632
  # Updates its receiver just like #update but calls #save! instead
629
633
  # of +save+, so an exception is raised if the record is invalid and saving will fail.
630
634
  def update!(attributes)
@@ -636,9 +640,6 @@ module ActiveRecord
636
640
  end
637
641
  end
638
642
 
639
- alias update_attributes! update!
640
- deprecate update_attributes!: "please, use update! instead"
641
-
642
643
  # Equivalent to <code>update_columns(name => value)</code>.
643
644
  def update_column(name, value)
644
645
  update_columns(name => value)
@@ -666,11 +667,8 @@ module ActiveRecord
666
667
 
667
668
  attributes = attributes.transform_keys do |key|
668
669
  name = key.to_s
669
- self.class.attribute_aliases[name] || name
670
- end
671
-
672
- attributes.each_key do |key|
673
- verify_readonly_attribute(key)
670
+ name = self.class.attribute_aliases[name] || name
671
+ verify_readonly_attribute(name) || name
674
672
  end
675
673
 
676
674
  id_in_database = self.id_in_database
@@ -703,9 +701,9 @@ module ActiveRecord
703
701
  # Returns +self+.
704
702
  def increment!(attribute, by = 1, touch: nil)
705
703
  increment(attribute, by)
706
- change = public_send(attribute) - (attribute_in_database(attribute.to_s) || 0)
704
+ change = public_send(attribute) - (public_send(:"#{attribute}_in_database") || 0)
707
705
  self.class.update_counters(id, attribute => change, touch: touch)
708
- clear_attribute_change(attribute) # eww
706
+ public_send(:"clear_#{attribute}_change")
709
707
  self
710
708
  end
711
709
 
@@ -809,8 +807,9 @@ module ActiveRecord
809
807
  self.class.unscoped { self.class.find(id) }
810
808
  end
811
809
 
812
- @attributes = fresh_object.instance_variable_get("@attributes")
810
+ @attributes = fresh_object.instance_variable_get(:@attributes)
813
811
  @new_record = false
812
+ @previously_new_record = false
814
813
  self
815
814
  end
816
815
 
@@ -849,17 +848,13 @@ module ActiveRecord
849
848
  # ball.touch(:updated_at) # => raises ActiveRecordError
850
849
  #
851
850
  def touch(*names, time: nil)
852
- unless persisted?
853
- raise ActiveRecordError, <<-MSG.squish
854
- cannot touch on a new or destroyed record object. Consider using
855
- persisted?, new_record?, or destroyed? before touching
856
- MSG
857
- end
851
+ _raise_record_not_touched_error unless persisted?
858
852
 
859
853
  attribute_names = timestamp_attributes_for_update_in_model
860
- attribute_names |= names.map!(&:to_s).map! { |name|
854
+ attribute_names |= names.map! do |name|
855
+ name = name.to_s
861
856
  self.class.attribute_aliases[name] || name
862
- }
857
+ end unless names.empty?
863
858
 
864
859
  unless attribute_names.empty?
865
860
  affected_rows = _touch_row(attribute_names, time)
@@ -919,6 +914,8 @@ module ActiveRecord
919
914
  @_trigger_update_callback = affected_rows == 1
920
915
  end
921
916
 
917
+ @previously_new_record = false
918
+
922
919
  yield(self) if block_given?
923
920
 
924
921
  affected_rows
@@ -936,6 +933,7 @@ module ActiveRecord
936
933
  self.id ||= new_id if @primary_key
937
934
 
938
935
  @new_record = false
936
+ @previously_new_record = true
939
937
 
940
938
  yield(self) if block_given?
941
939
 
@@ -943,7 +941,7 @@ module ActiveRecord
943
941
  end
944
942
 
945
943
  def verify_readonly_attribute(name)
946
- raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attributes.include?(name)
944
+ raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attribute?(name)
947
945
  end
948
946
 
949
947
  def _raise_record_not_destroyed
@@ -953,14 +951,21 @@ module ActiveRecord
953
951
  @_association_destroy_exception = nil
954
952
  end
955
953
 
954
+ def _raise_readonly_record_error
955
+ raise ReadOnlyRecord, "#{self.class} is marked as readonly"
956
+ end
957
+
958
+ def _raise_record_not_touched_error
959
+ raise ActiveRecordError, <<~MSG.squish
960
+ Cannot touch on a new or destroyed record object. Consider using
961
+ persisted?, new_record?, or destroyed? before touching.
962
+ MSG
963
+ end
964
+
956
965
  # The name of the method used to touch a +belongs_to+ association when the
957
966
  # +:touch+ option is used.
958
967
  def belongs_to_touch_method
959
968
  :touch
960
969
  end
961
-
962
- def _raise_readonly_record_error
963
- raise ReadOnlyRecord, "#{self.class} is marked as readonly"
964
- end
965
970
  end
966
971
  end
@@ -28,18 +28,28 @@ module ActiveRecord
28
28
  def self.run
29
29
  pools = []
30
30
 
31
- ActiveRecord::Base.connection_handlers.each do |key, handler|
32
- pools << handler.connection_pool_list.reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! }
31
+ if ActiveRecord::Base.legacy_connection_handling
32
+ ActiveRecord::Base.connection_handlers.each do |key, handler|
33
+ pools.concat(handler.connection_pool_list.reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! })
34
+ end
35
+ else
36
+ pools.concat(ActiveRecord::Base.connection_handler.all_connection_pools.reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! })
33
37
  end
34
38
 
35
- pools.flatten
39
+ pools
36
40
  end
37
41
 
38
42
  def self.complete(pools)
39
43
  pools.each { |pool| pool.disable_query_cache! }
40
44
 
41
- ActiveRecord::Base.connection_handlers.each do |_, handler|
42
- handler.connection_pool_list.each do |pool|
45
+ if ActiveRecord::Base.legacy_connection_handling
46
+ ActiveRecord::Base.connection_handlers.each do |_, handler|
47
+ handler.connection_pool_list.each do |pool|
48
+ pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
49
+ end
50
+ end
51
+ else
52
+ ActiveRecord::Base.connection_handler.all_connection_pools.each do |pool|
43
53
  pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
44
54
  end
45
55
  end
@@ -13,10 +13,11 @@ module ActiveRecord
13
13
  :destroy_all, :delete_all, :update_all, :touch_all, :destroy_by, :delete_by,
14
14
  :find_each, :find_in_batches, :in_batches,
15
15
  :select, :reselect, :order, :reorder, :group, :limit, :offset, :joins, :left_joins, :left_outer_joins,
16
- :where, :rewhere, :preload, :extract_associated, :eager_load, :includes, :from, :lock, :readonly, :extending, :or,
17
- :having, :create_with, :distinct, :references, :none, :unscope, :optimizer_hints, :merge, :except, :only,
18
- :count, :average, :minimum, :maximum, :sum, :calculate, :annotate,
19
- :pluck, :pick, :ids
16
+ :where, :rewhere, :preload, :extract_associated, :eager_load, :includes, :from, :lock, :readonly,
17
+ :and, :or, :annotate, :optimizer_hints, :extending,
18
+ :having, :create_with, :distinct, :references, :none, :unscope, :merge, :except, :only,
19
+ :count, :average, :minimum, :maximum, :sum, :calculate,
20
+ :pluck, :pick, :ids, :strict_loading
20
21
  ].freeze # :nodoc:
21
22
  delegate(*QUERYING_METHODS, to: :all)
22
23
 
@@ -44,8 +45,12 @@ module ActiveRecord
44
45
  # Post.find_by_sql ["SELECT body FROM comments WHERE author = :user_id OR approved_by = :user_id", { :user_id => user_id }]
45
46
  def find_by_sql(sql, binds = [], preparable: nil, &block)
46
47
  result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
47
- column_types = result_set.column_types.dup
48
- attribute_types.each_key { |k| column_types.delete k }
48
+ column_types = result_set.column_types
49
+
50
+ unless column_types.empty?
51
+ column_types = column_types.reject { |k, _| attribute_types.key?(k) }
52
+ end
53
+
49
54
  message_bus = ActiveSupport::Notifications.instrumenter
50
55
 
51
56
  payload = {