activerecord 6.0.0 → 6.1.4

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 (270) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1178 -600
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/lib/active_record/aggregations.rb +5 -6
  6. data/lib/active_record/association_relation.rb +30 -10
  7. data/lib/active_record/associations/alias_tracker.rb +19 -16
  8. data/lib/active_record/associations/association.rb +55 -29
  9. data/lib/active_record/associations/association_scope.rb +19 -15
  10. data/lib/active_record/associations/belongs_to_association.rb +23 -10
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
  12. data/lib/active_record/associations/builder/association.rb +32 -5
  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 -3
  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 +25 -8
  20. data/lib/active_record/associations/collection_proxy.rb +14 -7
  21. data/lib/active_record/associations/foreign_association.rb +13 -0
  22. data/lib/active_record/associations/has_many_association.rb +24 -3
  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 +39 -16
  26. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  27. data/lib/active_record/associations/join_dependency.rb +77 -42
  28. data/lib/active_record/associations/preloader/association.rb +51 -25
  29. data/lib/active_record/associations/preloader/through_association.rb +2 -2
  30. data/lib/active_record/associations/preloader.rb +13 -8
  31. data/lib/active_record/associations/singular_association.rb +1 -1
  32. data/lib/active_record/associations/through_association.rb +1 -1
  33. data/lib/active_record/associations.rb +120 -13
  34. data/lib/active_record/attribute_assignment.rb +10 -9
  35. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
  36. data/lib/active_record/attribute_methods/dirty.rb +3 -13
  37. data/lib/active_record/attribute_methods/primary_key.rb +6 -4
  38. data/lib/active_record/attribute_methods/query.rb +3 -6
  39. data/lib/active_record/attribute_methods/read.rb +8 -12
  40. data/lib/active_record/attribute_methods/serialization.rb +11 -6
  41. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  42. data/lib/active_record/attribute_methods/write.rb +12 -21
  43. data/lib/active_record/attribute_methods.rb +64 -54
  44. data/lib/active_record/attributes.rb +33 -9
  45. data/lib/active_record/autosave_association.rb +63 -44
  46. data/lib/active_record/base.rb +2 -14
  47. data/lib/active_record/callbacks.rb +153 -24
  48. data/lib/active_record/coders/yaml_column.rb +12 -3
  49. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +202 -138
  50. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  51. data/lib/active_record/connection_adapters/abstract/database_statements.rb +87 -38
  52. data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -10
  53. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  54. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  55. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
  56. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +141 -52
  57. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  58. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +267 -105
  59. data/lib/active_record/connection_adapters/abstract/transaction.rb +94 -36
  60. data/lib/active_record/connection_adapters/abstract_adapter.rb +76 -79
  61. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -115
  62. data/lib/active_record/connection_adapters/column.rb +15 -1
  63. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  64. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  65. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  66. data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
  67. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  68. data/lib/active_record/connection_adapters/mysql/quoting.rb +18 -3
  69. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
  70. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  71. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
  72. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
  73. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  74. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
  75. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  76. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  77. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  78. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -56
  79. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
  80. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  81. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  83. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
  85. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  87. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  91. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
  92. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  96. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  97. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
  98. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
  99. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  100. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
  101. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  102. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  103. data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -65
  104. data/lib/active_record/connection_adapters/schema_cache.rb +106 -15
  105. data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
  106. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +38 -12
  107. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
  108. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  109. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
  110. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -57
  111. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  112. data/lib/active_record/connection_adapters.rb +52 -0
  113. data/lib/active_record/connection_handling.rb +219 -81
  114. data/lib/active_record/core.rb +268 -71
  115. data/lib/active_record/counter_cache.rb +4 -1
  116. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  117. data/lib/active_record/database_configurations/database_config.rb +52 -9
  118. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  119. data/lib/active_record/database_configurations/url_config.rb +15 -41
  120. data/lib/active_record/database_configurations.rb +124 -85
  121. data/lib/active_record/delegated_type.rb +209 -0
  122. data/lib/active_record/destroy_association_async_job.rb +36 -0
  123. data/lib/active_record/dynamic_matchers.rb +2 -3
  124. data/lib/active_record/enum.rb +80 -38
  125. data/lib/active_record/errors.rb +47 -12
  126. data/lib/active_record/explain.rb +9 -5
  127. data/lib/active_record/explain_subscriber.rb +1 -1
  128. data/lib/active_record/fixture_set/file.rb +10 -17
  129. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  130. data/lib/active_record/fixture_set/render_context.rb +1 -1
  131. data/lib/active_record/fixture_set/table_row.rb +2 -3
  132. data/lib/active_record/fixture_set/table_rows.rb +0 -1
  133. data/lib/active_record/fixtures.rb +58 -12
  134. data/lib/active_record/gem_version.rb +2 -2
  135. data/lib/active_record/inheritance.rb +40 -21
  136. data/lib/active_record/insert_all.rb +43 -10
  137. data/lib/active_record/integration.rb +3 -5
  138. data/lib/active_record/internal_metadata.rb +16 -7
  139. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  140. data/lib/active_record/locking/optimistic.rb +33 -18
  141. data/lib/active_record/locking/pessimistic.rb +6 -2
  142. data/lib/active_record/log_subscriber.rb +28 -9
  143. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  144. data/lib/active_record/middleware/database_selector/resolver.rb +14 -14
  145. data/lib/active_record/middleware/database_selector.rb +4 -2
  146. data/lib/active_record/migration/command_recorder.rb +53 -45
  147. data/lib/active_record/migration/compatibility.rb +71 -20
  148. data/lib/active_record/migration/join_table.rb +0 -1
  149. data/lib/active_record/migration.rb +115 -85
  150. data/lib/active_record/model_schema.rb +120 -15
  151. data/lib/active_record/nested_attributes.rb +2 -5
  152. data/lib/active_record/no_touching.rb +1 -1
  153. data/lib/active_record/null_relation.rb +0 -1
  154. data/lib/active_record/persistence.rb +50 -46
  155. data/lib/active_record/query_cache.rb +15 -5
  156. data/lib/active_record/querying.rb +12 -7
  157. data/lib/active_record/railtie.rb +65 -45
  158. data/lib/active_record/railties/console_sandbox.rb +2 -4
  159. data/lib/active_record/railties/databases.rake +280 -99
  160. data/lib/active_record/readonly_attributes.rb +4 -0
  161. data/lib/active_record/reflection.rb +77 -63
  162. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  163. data/lib/active_record/relation/batches.rb +38 -32
  164. data/lib/active_record/relation/calculations.rb +106 -45
  165. data/lib/active_record/relation/delegation.rb +9 -7
  166. data/lib/active_record/relation/finder_methods.rb +55 -17
  167. data/lib/active_record/relation/from_clause.rb +5 -1
  168. data/lib/active_record/relation/merger.rb +27 -26
  169. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  170. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  171. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
  172. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  173. data/lib/active_record/relation/predicate_builder.rb +59 -40
  174. data/lib/active_record/relation/query_methods.rb +344 -181
  175. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  176. data/lib/active_record/relation/spawn_methods.rb +8 -8
  177. data/lib/active_record/relation/where_clause.rb +111 -62
  178. data/lib/active_record/relation.rb +116 -82
  179. data/lib/active_record/result.rb +41 -34
  180. data/lib/active_record/runtime_registry.rb +2 -2
  181. data/lib/active_record/sanitization.rb +6 -17
  182. data/lib/active_record/schema_dumper.rb +34 -4
  183. data/lib/active_record/schema_migration.rb +2 -8
  184. data/lib/active_record/scoping/default.rb +1 -4
  185. data/lib/active_record/scoping/named.rb +7 -18
  186. data/lib/active_record/scoping.rb +0 -1
  187. data/lib/active_record/secure_token.rb +16 -8
  188. data/lib/active_record/serialization.rb +5 -3
  189. data/lib/active_record/signed_id.rb +116 -0
  190. data/lib/active_record/statement_cache.rb +20 -4
  191. data/lib/active_record/store.rb +3 -3
  192. data/lib/active_record/suppressor.rb +2 -2
  193. data/lib/active_record/table_metadata.rb +42 -36
  194. data/lib/active_record/tasks/database_tasks.rb +140 -113
  195. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
  196. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
  197. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
  198. data/lib/active_record/test_databases.rb +5 -4
  199. data/lib/active_record/test_fixtures.rb +79 -16
  200. data/lib/active_record/timestamp.rb +4 -7
  201. data/lib/active_record/touch_later.rb +20 -21
  202. data/lib/active_record/transactions.rb +26 -73
  203. data/lib/active_record/type/adapter_specific_registry.rb +2 -5
  204. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  205. data/lib/active_record/type/serialized.rb +6 -3
  206. data/lib/active_record/type/time.rb +10 -0
  207. data/lib/active_record/type/type_map.rb +0 -1
  208. data/lib/active_record/type/unsigned_integer.rb +0 -1
  209. data/lib/active_record/type.rb +8 -2
  210. data/lib/active_record/type_caster/connection.rb +0 -1
  211. data/lib/active_record/type_caster/map.rb +8 -5
  212. data/lib/active_record/validations/associated.rb +1 -2
  213. data/lib/active_record/validations/numericality.rb +35 -0
  214. data/lib/active_record/validations/uniqueness.rb +24 -4
  215. data/lib/active_record/validations.rb +3 -3
  216. data/lib/active_record.rb +7 -13
  217. data/lib/arel/attributes/attribute.rb +4 -0
  218. data/lib/arel/collectors/bind.rb +5 -0
  219. data/lib/arel/collectors/composite.rb +8 -0
  220. data/lib/arel/collectors/sql_string.rb +7 -0
  221. data/lib/arel/collectors/substitute_binds.rb +7 -0
  222. data/lib/arel/nodes/binary.rb +82 -8
  223. data/lib/arel/nodes/bind_param.rb +8 -0
  224. data/lib/arel/nodes/casted.rb +21 -9
  225. data/lib/arel/nodes/equality.rb +6 -9
  226. data/lib/arel/nodes/grouping.rb +3 -0
  227. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  228. data/lib/arel/nodes/in.rb +8 -1
  229. data/lib/arel/nodes/infix_operation.rb +13 -1
  230. data/lib/arel/nodes/join_source.rb +1 -1
  231. data/lib/arel/nodes/node.rb +7 -6
  232. data/lib/arel/nodes/ordering.rb +27 -0
  233. data/lib/arel/nodes/sql_literal.rb +3 -0
  234. data/lib/arel/nodes/table_alias.rb +7 -3
  235. data/lib/arel/nodes/unary.rb +0 -1
  236. data/lib/arel/nodes.rb +3 -1
  237. data/lib/arel/predications.rb +17 -24
  238. data/lib/arel/select_manager.rb +1 -2
  239. data/lib/arel/table.rb +13 -5
  240. data/lib/arel/visitors/dot.rb +14 -3
  241. data/lib/arel/visitors/mysql.rb +11 -1
  242. data/lib/arel/visitors/postgresql.rb +15 -5
  243. data/lib/arel/visitors/sqlite.rb +0 -1
  244. data/lib/arel/visitors/to_sql.rb +89 -79
  245. data/lib/arel/visitors/visitor.rb +0 -1
  246. data/lib/arel/visitors.rb +0 -7
  247. data/lib/arel.rb +15 -12
  248. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  249. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  250. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  251. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  252. data/lib/rails/generators/active_record/migration.rb +6 -2
  253. data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
  254. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  255. metadata +27 -24
  256. data/lib/active_record/attribute_decorators.rb +0 -90
  257. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  258. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  259. data/lib/active_record/define_callbacks.rb +0 -22
  260. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  261. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  262. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  263. data/lib/arel/attributes.rb +0 -22
  264. data/lib/arel/visitors/depth_first.rb +0 -204
  265. data/lib/arel/visitors/ibm_db.rb +0 -34
  266. data/lib/arel/visitors/informix.rb +0 -62
  267. data/lib/arel/visitors/mssql.rb +0 -157
  268. data/lib/arel/visitors/oracle.rb +0 -159
  269. data/lib/arel/visitors/oracle12.rb +0 -66
  270. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/enumerable"
3
4
  require "active_support/core_ext/hash/indifferent_access"
4
5
  require "active_support/core_ext/string/filters"
5
6
  require "active_support/parameter_filter"
@@ -25,6 +26,18 @@ module ActiveRecord
25
26
  # their relevant queries. Defaults to false.
26
27
  mattr_accessor :verbose_query_logs, instance_writer: false, default: false
27
28
 
29
+ ##
30
+ # :singleton-method:
31
+ #
32
+ # Specifies the names of the queues used by background jobs.
33
+ mattr_accessor :queues, instance_accessor: false, default: {}
34
+
35
+ ##
36
+ # :singleton-method:
37
+ #
38
+ # Specifies the job used to destroy associations in the background
39
+ class_attribute :destroy_association_async_job, instance_writer: false, instance_predicate: false, default: false
40
+
28
41
  ##
29
42
  # Contains the database configuration - as is typically stored in config/database.yml -
30
43
  # as an ActiveRecord::DatabaseConfigurations object.
@@ -43,9 +56,9 @@ module ActiveRecord
43
56
  #
44
57
  # #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
45
58
  # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
46
- # @spec_name="primary", @config={"adapter"=>"sqlite3", "database"=>"db/development.sqlite3"}>,
59
+ # @name="primary", @config={adapter: "sqlite3", database: "db/development.sqlite3"}>,
47
60
  # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
48
- # @spec_name="primary", @config={"adapter"=>"mysql2", "database"=>"db/production.sqlite3"}>
61
+ # @name="primary", @config={adapter: "sqlite3", database: "db/production.sqlite3"}>
49
62
  # ]>
50
63
  def self.configurations=(config)
51
64
  @@configurations = ActiveRecord::DatabaseConfigurations.new(config)
@@ -80,14 +93,6 @@ module ActiveRecord
80
93
  # scope being ignored is error-worthy, rather than a warning.
81
94
  mattr_accessor :error_on_ignored_order, instance_writer: false, default: false
82
95
 
83
- # :singleton-method:
84
- # Specify the behavior for unsafe raw query methods. Values are as follows
85
- # deprecated - Warnings are logged when unsafe raw SQL is passed to
86
- # query methods.
87
- # disabled - Unsafe raw SQL passed to query methods results in
88
- # UnknownAttributeReference exception.
89
- mattr_accessor :allow_unsafe_raw_sql, instance_writer: false, default: :deprecated
90
-
91
96
  ##
92
97
  # :singleton-method:
93
98
  # Specify whether or not to use timestamps for migration versions
@@ -103,7 +108,7 @@ module ActiveRecord
103
108
 
104
109
  ##
105
110
  # :singleton-method:
106
- # Specifies which database schemas to dump when calling db:structure:dump.
111
+ # Specifies which database schemas to dump when calling db:schema:dump.
107
112
  # If the value is :schema_search_path (the default), any schemas listed in
108
113
  # schema_search_path are dumped. Use :all to dump all schemas regardless
109
114
  # of schema_search_path, or a string of comma separated schemas for a
@@ -118,29 +123,182 @@ module ActiveRecord
118
123
  # potentially cause memory bloat.
119
124
  mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false
120
125
 
126
+ ##
127
+ # :singleton-method:
128
+ # Show a warning when Rails couldn't parse your database.yml
129
+ # for multiple databases.
130
+ mattr_accessor :suppress_multiple_database_warning, instance_writer: false, default: false
131
+
121
132
  mattr_accessor :maintain_test_schema, instance_accessor: false
122
133
 
123
- mattr_accessor :belongs_to_required_by_default, instance_accessor: false
134
+ class_attribute :belongs_to_required_by_default, instance_accessor: false
135
+
136
+ ##
137
+ # :singleton-method:
138
+ # Set the application to log or raise when an association violates strict loading.
139
+ # Defaults to :raise.
140
+ mattr_accessor :action_on_strict_loading_violation, instance_accessor: false, default: :raise
124
141
 
125
- mattr_accessor :connection_handlers, instance_accessor: false, default: {}
142
+ class_attribute :strict_loading_by_default, instance_accessor: false, default: false
126
143
 
127
144
  mattr_accessor :writing_role, instance_accessor: false, default: :writing
128
145
 
129
146
  mattr_accessor :reading_role, instance_accessor: false, default: :reading
130
147
 
148
+ mattr_accessor :has_many_inversing, instance_accessor: false, default: false
149
+
131
150
  class_attribute :default_connection_handler, instance_writer: false
132
151
 
152
+ class_attribute :default_role, instance_writer: false
153
+
154
+ class_attribute :default_shard, instance_writer: false
155
+
156
+ mattr_accessor :legacy_connection_handling, instance_writer: false, default: true
157
+
133
158
  self.filter_attributes = []
134
159
 
135
160
  def self.connection_handler
136
- Thread.current.thread_variable_get("ar_connection_handler") || default_connection_handler
161
+ Thread.current.thread_variable_get(:ar_connection_handler) || default_connection_handler
137
162
  end
138
163
 
139
164
  def self.connection_handler=(handler)
140
- Thread.current.thread_variable_set("ar_connection_handler", handler)
165
+ Thread.current.thread_variable_set(:ar_connection_handler, handler)
166
+ end
167
+
168
+ def self.connection_handlers
169
+ unless legacy_connection_handling
170
+ raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
171
+ end
172
+
173
+ @@connection_handlers ||= {}
174
+ end
175
+
176
+ def self.connection_handlers=(handlers)
177
+ unless legacy_connection_handling
178
+ raise NotImplementedError, "The new connection handling does not setting support multiple connection handlers."
179
+ end
180
+
181
+ @@connection_handlers = handlers
182
+ end
183
+
184
+ # Returns the symbol representing the current connected role.
185
+ #
186
+ # ActiveRecord::Base.connected_to(role: :writing) do
187
+ # ActiveRecord::Base.current_role #=> :writing
188
+ # end
189
+ #
190
+ # ActiveRecord::Base.connected_to(role: :reading) do
191
+ # ActiveRecord::Base.current_role #=> :reading
192
+ # end
193
+ def self.current_role
194
+ if ActiveRecord::Base.legacy_connection_handling
195
+ connection_handlers.key(connection_handler) || default_role
196
+ else
197
+ connected_to_stack.reverse_each do |hash|
198
+ return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
199
+ return hash[:role] if hash[:role] && hash[:klasses].include?(connection_classes)
200
+ end
201
+
202
+ default_role
203
+ end
204
+ end
205
+
206
+ # Returns the symbol representing the current connected shard.
207
+ #
208
+ # ActiveRecord::Base.connected_to(role: :reading) do
209
+ # ActiveRecord::Base.current_shard #=> :default
210
+ # end
211
+ #
212
+ # ActiveRecord::Base.connected_to(role: :writing, shard: :one) do
213
+ # ActiveRecord::Base.current_shard #=> :one
214
+ # end
215
+ def self.current_shard
216
+ connected_to_stack.reverse_each do |hash|
217
+ return hash[:shard] if hash[:shard] && hash[:klasses].include?(Base)
218
+ return hash[:shard] if hash[:shard] && hash[:klasses].include?(connection_classes)
219
+ end
220
+
221
+ default_shard
222
+ end
223
+
224
+ # Returns the symbol representing the current setting for
225
+ # preventing writes.
226
+ #
227
+ # ActiveRecord::Base.connected_to(role: :reading) do
228
+ # ActiveRecord::Base.current_preventing_writes #=> true
229
+ # end
230
+ #
231
+ # ActiveRecord::Base.connected_to(role: :writing) do
232
+ # ActiveRecord::Base.current_preventing_writes #=> false
233
+ # end
234
+ def self.current_preventing_writes
235
+ if legacy_connection_handling
236
+ connection_handler.prevent_writes
237
+ else
238
+ connected_to_stack.reverse_each do |hash|
239
+ return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
240
+ return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_classes)
241
+ end
242
+
243
+ false
244
+ end
245
+ end
246
+
247
+ def self.connected_to_stack # :nodoc:
248
+ if connected_to_stack = Thread.current.thread_variable_get(:ar_connected_to_stack)
249
+ connected_to_stack
250
+ else
251
+ connected_to_stack = Concurrent::Array.new
252
+ Thread.current.thread_variable_set(:ar_connected_to_stack, connected_to_stack)
253
+ connected_to_stack
254
+ end
255
+ end
256
+
257
+ def self.connection_class=(b) # :nodoc:
258
+ @connection_class = b
259
+ end
260
+
261
+ def self.connection_class # :nodoc
262
+ @connection_class ||= false
263
+ end
264
+
265
+ def self.connection_class? # :nodoc:
266
+ self.connection_class
267
+ end
268
+
269
+ def self.connection_classes # :nodoc:
270
+ klass = self
271
+
272
+ until klass == Base
273
+ break if klass.connection_class?
274
+ klass = klass.superclass
275
+ end
276
+
277
+ klass
278
+ end
279
+
280
+ def self.allow_unsafe_raw_sql # :nodoc:
281
+ ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql is deprecated and will be removed in Rails 6.2")
282
+ end
283
+
284
+ def self.allow_unsafe_raw_sql=(value) # :nodoc:
285
+ ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql= is deprecated and will be removed in Rails 6.2")
141
286
  end
142
287
 
143
288
  self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
289
+ self.default_role = writing_role
290
+ self.default_shard = :default
291
+
292
+ def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
293
+ case action_on_strict_loading_violation
294
+ when :raise
295
+ message = "`#{owner}` is marked for strict_loading. The `#{reflection.klass}` association named `:#{reflection.name}` cannot be lazily loaded."
296
+ raise ActiveRecord::StrictLoadingViolationError.new(message)
297
+ when :log
298
+ name = "strict_loading_violation.active_record"
299
+ ActiveSupport::Notifications.instrument(name, owner: owner, reflection: reflection)
300
+ end
301
+ end
144
302
  end
145
303
 
146
304
  module ClassMethods
@@ -151,16 +309,20 @@ module ActiveRecord
151
309
  def inherited(child_class) # :nodoc:
152
310
  # initialize cache at class definition for thread safety
153
311
  child_class.initialize_find_by_cache
312
+ unless child_class.base_class?
313
+ klass = self
314
+ until klass.base_class?
315
+ klass.initialize_find_by_cache
316
+ klass = klass.superclass
317
+ end
318
+ end
154
319
  super
155
320
  end
156
321
 
157
322
  def find(*ids) # :nodoc:
158
323
  # We don't have cache keys for this stuff yet
159
324
  return super unless ids.length == 1
160
- return super if block_given? ||
161
- primary_key.nil? ||
162
- scope_attributes? ||
163
- columns_hash.key?(inheritance_column) && !base_class?
325
+ return super if block_given? || primary_key.nil? || scope_attributes?
164
326
 
165
327
  id = ids.first
166
328
 
@@ -172,36 +334,47 @@ module ActiveRecord
172
334
  where(key => params.bind).limit(1)
173
335
  }
174
336
 
175
- record = statement.execute([id], connection)&.first
176
- unless record
177
- raise RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id)
178
- end
179
- record
337
+ statement.execute([id], connection).first ||
338
+ raise(RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id))
180
339
  end
181
340
 
182
341
  def find_by(*args) # :nodoc:
183
- return super if scope_attributes? || reflect_on_all_aggregations.any? ||
184
- columns_hash.key?(inheritance_column) && !base_class?
342
+ return super if scope_attributes?
185
343
 
186
344
  hash = args.first
345
+ return super unless Hash === hash
187
346
 
188
- return super if !(Hash === hash) || hash.values.any? { |v|
189
- StatementCache.unsupported_value?(v)
190
- }
347
+ hash = hash.each_with_object({}) do |(key, value), h|
348
+ key = key.to_s
349
+ key = attribute_aliases[key] || key
191
350
 
192
- # We can't cache Post.find_by(author: david) ...yet
193
- return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
351
+ return super if reflect_on_aggregation(key)
194
352
 
195
- keys = hash.keys
353
+ reflection = _reflect_on_association(key)
354
+
355
+ if !reflection
356
+ value = value.id if value.respond_to?(:id)
357
+ elsif reflection.belongs_to? && !reflection.polymorphic?
358
+ key = reflection.join_foreign_key
359
+ pkey = reflection.join_primary_key
360
+ value = value.public_send(pkey) if value.respond_to?(pkey)
361
+ end
362
+
363
+ if !columns_hash.key?(key) || StatementCache.unsupported_value?(value)
364
+ return super
365
+ end
366
+
367
+ h[key] = value
368
+ end
196
369
 
370
+ keys = hash.keys
197
371
  statement = cached_find_by_statement(keys) { |params|
198
- wheres = keys.each_with_object({}) { |param, o|
199
- o[param] = params.bind
200
- }
372
+ wheres = keys.index_with { params.bind }
201
373
  where(wheres).limit(1)
202
374
  }
375
+
203
376
  begin
204
- statement.execute(hash.values, connection)&.first
377
+ statement.execute(hash.values, connection).first
205
378
  rescue TypeError
206
379
  raise ActiveRecord::StatementInvalid
207
380
  end
@@ -235,7 +408,21 @@ module ActiveRecord
235
408
  end
236
409
 
237
410
  # Specifies columns which shouldn't be exposed while calling +#inspect+.
238
- attr_writer :filter_attributes
411
+ def filter_attributes=(filter_attributes)
412
+ @inspection_filter = nil
413
+ @filter_attributes = filter_attributes
414
+ end
415
+
416
+ def inspection_filter # :nodoc:
417
+ if defined?(@filter_attributes)
418
+ @inspection_filter ||= begin
419
+ mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
420
+ ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
421
+ end
422
+ else
423
+ superclass.inspection_filter
424
+ end
425
+ end
239
426
 
240
427
  # Returns a string like 'Post(id:integer, title:string, body:text)'
241
428
  def inspect # :nodoc:
@@ -264,14 +451,13 @@ module ActiveRecord
264
451
  # scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
265
452
  # end
266
453
  def arel_table # :nodoc:
267
- @arel_table ||= Arel::Table.new(table_name, type_caster: type_caster)
454
+ @arel_table ||= Arel::Table.new(table_name, klass: self)
268
455
  end
269
456
 
270
457
  def arel_attribute(name, table = arel_table) # :nodoc:
271
- name = name.to_s
272
- name = attribute_aliases[name] || name
273
458
  table[name]
274
459
  end
460
+ deprecate :arel_attribute
275
461
 
276
462
  def predicate_builder # :nodoc:
277
463
  @predicate_builder ||= PredicateBuilder.new(table_metadata)
@@ -285,19 +471,17 @@ module ActiveRecord
285
471
  false
286
472
  end
287
473
 
288
- private
289
-
290
- def cached_find_by_statement(key, &block)
291
- cache = @find_by_statement_cache[connection.prepared_statements]
292
- cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
293
- end
474
+ def cached_find_by_statement(key, &block) # :nodoc:
475
+ cache = @find_by_statement_cache[connection.prepared_statements]
476
+ cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
477
+ end
294
478
 
479
+ private
295
480
  def relation
296
481
  relation = Relation.create(self)
297
482
 
298
483
  if finder_needs_type_condition? && !ignore_default_scope?
299
484
  relation.where!(type_condition)
300
- relation.create_with!(inheritance_column.to_s => sti_name)
301
485
  else
302
486
  relation
303
487
  end
@@ -401,9 +585,9 @@ module ActiveRecord
401
585
  _run_initialize_callbacks
402
586
 
403
587
  @new_record = true
588
+ @previously_new_record = false
404
589
  @destroyed = false
405
590
  @_start_transaction_state = nil
406
- @transaction_state = nil
407
591
 
408
592
  super
409
593
  end
@@ -463,7 +647,6 @@ module ActiveRecord
463
647
 
464
648
  # Returns +true+ if the attributes hash has been frozen.
465
649
  def frozen?
466
- sync_with_transaction_state if @transaction_state&.finalized?
467
650
  @attributes.frozen?
468
651
  end
469
652
 
@@ -484,12 +667,27 @@ module ActiveRecord
484
667
  false
485
668
  end
486
669
 
487
- # Returns +true+ if the record is read only. Records loaded through joins with piggy-back
488
- # attributes will be marked as read only since they cannot be saved.
670
+ # Returns +true+ if the record is read only.
489
671
  def readonly?
490
672
  @readonly
491
673
  end
492
674
 
675
+ # Returns +true+ if the record is in strict_loading mode.
676
+ def strict_loading?
677
+ @strict_loading
678
+ end
679
+
680
+ # Sets the record to strict_loading mode. This will raise an error
681
+ # if the record tries to lazily load an association.
682
+ #
683
+ # user = User.first
684
+ # user.strict_loading!
685
+ # user.comments.to_a
686
+ # => ActiveRecord::StrictLoadingViolationError
687
+ def strict_loading!
688
+ @strict_loading = true
689
+ end
690
+
493
691
  # Marks this record as read only.
494
692
  def readonly!
495
693
  @readonly = true
@@ -505,15 +703,8 @@ module ActiveRecord
505
703
  # allocated but not initialized.
506
704
  inspection = if defined?(@attributes) && @attributes
507
705
  self.class.attribute_names.collect do |name|
508
- if has_attribute?(name)
509
- attr = _read_attribute(name)
510
- value = if attr.nil?
511
- attr.inspect
512
- else
513
- attr = format_for_inspect(attr)
514
- inspection_filter.filter_param(name, attr)
515
- end
516
- "#{name}: #{value}"
706
+ if _has_attribute?(name)
707
+ "#{name}: #{attribute_for_inspect(name)}"
517
708
  end
518
709
  end.compact.join(", ")
519
710
  else
@@ -529,7 +720,7 @@ module ActiveRecord
529
720
  return super if custom_inspect_method_defined?
530
721
  pp.object_address_group(self) do
531
722
  if defined?(@attributes) && @attributes
532
- attr_names = self.class.attribute_names.select { |name| has_attribute?(name) }
723
+ attr_names = self.class.attribute_names.select { |name| _has_attribute?(name) }
533
724
  pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
534
725
  pp.breakable " "
535
726
  pp.group(1) do
@@ -550,11 +741,15 @@ module ActiveRecord
550
741
 
551
742
  # Returns a hash of the given methods with their names as keys and returned values as values.
552
743
  def slice(*methods)
553
- Hash[methods.flatten.map! { |method| [method, public_send(method)] }].with_indifferent_access
744
+ methods.flatten.index_with { |method| public_send(method) }.with_indifferent_access
554
745
  end
555
746
 
556
- private
747
+ # Returns an array of the values returned by the given methods.
748
+ def values_at(*methods)
749
+ methods.flatten.map! { |method| public_send(method) }
750
+ end
557
751
 
752
+ private
558
753
  # +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
559
754
  # the array, and then rescues from the possible +NoMethodError+. If those elements are
560
755
  # +ActiveRecord::Base+'s, then this triggers the various +method_missing+'s that we have,
@@ -570,11 +765,12 @@ module ActiveRecord
570
765
  def init_internals
571
766
  @primary_key = self.class.primary_key
572
767
  @readonly = false
768
+ @previously_new_record = false
573
769
  @destroyed = false
574
770
  @marked_for_destruction = false
575
771
  @destroyed_by_association = nil
576
772
  @_start_transaction_state = nil
577
- @transaction_state = nil
773
+ @strict_loading = self.class.strict_loading_by_default
578
774
 
579
775
  self.class.define_attribute_methods
580
776
  end
@@ -586,14 +782,15 @@ module ActiveRecord
586
782
  self.class.instance_method(:inspect).owner != ActiveRecord::Base.instance_method(:inspect).owner
587
783
  end
588
784
 
589
- def inspection_filter
590
- @inspection_filter ||= begin
591
- mask = DelegateClass(::String).new(ActiveSupport::ParameterFilter::FILTERED)
592
- def mask.pretty_print(pp)
593
- pp.text __getobj__
594
- end
595
- ActiveSupport::ParameterFilter.new(self.class.filter_attributes, mask: mask)
785
+ class InspectionMask < DelegateClass(::String)
786
+ def pretty_print(pp)
787
+ pp.text __getobj__
596
788
  end
597
789
  end
790
+ private_constant :InspectionMask
791
+
792
+ def inspection_filter
793
+ self.class.inspection_filter
794
+ end
598
795
  end
599
796
  end
@@ -51,7 +51,10 @@ module ActiveRecord
51
51
 
52
52
  if touch
53
53
  names = touch if touch != true
54
- updates.merge!(touch_attributes_with_time(*names))
54
+ names = Array.wrap(names)
55
+ options = names.extract_options!
56
+ touch_updates = touch_attributes_with_time(*names, **options)
57
+ updates.merge!(touch_updates)
55
58
  end
56
59
 
57
60
  unscoped.where(primary_key => object.id).update_all(updates)
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/enumerable"
4
+
5
+ module ActiveRecord
6
+ class DatabaseConfigurations
7
+ # Expands a connection string into a hash.
8
+ class ConnectionUrlResolver # :nodoc:
9
+ # == Example
10
+ #
11
+ # url = "postgresql://foo:bar@localhost:9000/foo_test?pool=5&timeout=3000"
12
+ # ConnectionUrlResolver.new(url).to_hash
13
+ # # => {
14
+ # adapter: "postgresql",
15
+ # host: "localhost",
16
+ # port: 9000,
17
+ # database: "foo_test",
18
+ # username: "foo",
19
+ # password: "bar",
20
+ # pool: "5",
21
+ # timeout: "3000"
22
+ # }
23
+ def initialize(url)
24
+ raise "Database URL cannot be empty" if url.blank?
25
+ @uri = uri_parser.parse(url)
26
+ @adapter = @uri.scheme && @uri.scheme.tr("-", "_")
27
+ @adapter = "postgresql" if @adapter == "postgres"
28
+
29
+ if @uri.opaque
30
+ @uri.opaque, @query = @uri.opaque.split("?", 2)
31
+ else
32
+ @query = @uri.query
33
+ end
34
+ end
35
+
36
+ # Converts the given URL to a full connection hash.
37
+ def to_hash
38
+ config = raw_config.compact_blank
39
+ config.map { |key, value| config[key] = uri_parser.unescape(value) if value.is_a? String }
40
+ config
41
+ end
42
+
43
+ private
44
+ attr_reader :uri
45
+
46
+ def uri_parser
47
+ @uri_parser ||= URI::Parser.new
48
+ end
49
+
50
+ # Converts the query parameters of the URI into a hash.
51
+ #
52
+ # "localhost?pool=5&reaping_frequency=2"
53
+ # # => { pool: "5", reaping_frequency: "2" }
54
+ #
55
+ # returns empty hash if no query present.
56
+ #
57
+ # "localhost"
58
+ # # => {}
59
+ def query_hash
60
+ Hash[(@query || "").split("&").map { |pair| pair.split("=", 2) }].symbolize_keys
61
+ end
62
+
63
+ def raw_config
64
+ if uri.opaque
65
+ query_hash.merge(
66
+ adapter: @adapter,
67
+ database: uri.opaque
68
+ )
69
+ else
70
+ query_hash.merge(
71
+ adapter: @adapter,
72
+ username: uri.user,
73
+ password: uri.password,
74
+ port: uri.port,
75
+ database: database_from_path,
76
+ host: uri.hostname
77
+ )
78
+ end
79
+ end
80
+
81
+ # Returns name of the database.
82
+ def database_from_path
83
+ if @adapter == "sqlite3"
84
+ # 'sqlite3:/foo' is absolute, because that makes sense. The
85
+ # corresponding relative version, 'sqlite3:foo', is handled
86
+ # elsewhere, as an "opaque".
87
+
88
+ uri.path
89
+ else
90
+ # Only SQLite uses a filename as the "database" name; for
91
+ # anything else, a leading slash would be silly.
92
+
93
+ uri.path.delete_prefix("/")
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end