activerecord 5.2.8.1 → 6.1.6.1

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 (316) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1255 -596
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +7 -5
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +9 -8
  7. data/lib/active_record/association_relation.rb +30 -10
  8. data/lib/active_record/associations/alias_tracker.rb +19 -16
  9. data/lib/active_record/associations/association.rb +100 -41
  10. data/lib/active_record/associations/association_scope.rb +23 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +55 -48
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
  13. data/lib/active_record/associations/builder/association.rb +45 -22
  14. data/lib/active_record/associations/builder/belongs_to.rb +29 -59
  15. data/lib/active_record/associations/builder/collection_association.rb +8 -17
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -2
  18. data/lib/active_record/associations/builder/has_one.rb +33 -2
  19. data/lib/active_record/associations/builder/singular_association.rb +3 -1
  20. data/lib/active_record/associations/collection_association.rb +44 -34
  21. data/lib/active_record/associations/collection_proxy.rb +25 -21
  22. data/lib/active_record/associations/foreign_association.rb +20 -0
  23. data/lib/active_record/associations/has_many_association.rb +26 -13
  24. data/lib/active_record/associations/has_many_through_association.rb +24 -18
  25. data/lib/active_record/associations/has_one_association.rb +43 -31
  26. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  27. data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
  28. data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
  29. data/lib/active_record/associations/join_dependency.rb +91 -60
  30. data/lib/active_record/associations/preloader/association.rb +69 -43
  31. data/lib/active_record/associations/preloader/through_association.rb +49 -40
  32. data/lib/active_record/associations/preloader.rb +47 -34
  33. data/lib/active_record/associations/singular_association.rb +3 -17
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/associations.rb +137 -25
  36. data/lib/active_record/attribute_assignment.rb +17 -19
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
  38. data/lib/active_record/attribute_methods/dirty.rb +101 -40
  39. data/lib/active_record/attribute_methods/primary_key.rb +20 -25
  40. data/lib/active_record/attribute_methods/query.rb +4 -8
  41. data/lib/active_record/attribute_methods/read.rb +14 -56
  42. data/lib/active_record/attribute_methods/serialization.rb +12 -7
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  44. data/lib/active_record/attribute_methods/write.rb +18 -34
  45. data/lib/active_record/attribute_methods.rb +81 -143
  46. data/lib/active_record/attributes.rb +46 -9
  47. data/lib/active_record/autosave_association.rb +57 -42
  48. data/lib/active_record/base.rb +4 -17
  49. data/lib/active_record/callbacks.rb +158 -43
  50. data/lib/active_record/coders/yaml_column.rb +1 -2
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +211 -90
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +167 -69
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -99
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
  64. data/lib/active_record/connection_adapters/column.rb +30 -12
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  67. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  68. data/lib/active_record/connection_adapters/mysql/database_statements.rb +88 -32
  69. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  70. data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
  71. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
  72. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
  73. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
  74. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +142 -19
  75. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
  77. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  78. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  79. data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
  80. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -54
  81. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
  93. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  94. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  96. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
  97. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
  99. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  100. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
  101. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  102. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  103. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
  104. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
  105. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  106. data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
  107. data/lib/active_record/connection_adapters/schema_cache.rb +159 -21
  108. data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
  109. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  110. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  111. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  112. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
  113. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
  114. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  115. data/lib/active_record/connection_adapters.rb +52 -0
  116. data/lib/active_record/connection_handling.rb +293 -33
  117. data/lib/active_record/core.rb +333 -98
  118. data/lib/active_record/counter_cache.rb +8 -30
  119. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  120. data/lib/active_record/database_configurations/database_config.rb +80 -0
  121. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  122. data/lib/active_record/database_configurations/url_config.rb +53 -0
  123. data/lib/active_record/database_configurations.rb +273 -0
  124. data/lib/active_record/delegated_type.rb +209 -0
  125. data/lib/active_record/destroy_association_async_job.rb +36 -0
  126. data/lib/active_record/dynamic_matchers.rb +3 -4
  127. data/lib/active_record/enum.rb +108 -36
  128. data/lib/active_record/errors.rb +62 -19
  129. data/lib/active_record/explain.rb +10 -6
  130. data/lib/active_record/explain_subscriber.rb +1 -1
  131. data/lib/active_record/fixture_set/file.rb +10 -17
  132. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  133. data/lib/active_record/fixture_set/render_context.rb +17 -0
  134. data/lib/active_record/fixture_set/table_row.rb +152 -0
  135. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  136. data/lib/active_record/fixtures.rb +200 -481
  137. data/lib/active_record/gem_version.rb +3 -3
  138. data/lib/active_record/inheritance.rb +53 -24
  139. data/lib/active_record/insert_all.rb +212 -0
  140. data/lib/active_record/integration.rb +67 -17
  141. data/lib/active_record/internal_metadata.rb +28 -9
  142. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  143. data/lib/active_record/locking/optimistic.rb +37 -23
  144. data/lib/active_record/locking/pessimistic.rb +9 -5
  145. data/lib/active_record/log_subscriber.rb +35 -35
  146. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  147. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  148. data/lib/active_record/middleware/database_selector.rb +77 -0
  149. data/lib/active_record/migration/command_recorder.rb +96 -44
  150. data/lib/active_record/migration/compatibility.rb +145 -64
  151. data/lib/active_record/migration/join_table.rb +0 -1
  152. data/lib/active_record/migration.rb +206 -157
  153. data/lib/active_record/model_schema.rb +148 -22
  154. data/lib/active_record/nested_attributes.rb +4 -7
  155. data/lib/active_record/no_touching.rb +8 -1
  156. data/lib/active_record/null_relation.rb +0 -1
  157. data/lib/active_record/persistence.rb +267 -59
  158. data/lib/active_record/query_cache.rb +21 -4
  159. data/lib/active_record/querying.rb +40 -23
  160. data/lib/active_record/railtie.rb +116 -59
  161. data/lib/active_record/railties/console_sandbox.rb +2 -4
  162. data/lib/active_record/railties/controller_runtime.rb +30 -35
  163. data/lib/active_record/railties/databases.rake +411 -80
  164. data/lib/active_record/readonly_attributes.rb +4 -0
  165. data/lib/active_record/reflection.rb +109 -93
  166. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  167. data/lib/active_record/relation/batches.rb +44 -35
  168. data/lib/active_record/relation/calculations.rb +157 -90
  169. data/lib/active_record/relation/delegation.rb +35 -50
  170. data/lib/active_record/relation/finder_methods.rb +64 -39
  171. data/lib/active_record/relation/from_clause.rb +5 -1
  172. data/lib/active_record/relation/merger.rb +32 -40
  173. data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
  174. data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  179. data/lib/active_record/relation/predicate_builder.rb +62 -45
  180. data/lib/active_record/relation/query_attribute.rb +13 -8
  181. data/lib/active_record/relation/query_methods.rb +476 -187
  182. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  183. data/lib/active_record/relation/spawn_methods.rb +9 -9
  184. data/lib/active_record/relation/where_clause.rb +115 -62
  185. data/lib/active_record/relation.rb +379 -115
  186. data/lib/active_record/result.rb +64 -38
  187. data/lib/active_record/runtime_registry.rb +2 -2
  188. data/lib/active_record/sanitization.rb +22 -41
  189. data/lib/active_record/schema.rb +2 -11
  190. data/lib/active_record/schema_dumper.rb +54 -9
  191. data/lib/active_record/schema_migration.rb +7 -9
  192. data/lib/active_record/scoping/default.rb +4 -8
  193. data/lib/active_record/scoping/named.rb +17 -24
  194. data/lib/active_record/scoping.rb +8 -9
  195. data/lib/active_record/secure_token.rb +16 -8
  196. data/lib/active_record/serialization.rb +5 -3
  197. data/lib/active_record/signed_id.rb +116 -0
  198. data/lib/active_record/statement_cache.rb +49 -6
  199. data/lib/active_record/store.rb +88 -9
  200. data/lib/active_record/suppressor.rb +2 -2
  201. data/lib/active_record/table_metadata.rb +42 -43
  202. data/lib/active_record/tasks/database_tasks.rb +277 -81
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
  206. data/lib/active_record/test_databases.rb +24 -0
  207. data/lib/active_record/test_fixtures.rb +287 -0
  208. data/lib/active_record/timestamp.rb +43 -32
  209. data/lib/active_record/touch_later.rb +23 -22
  210. data/lib/active_record/transactions.rb +62 -118
  211. data/lib/active_record/translation.rb +1 -1
  212. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  213. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  214. data/lib/active_record/type/serialized.rb +6 -3
  215. data/lib/active_record/type/time.rb +10 -0
  216. data/lib/active_record/type/type_map.rb +0 -1
  217. data/lib/active_record/type/unsigned_integer.rb +0 -1
  218. data/lib/active_record/type.rb +10 -5
  219. data/lib/active_record/type_caster/connection.rb +15 -15
  220. data/lib/active_record/type_caster/map.rb +8 -8
  221. data/lib/active_record/validations/associated.rb +1 -2
  222. data/lib/active_record/validations/numericality.rb +35 -0
  223. data/lib/active_record/validations/uniqueness.rb +38 -30
  224. data/lib/active_record/validations.rb +4 -3
  225. data/lib/active_record.rb +13 -12
  226. data/lib/arel/alias_predication.rb +9 -0
  227. data/lib/arel/attributes/attribute.rb +41 -0
  228. data/lib/arel/collectors/bind.rb +29 -0
  229. data/lib/arel/collectors/composite.rb +39 -0
  230. data/lib/arel/collectors/plain_string.rb +20 -0
  231. data/lib/arel/collectors/sql_string.rb +27 -0
  232. data/lib/arel/collectors/substitute_binds.rb +35 -0
  233. data/lib/arel/crud.rb +42 -0
  234. data/lib/arel/delete_manager.rb +18 -0
  235. data/lib/arel/errors.rb +9 -0
  236. data/lib/arel/expressions.rb +29 -0
  237. data/lib/arel/factory_methods.rb +49 -0
  238. data/lib/arel/insert_manager.rb +49 -0
  239. data/lib/arel/math.rb +45 -0
  240. data/lib/arel/nodes/and.rb +32 -0
  241. data/lib/arel/nodes/ascending.rb +23 -0
  242. data/lib/arel/nodes/binary.rb +126 -0
  243. data/lib/arel/nodes/bind_param.rb +44 -0
  244. data/lib/arel/nodes/case.rb +55 -0
  245. data/lib/arel/nodes/casted.rb +62 -0
  246. data/lib/arel/nodes/comment.rb +29 -0
  247. data/lib/arel/nodes/count.rb +12 -0
  248. data/lib/arel/nodes/delete_statement.rb +45 -0
  249. data/lib/arel/nodes/descending.rb +23 -0
  250. data/lib/arel/nodes/equality.rb +15 -0
  251. data/lib/arel/nodes/extract.rb +24 -0
  252. data/lib/arel/nodes/false.rb +16 -0
  253. data/lib/arel/nodes/full_outer_join.rb +8 -0
  254. data/lib/arel/nodes/function.rb +44 -0
  255. data/lib/arel/nodes/grouping.rb +11 -0
  256. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  257. data/lib/arel/nodes/in.rb +15 -0
  258. data/lib/arel/nodes/infix_operation.rb +92 -0
  259. data/lib/arel/nodes/inner_join.rb +8 -0
  260. data/lib/arel/nodes/insert_statement.rb +37 -0
  261. data/lib/arel/nodes/join_source.rb +20 -0
  262. data/lib/arel/nodes/matches.rb +18 -0
  263. data/lib/arel/nodes/named_function.rb +23 -0
  264. data/lib/arel/nodes/node.rb +51 -0
  265. data/lib/arel/nodes/node_expression.rb +13 -0
  266. data/lib/arel/nodes/ordering.rb +27 -0
  267. data/lib/arel/nodes/outer_join.rb +8 -0
  268. data/lib/arel/nodes/over.rb +15 -0
  269. data/lib/arel/nodes/regexp.rb +16 -0
  270. data/lib/arel/nodes/right_outer_join.rb +8 -0
  271. data/lib/arel/nodes/select_core.rb +67 -0
  272. data/lib/arel/nodes/select_statement.rb +41 -0
  273. data/lib/arel/nodes/sql_literal.rb +19 -0
  274. data/lib/arel/nodes/string_join.rb +11 -0
  275. data/lib/arel/nodes/table_alias.rb +31 -0
  276. data/lib/arel/nodes/terminal.rb +16 -0
  277. data/lib/arel/nodes/true.rb +16 -0
  278. data/lib/arel/nodes/unary.rb +44 -0
  279. data/lib/arel/nodes/unary_operation.rb +20 -0
  280. data/lib/arel/nodes/unqualified_column.rb +22 -0
  281. data/lib/arel/nodes/update_statement.rb +41 -0
  282. data/lib/arel/nodes/values_list.rb +9 -0
  283. data/lib/arel/nodes/window.rb +126 -0
  284. data/lib/arel/nodes/with.rb +11 -0
  285. data/lib/arel/nodes.rb +70 -0
  286. data/lib/arel/order_predications.rb +13 -0
  287. data/lib/arel/predications.rb +250 -0
  288. data/lib/arel/select_manager.rb +270 -0
  289. data/lib/arel/table.rb +118 -0
  290. data/lib/arel/tree_manager.rb +72 -0
  291. data/lib/arel/update_manager.rb +34 -0
  292. data/lib/arel/visitors/dot.rb +308 -0
  293. data/lib/arel/visitors/mysql.rb +93 -0
  294. data/lib/arel/visitors/postgresql.rb +120 -0
  295. data/lib/arel/visitors/sqlite.rb +38 -0
  296. data/lib/arel/visitors/to_sql.rb +899 -0
  297. data/lib/arel/visitors/visitor.rb +45 -0
  298. data/lib/arel/visitors.rb +13 -0
  299. data/lib/arel/window_predications.rb +9 -0
  300. data/lib/arel.rb +54 -0
  301. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  302. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
  303. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
  304. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
  305. data/lib/rails/generators/active_record/migration.rb +19 -2
  306. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  307. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  308. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  309. metadata +116 -30
  310. data/lib/active_record/attribute_decorators.rb +0 -90
  311. data/lib/active_record/collection_cache_key.rb +0 -53
  312. data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
  313. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
  314. data/lib/active_record/define_callbacks.rb +0 -22
  315. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
  316. data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -102,6 +102,30 @@ module ActiveRecord
102
102
  # If true, the default table name for a Product class will be "products". If false, it would just be "product".
103
103
  # See table_name for the full rules on table/class naming. This is true, by default.
104
104
 
105
+ ##
106
+ # :singleton-method: implicit_order_column
107
+ # :call-seq: implicit_order_column
108
+ #
109
+ # The name of the column records are ordered by if no explicit order clause
110
+ # is used during an ordered finder call. If not set the primary key is used.
111
+
112
+ ##
113
+ # :singleton-method: implicit_order_column=
114
+ # :call-seq: implicit_order_column=(column_name)
115
+ #
116
+ # Sets the column to sort records by when no explicit order clause is used
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. 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
+ # <tt>attribute :foo, :string</tt>. Defaults to false.
128
+
105
129
  included do
106
130
  mattr_accessor :primary_key_prefix_type, instance_writer: false
107
131
 
@@ -110,12 +134,14 @@ module ActiveRecord
110
134
  class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
111
135
  class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
112
136
  class_attribute :pluralize_table_names, instance_writer: false, default: true
137
+ class_attribute :implicit_order_column, instance_accessor: false
138
+ class_attribute :immutable_strings_by_default, instance_accessor: false
113
139
 
114
140
  self.protected_environments = ["production"]
115
141
  self.inheritance_column = "type"
116
142
  self.ignored_columns = [].freeze
117
143
 
118
- delegate :type_for_attribute, to: :class
144
+ delegate :type_for_attribute, :column_for_attribute, to: :class
119
145
 
120
146
  initialize_load_schema_monitor
121
147
  end
@@ -218,11 +244,11 @@ module ActiveRecord
218
244
  end
219
245
 
220
246
  def full_table_name_prefix #:nodoc:
221
- (parents.detect { |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
247
+ (module_parents.detect { |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
222
248
  end
223
249
 
224
250
  def full_table_name_suffix #:nodoc:
225
- (parents.detect { |p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
251
+ (module_parents.detect { |p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
226
252
  end
227
253
 
228
254
  # The array of names of environments where destructive actions should be prohibited. By default,
@@ -271,12 +297,42 @@ module ActiveRecord
271
297
 
272
298
  # Sets the columns names the model should ignore. Ignored columns won't have attribute
273
299
  # accessors defined, and won't be referenced in SQL queries.
300
+ #
301
+ # A common usage pattern for this method is to ensure all references to an attribute
302
+ # have been removed and deployed, before a migration to drop the column from the database
303
+ # has been deployed and run. Using this two step approach to dropping columns ensures there
304
+ # is no code that raises errors due to having a cached schema in memory at the time the
305
+ # schema migration is run.
306
+ #
307
+ # For example, given a model where you want to drop the "category" attribute, first mark it
308
+ # as ignored:
309
+ #
310
+ # class Project < ActiveRecord::Base
311
+ # # schema:
312
+ # # id :bigint
313
+ # # name :string, limit: 255
314
+ # # category :string, limit: 255
315
+ #
316
+ # self.ignored_columns = [:category]
317
+ # end
318
+ #
319
+ # The schema still contains "category", but now the model omits it, so any meta-driven code or
320
+ # schema caching will not attempt to use the column:
321
+ #
322
+ # Project.columns_hash["category"] => nil
323
+ #
324
+ # You will get an error if accessing that attribute directly, so ensure all usages of the
325
+ # column are removed (automated tests can help you find any usages).
326
+ #
327
+ # user = Project.create!(name: "First Project")
328
+ # user.category # => raises NoMethodError
274
329
  def ignored_columns=(columns)
275
- @ignored_columns = columns.map(&:to_s)
330
+ reload_schema_from_cache
331
+ @ignored_columns = columns.map(&:to_s).freeze
276
332
  end
277
333
 
278
334
  def sequence_name
279
- if base_class == self
335
+ if base_class?
280
336
  @sequence_name ||= reset_sequence_name
281
337
  else
282
338
  (@sequence_name ||= nil) || base_class.sequence_name
@@ -339,7 +395,7 @@ module ActiveRecord
339
395
 
340
396
  def columns
341
397
  load_schema
342
- @columns ||= columns_hash.values
398
+ @columns ||= columns_hash.values.freeze
343
399
  end
344
400
 
345
401
  def attribute_types # :nodoc:
@@ -364,6 +420,8 @@ module ActiveRecord
364
420
  # a string or a symbol.
365
421
  def type_for_attribute(attr_name, &block)
366
422
  attr_name = attr_name.to_s
423
+ attr_name = attribute_aliases[attr_name] || attr_name
424
+
367
425
  if block
368
426
  attribute_types.fetch(attr_name, &block)
369
427
  else
@@ -371,11 +429,31 @@ module ActiveRecord
371
429
  end
372
430
  end
373
431
 
432
+ # Returns the column object for the named attribute.
433
+ # Returns an +ActiveRecord::ConnectionAdapters::NullColumn+ if the
434
+ # named attribute does not exist.
435
+ #
436
+ # class Person < ActiveRecord::Base
437
+ # end
438
+ #
439
+ # person = Person.new
440
+ # person.column_for_attribute(:name) # the result depends on the ConnectionAdapter
441
+ # # => #<ActiveRecord::ConnectionAdapters::Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>
442
+ #
443
+ # person.column_for_attribute(:nothing)
444
+ # # => #<ActiveRecord::ConnectionAdapters::NullColumn:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...>
445
+ def column_for_attribute(name)
446
+ name = name.to_s
447
+ columns_hash.fetch(name) do
448
+ ConnectionAdapters::NullColumn.new(name)
449
+ end
450
+ end
451
+
374
452
  # Returns a hash where the keys are column names and the values are
375
453
  # default values when instantiating the Active Record object for this table.
376
454
  def column_defaults
377
455
  load_schema
378
- @column_defaults ||= _default_attributes.deep_dup.to_hash
456
+ @column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
379
457
  end
380
458
 
381
459
  def _default_attributes # :nodoc:
@@ -385,7 +463,12 @@ module ActiveRecord
385
463
 
386
464
  # Returns an array of column names as strings.
387
465
  def column_names
388
- @column_names ||= columns.map(&:name)
466
+ @column_names ||= columns.map(&:name).freeze
467
+ end
468
+
469
+ def symbol_column_to_string(name_symbol) # :nodoc:
470
+ @symbol_column_to_string_name_hash ||= column_names.index_by(&:to_sym)
471
+ @symbol_column_to_string_name_hash[name_symbol]
389
472
  end
390
473
 
391
474
  # Returns an array of column objects where the primary id, all columns ending in "_id" or "_count",
@@ -394,9 +477,8 @@ module ActiveRecord
394
477
  @content_columns ||= columns.reject do |c|
395
478
  c.name == primary_key ||
396
479
  c.name == inheritance_column ||
397
- c.name.end_with?("_id") ||
398
- c.name.end_with?("_count")
399
- end
480
+ c.name.end_with?("_id", "_count")
481
+ end.freeze
400
482
  end
401
483
 
402
484
  # Resets all the cached information about columns, which will cause them
@@ -406,7 +488,7 @@ module ActiveRecord
406
488
  # when just after creating a table you want to populate it with some default
407
489
  # values, eg:
408
490
  #
409
- # class CreateJobLevels < ActiveRecord::Migration[5.0]
491
+ # class CreateJobLevels < ActiveRecord::Migration[6.0]
410
492
  # def up
411
493
  # create_table :job_levels do |t|
412
494
  # t.integer :id
@@ -435,13 +517,11 @@ module ActiveRecord
435
517
  end
436
518
 
437
519
  protected
438
-
439
520
  def initialize_load_schema_monitor
440
521
  @load_schema_monitor = Monitor.new
441
522
  end
442
523
 
443
524
  private
444
-
445
525
  def inherited(child_class)
446
526
  super
447
527
  child_class.initialize_load_schema_monitor
@@ -459,15 +539,27 @@ module ActiveRecord
459
539
  load_schema!
460
540
 
461
541
  @schema_loaded = true
542
+ rescue
543
+ reload_schema_from_cache # If the schema loading failed half way through, we must reset the state.
544
+ raise
462
545
  end
463
546
  end
464
547
 
465
548
  def load_schema!
466
- @columns_hash = connection.schema_cache.columns_hash(table_name).except(*ignored_columns)
549
+ unless table_name
550
+ raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
551
+ end
552
+
553
+ columns_hash = connection.schema_cache.columns_hash(table_name)
554
+ columns_hash = columns_hash.except(*ignored_columns) unless ignored_columns.empty?
555
+ @columns_hash = columns_hash.freeze
467
556
  @columns_hash.each do |name, column|
557
+ type = connection.lookup_cast_type_from_column(column)
558
+ type = _convert_type_from_options(type)
559
+ warn_if_deprecated_type(column)
468
560
  define_attribute(
469
561
  name,
470
- connection.lookup_cast_type_from_column(column),
562
+ type,
471
563
  default: column.default,
472
564
  user_provided_default: false
473
565
  )
@@ -477,6 +569,7 @@ module ActiveRecord
477
569
  def reload_schema_from_cache
478
570
  @arel_table = nil
479
571
  @column_names = nil
572
+ @symbol_column_to_string_name_hash = nil
480
573
  @attribute_types = nil
481
574
  @content_columns = nil
482
575
  @default_attributes = nil
@@ -501,19 +594,52 @@ module ActiveRecord
501
594
 
502
595
  # Computes and returns a table name according to default conventions.
503
596
  def compute_table_name
504
- base = base_class
505
- if self == base
597
+ if base_class?
506
598
  # Nested classes are prefixed with singular parent table name.
507
- if parent < Base && !parent.abstract_class?
508
- contained = parent.table_name
509
- contained = contained.singularize if parent.pluralize_table_names
599
+ if module_parent < Base && !module_parent.abstract_class?
600
+ contained = module_parent.table_name
601
+ contained = contained.singularize if module_parent.pluralize_table_names
510
602
  contained += "_"
511
603
  end
512
604
 
513
605
  "#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}"
514
606
  else
515
607
  # STI subclasses always use their superclass' table.
516
- base.table_name
608
+ base_class.table_name
609
+ end
610
+ end
611
+
612
+ def _convert_type_from_options(type)
613
+ if immutable_strings_by_default && type.respond_to?(:to_immutable_string)
614
+ type.to_immutable_string
615
+ else
616
+ type
617
+ end
618
+ end
619
+
620
+ def warn_if_deprecated_type(column)
621
+ return if attributes_to_define_after_schema_loads.key?(column.name)
622
+ return unless column.respond_to?(:oid)
623
+
624
+ if column.array?
625
+ array_arguments = ", array: true"
626
+ else
627
+ array_arguments = ""
628
+ end
629
+
630
+ if column.sql_type.start_with?("interval")
631
+ precision_arguments = column.precision.presence && ", precision: #{column.precision}"
632
+ ActiveSupport::Deprecation.warn(<<~WARNING)
633
+ The behavior of the `:interval` type will be changing in Rails 7.0
634
+ to return an `ActiveSupport::Duration` object. If you'd like to keep
635
+ the old behavior, you can add this line to #{self.name} model:
636
+
637
+ attribute :#{column.name}, :string#{precision_arguments}#{array_arguments}
638
+
639
+ If you'd like the new behavior today, you can add this line:
640
+
641
+ attribute :#{column.name}, :interval#{precision_arguments}#{array_arguments}
642
+ WARNING
517
643
  end
518
644
  end
519
645
  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
@@ -354,7 +353,6 @@ module ActiveRecord
354
353
  end
355
354
 
356
355
  private
357
-
358
356
  # Generates a writer method for this association. Serves as a point for
359
357
  # accessing the objects in the association. For example, this method
360
358
  # could generate the following:
@@ -386,7 +384,6 @@ module ActiveRecord
386
384
  end
387
385
 
388
386
  private
389
-
390
387
  # Attribute hash keys that should not be assigned as normal attributes.
391
388
  # These hash keys are nested attributes implementation details.
392
389
  UNASSIGNABLE_KEYS = %w( id _destroy )
@@ -426,7 +423,7 @@ module ActiveRecord
426
423
  existing_record.assign_attributes(assignable_attributes)
427
424
  association(association_name).initialize_attributes(existing_record)
428
425
  else
429
- method = "build_#{association_name}"
426
+ method = :"build_#{association_name}"
430
427
  if respond_to?(method)
431
428
  send(method, assignable_attributes)
432
429
  else
@@ -501,7 +498,7 @@ module ActiveRecord
501
498
 
502
499
  if attributes["id"].blank?
503
500
  unless reject_new_record?(association_name, attributes)
504
- association.build(attributes.except(*UNASSIGNABLE_KEYS))
501
+ association.reader.build(attributes.except(*UNASSIGNABLE_KEYS))
505
502
  end
506
503
  elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes["id"].to_s }
507
504
  unless call_reject_if(association_name, attributes)
@@ -512,7 +509,7 @@ module ActiveRecord
512
509
  if target_record
513
510
  existing_record = target_record
514
511
  else
515
- association.add_to_target(existing_record, :skip_callbacks)
512
+ association.add_to_target(existing_record, skip_callbacks: true)
516
513
  end
517
514
 
518
515
  assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
@@ -43,6 +43,13 @@ module ActiveRecord
43
43
  end
44
44
  end
45
45
 
46
+ # Returns +true+ if the class has +no_touching+ set, +false+ otherwise.
47
+ #
48
+ # Project.no_touching do
49
+ # Project.first.no_touching? # true
50
+ # Message.first.no_touching? # false
51
+ # end
52
+ #
46
53
  def no_touching?
47
54
  NoTouching.applied_to?(self.class)
48
55
  end
@@ -51,7 +58,7 @@ module ActiveRecord
51
58
  super unless no_touching?
52
59
  end
53
60
 
54
- def touch(*) # :nodoc:
61
+ def touch(*, **) # :nodoc:
55
62
  super unless no_touching?
56
63
  end
57
64
  end
@@ -60,7 +60,6 @@ module ActiveRecord
60
60
  end
61
61
 
62
62
  private
63
-
64
63
  def exec_queries
65
64
  @records = [].freeze
66
65
  end