activerecord 5.2.8 → 7.0.2

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 (364) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1393 -587
  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 +10 -9
  7. data/lib/active_record/association_relation.rb +22 -12
  8. data/lib/active_record/associations/alias_tracker.rb +19 -16
  9. data/lib/active_record/associations/association.rb +122 -47
  10. data/lib/active_record/associations/association_scope.rb +24 -24
  11. data/lib/active_record/associations/belongs_to_association.rb +67 -49
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -7
  13. data/lib/active_record/associations/builder/association.rb +52 -23
  14. data/lib/active_record/associations/builder/belongs_to.rb +44 -61
  15. data/lib/active_record/associations/builder/collection_association.rb +17 -19
  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 +10 -3
  18. data/lib/active_record/associations/builder/has_one.rb +35 -3
  19. data/lib/active_record/associations/builder/singular_association.rb +5 -3
  20. data/lib/active_record/associations/collection_association.rb +59 -50
  21. data/lib/active_record/associations/collection_proxy.rb +32 -23
  22. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  23. data/lib/active_record/associations/foreign_association.rb +20 -0
  24. data/lib/active_record/associations/has_many_association.rb +27 -14
  25. data/lib/active_record/associations/has_many_through_association.rb +26 -19
  26. data/lib/active_record/associations/has_one_association.rb +52 -37
  27. data/lib/active_record/associations/has_one_through_association.rb +6 -6
  28. data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
  29. data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
  30. data/lib/active_record/associations/join_dependency.rb +97 -62
  31. data/lib/active_record/associations/preloader/association.rb +220 -60
  32. data/lib/active_record/associations/preloader/batch.rb +48 -0
  33. data/lib/active_record/associations/preloader/branch.rb +147 -0
  34. data/lib/active_record/associations/preloader/through_association.rb +85 -40
  35. data/lib/active_record/associations/preloader.rb +44 -105
  36. data/lib/active_record/associations/singular_association.rb +9 -17
  37. data/lib/active_record/associations/through_association.rb +4 -4
  38. data/lib/active_record/associations.rb +207 -66
  39. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  40. data/lib/active_record/attribute_assignment.rb +17 -19
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +19 -8
  42. data/lib/active_record/attribute_methods/dirty.rb +141 -47
  43. data/lib/active_record/attribute_methods/primary_key.rb +22 -27
  44. data/lib/active_record/attribute_methods/query.rb +6 -10
  45. data/lib/active_record/attribute_methods/read.rb +15 -55
  46. data/lib/active_record/attribute_methods/serialization.rb +77 -18
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +16 -18
  48. data/lib/active_record/attribute_methods/write.rb +18 -37
  49. data/lib/active_record/attribute_methods.rb +90 -153
  50. data/lib/active_record/attributes.rb +38 -12
  51. data/lib/active_record/autosave_association.rb +50 -50
  52. data/lib/active_record/base.rb +23 -18
  53. data/lib/active_record/callbacks.rb +159 -44
  54. data/lib/active_record/coders/yaml_column.rb +12 -3
  55. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
  57. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
  58. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +92 -464
  59. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -51
  60. data/lib/active_record/connection_adapters/abstract/database_statements.rb +209 -164
  61. data/lib/active_record/connection_adapters/abstract/query_cache.rb +38 -22
  62. data/lib/active_record/connection_adapters/abstract/quoting.rb +103 -82
  63. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  64. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +140 -110
  65. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -94
  66. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +16 -5
  67. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +456 -159
  68. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -162
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +311 -327
  71. data/lib/active_record/connection_adapters/column.rb +33 -11
  72. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  73. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  74. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  75. data/lib/active_record/connection_adapters/mysql/database_statements.rb +113 -45
  76. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  77. data/lib/active_record/connection_adapters/mysql/quoting.rb +71 -5
  78. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
  79. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
  80. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +25 -8
  81. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +143 -19
  82. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
  83. data/lib/active_record/connection_adapters/mysql2_adapter.rb +63 -22
  84. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  85. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  86. data/lib/active_record/connection_adapters/postgresql/column.rb +53 -28
  87. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +56 -63
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +54 -16
  95. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +26 -12
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -52
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -2
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +39 -4
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +128 -91
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -1
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +149 -113
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +386 -182
  116. data/lib/active_record/connection_adapters/schema_cache.rb +161 -22
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
  118. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +152 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +65 -18
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  121. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +92 -26
  122. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +251 -204
  123. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  124. data/lib/active_record/connection_adapters.rb +53 -0
  125. data/lib/active_record/connection_handling.rb +292 -38
  126. data/lib/active_record/core.rb +385 -158
  127. data/lib/active_record/counter_cache.rb +8 -30
  128. data/lib/active_record/database_configurations/connection_url_resolver.rb +100 -0
  129. data/lib/active_record/database_configurations/database_config.rb +83 -0
  130. data/lib/active_record/database_configurations/hash_config.rb +154 -0
  131. data/lib/active_record/database_configurations/url_config.rb +53 -0
  132. data/lib/active_record/database_configurations.rb +256 -0
  133. data/lib/active_record/delegated_type.rb +250 -0
  134. data/lib/active_record/destroy_association_async_job.rb +36 -0
  135. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  136. data/lib/active_record/dynamic_matchers.rb +4 -5
  137. data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
  138. data/lib/active_record/encryption/cipher.rb +53 -0
  139. data/lib/active_record/encryption/config.rb +44 -0
  140. data/lib/active_record/encryption/configurable.rb +61 -0
  141. data/lib/active_record/encryption/context.rb +35 -0
  142. data/lib/active_record/encryption/contexts.rb +72 -0
  143. data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
  144. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  145. data/lib/active_record/encryption/encryptable_record.rb +208 -0
  146. data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
  147. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  148. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  149. data/lib/active_record/encryption/encryptor.rb +155 -0
  150. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  151. data/lib/active_record/encryption/errors.rb +15 -0
  152. data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
  153. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  154. data/lib/active_record/encryption/key.rb +28 -0
  155. data/lib/active_record/encryption/key_generator.rb +42 -0
  156. data/lib/active_record/encryption/key_provider.rb +46 -0
  157. data/lib/active_record/encryption/message.rb +33 -0
  158. data/lib/active_record/encryption/message_serializer.rb +90 -0
  159. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  160. data/lib/active_record/encryption/properties.rb +76 -0
  161. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  162. data/lib/active_record/encryption/scheme.rb +99 -0
  163. data/lib/active_record/encryption.rb +55 -0
  164. data/lib/active_record/enum.rb +130 -51
  165. data/lib/active_record/errors.rb +129 -23
  166. data/lib/active_record/explain.rb +10 -6
  167. data/lib/active_record/explain_registry.rb +11 -6
  168. data/lib/active_record/explain_subscriber.rb +1 -1
  169. data/lib/active_record/fixture_set/file.rb +22 -15
  170. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  171. data/lib/active_record/fixture_set/render_context.rb +17 -0
  172. data/lib/active_record/fixture_set/table_row.rb +187 -0
  173. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  174. data/lib/active_record/fixtures.rb +206 -490
  175. data/lib/active_record/future_result.rb +139 -0
  176. data/lib/active_record/gem_version.rb +3 -3
  177. data/lib/active_record/inheritance.rb +104 -37
  178. data/lib/active_record/insert_all.rb +278 -0
  179. data/lib/active_record/integration.rb +69 -18
  180. data/lib/active_record/internal_metadata.rb +24 -9
  181. data/lib/active_record/legacy_yaml_adapter.rb +3 -36
  182. data/lib/active_record/locking/optimistic.rb +41 -26
  183. data/lib/active_record/locking/pessimistic.rb +18 -8
  184. data/lib/active_record/log_subscriber.rb +46 -35
  185. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  186. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  187. data/lib/active_record/middleware/database_selector.rb +82 -0
  188. data/lib/active_record/middleware/shard_selector.rb +60 -0
  189. data/lib/active_record/migration/command_recorder.rb +96 -44
  190. data/lib/active_record/migration/compatibility.rb +246 -64
  191. data/lib/active_record/migration/join_table.rb +1 -2
  192. data/lib/active_record/migration.rb +266 -187
  193. data/lib/active_record/model_schema.rb +165 -52
  194. data/lib/active_record/nested_attributes.rb +17 -19
  195. data/lib/active_record/no_touching.rb +11 -4
  196. data/lib/active_record/null_relation.rb +2 -7
  197. data/lib/active_record/persistence.rb +467 -92
  198. data/lib/active_record/query_cache.rb +21 -4
  199. data/lib/active_record/query_logs.rb +138 -0
  200. data/lib/active_record/querying.rb +51 -24
  201. data/lib/active_record/railtie.rb +224 -57
  202. data/lib/active_record/railties/console_sandbox.rb +2 -4
  203. data/lib/active_record/railties/controller_runtime.rb +31 -36
  204. data/lib/active_record/railties/databases.rake +369 -101
  205. data/lib/active_record/readonly_attributes.rb +15 -0
  206. data/lib/active_record/reflection.rb +170 -137
  207. data/lib/active_record/relation/batches/batch_enumerator.rb +44 -14
  208. data/lib/active_record/relation/batches.rb +46 -37
  209. data/lib/active_record/relation/calculations.rb +168 -96
  210. data/lib/active_record/relation/delegation.rb +37 -52
  211. data/lib/active_record/relation/finder_methods.rb +79 -58
  212. data/lib/active_record/relation/from_clause.rb +5 -1
  213. data/lib/active_record/relation/merger.rb +50 -51
  214. data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
  215. data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
  216. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  217. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
  218. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  219. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  220. data/lib/active_record/relation/predicate_builder.rb +58 -46
  221. data/lib/active_record/relation/query_attribute.rb +9 -10
  222. data/lib/active_record/relation/query_methods.rb +685 -208
  223. data/lib/active_record/relation/record_fetch_warning.rb +9 -11
  224. data/lib/active_record/relation/spawn_methods.rb +10 -10
  225. data/lib/active_record/relation/where_clause.rb +108 -64
  226. data/lib/active_record/relation.rb +515 -151
  227. data/lib/active_record/result.rb +78 -42
  228. data/lib/active_record/runtime_registry.rb +9 -13
  229. data/lib/active_record/sanitization.rb +29 -44
  230. data/lib/active_record/schema.rb +37 -31
  231. data/lib/active_record/schema_dumper.rb +74 -23
  232. data/lib/active_record/schema_migration.rb +7 -9
  233. data/lib/active_record/scoping/default.rb +62 -17
  234. data/lib/active_record/scoping/named.rb +17 -32
  235. data/lib/active_record/scoping.rb +70 -41
  236. data/lib/active_record/secure_token.rb +16 -8
  237. data/lib/active_record/serialization.rb +6 -4
  238. data/lib/active_record/signed_id.rb +116 -0
  239. data/lib/active_record/statement_cache.rb +49 -6
  240. data/lib/active_record/store.rb +88 -9
  241. data/lib/active_record/suppressor.rb +13 -17
  242. data/lib/active_record/table_metadata.rb +42 -43
  243. data/lib/active_record/tasks/database_tasks.rb +352 -94
  244. data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
  245. data/lib/active_record/tasks/postgresql_database_tasks.rb +41 -39
  246. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
  247. data/lib/active_record/test_databases.rb +24 -0
  248. data/lib/active_record/test_fixtures.rb +287 -0
  249. data/lib/active_record/timestamp.rb +44 -34
  250. data/lib/active_record/touch_later.rb +23 -22
  251. data/lib/active_record/transactions.rb +67 -128
  252. data/lib/active_record/translation.rb +3 -3
  253. data/lib/active_record/type/adapter_specific_registry.rb +34 -19
  254. data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
  255. data/lib/active_record/type/internal/timezone.rb +2 -2
  256. data/lib/active_record/type/serialized.rb +7 -4
  257. data/lib/active_record/type/time.rb +10 -0
  258. data/lib/active_record/type/type_map.rb +17 -21
  259. data/lib/active_record/type/unsigned_integer.rb +0 -1
  260. data/lib/active_record/type.rb +9 -5
  261. data/lib/active_record/type_caster/connection.rb +15 -15
  262. data/lib/active_record/type_caster/map.rb +8 -8
  263. data/lib/active_record/validations/associated.rb +2 -3
  264. data/lib/active_record/validations/numericality.rb +35 -0
  265. data/lib/active_record/validations/uniqueness.rb +39 -31
  266. data/lib/active_record/validations.rb +4 -3
  267. data/lib/active_record.rb +209 -32
  268. data/lib/arel/alias_predication.rb +9 -0
  269. data/lib/arel/attributes/attribute.rb +33 -0
  270. data/lib/arel/collectors/bind.rb +29 -0
  271. data/lib/arel/collectors/composite.rb +39 -0
  272. data/lib/arel/collectors/plain_string.rb +20 -0
  273. data/lib/arel/collectors/sql_string.rb +27 -0
  274. data/lib/arel/collectors/substitute_binds.rb +35 -0
  275. data/lib/arel/crud.rb +48 -0
  276. data/lib/arel/delete_manager.rb +32 -0
  277. data/lib/arel/errors.rb +9 -0
  278. data/lib/arel/expressions.rb +29 -0
  279. data/lib/arel/factory_methods.rb +49 -0
  280. data/lib/arel/filter_predications.rb +9 -0
  281. data/lib/arel/insert_manager.rb +48 -0
  282. data/lib/arel/math.rb +45 -0
  283. data/lib/arel/nodes/and.rb +32 -0
  284. data/lib/arel/nodes/ascending.rb +23 -0
  285. data/lib/arel/nodes/binary.rb +126 -0
  286. data/lib/arel/nodes/bind_param.rb +44 -0
  287. data/lib/arel/nodes/case.rb +55 -0
  288. data/lib/arel/nodes/casted.rb +62 -0
  289. data/lib/arel/nodes/comment.rb +29 -0
  290. data/lib/arel/nodes/count.rb +12 -0
  291. data/lib/arel/nodes/delete_statement.rb +44 -0
  292. data/lib/arel/nodes/descending.rb +23 -0
  293. data/lib/arel/nodes/equality.rb +15 -0
  294. data/lib/arel/nodes/extract.rb +24 -0
  295. data/lib/arel/nodes/false.rb +16 -0
  296. data/lib/arel/nodes/filter.rb +10 -0
  297. data/lib/arel/nodes/full_outer_join.rb +8 -0
  298. data/lib/arel/nodes/function.rb +45 -0
  299. data/lib/arel/nodes/grouping.rb +11 -0
  300. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  301. data/lib/arel/nodes/in.rb +15 -0
  302. data/lib/arel/nodes/infix_operation.rb +92 -0
  303. data/lib/arel/nodes/inner_join.rb +8 -0
  304. data/lib/arel/nodes/insert_statement.rb +37 -0
  305. data/lib/arel/nodes/join_source.rb +20 -0
  306. data/lib/arel/nodes/matches.rb +18 -0
  307. data/lib/arel/nodes/named_function.rb +23 -0
  308. data/lib/arel/nodes/node.rb +51 -0
  309. data/lib/arel/nodes/node_expression.rb +13 -0
  310. data/lib/arel/nodes/ordering.rb +27 -0
  311. data/lib/arel/nodes/outer_join.rb +8 -0
  312. data/lib/arel/nodes/over.rb +15 -0
  313. data/lib/arel/nodes/regexp.rb +16 -0
  314. data/lib/arel/nodes/right_outer_join.rb +8 -0
  315. data/lib/arel/nodes/select_core.rb +67 -0
  316. data/lib/arel/nodes/select_statement.rb +41 -0
  317. data/lib/arel/nodes/sql_literal.rb +19 -0
  318. data/lib/arel/nodes/string_join.rb +11 -0
  319. data/lib/arel/nodes/table_alias.rb +31 -0
  320. data/lib/arel/nodes/terminal.rb +16 -0
  321. data/lib/arel/nodes/true.rb +16 -0
  322. data/lib/arel/nodes/unary.rb +44 -0
  323. data/lib/arel/nodes/unary_operation.rb +20 -0
  324. data/lib/arel/nodes/unqualified_column.rb +22 -0
  325. data/lib/arel/nodes/update_statement.rb +46 -0
  326. data/lib/arel/nodes/values_list.rb +9 -0
  327. data/lib/arel/nodes/window.rb +126 -0
  328. data/lib/arel/nodes/with.rb +11 -0
  329. data/lib/arel/nodes.rb +71 -0
  330. data/lib/arel/order_predications.rb +13 -0
  331. data/lib/arel/predications.rb +258 -0
  332. data/lib/arel/select_manager.rb +276 -0
  333. data/lib/arel/table.rb +117 -0
  334. data/lib/arel/tree_manager.rb +60 -0
  335. data/lib/arel/update_manager.rb +48 -0
  336. data/lib/arel/visitors/dot.rb +298 -0
  337. data/lib/arel/visitors/mysql.rb +99 -0
  338. data/lib/arel/visitors/postgresql.rb +110 -0
  339. data/lib/arel/visitors/sqlite.rb +38 -0
  340. data/lib/arel/visitors/to_sql.rb +955 -0
  341. data/lib/arel/visitors/visitor.rb +45 -0
  342. data/lib/arel/visitors.rb +13 -0
  343. data/lib/arel/window_predications.rb +9 -0
  344. data/lib/arel.rb +55 -0
  345. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  346. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  347. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
  348. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
  349. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
  350. data/lib/rails/generators/active_record/migration.rb +19 -2
  351. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  352. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  353. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  354. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  355. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  356. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  357. metadata +162 -32
  358. data/lib/active_record/attribute_decorators.rb +0 -90
  359. data/lib/active_record/collection_cache_key.rb +0 -53
  360. data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
  361. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
  362. data/lib/active_record/define_callbacks.rb +0 -22
  363. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
  364. data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "mutex_m"
4
+ require "active_support/core_ext/enumerable"
4
5
 
5
6
  module ActiveRecord
6
7
  # = Active Record Attribute Methods
@@ -18,33 +19,34 @@ module ActiveRecord
18
19
  include TimeZoneConversion
19
20
  include Dirty
20
21
  include Serialization
21
-
22
- delegate :column_for_attribute, to: :class
23
22
  end
24
23
 
25
- AttrNames = Module.new {
26
- def self.set_name_cache(name, value)
27
- const_name = "ATTR_#{name}"
28
- unless const_defined? const_name
29
- const_set const_name, value.dup.freeze
30
- end
31
- end
32
- }
33
-
34
- BLACKLISTED_CLASS_METHODS = %w(private public protected allocate new name parent superclass)
24
+ RESTRICTED_CLASS_METHODS = %w(private public protected allocate new name parent superclass)
35
25
 
36
- class GeneratedAttributeMethods < Module #:nodoc:
26
+ class GeneratedAttributeMethods < Module # :nodoc:
37
27
  include Mutex_m
38
28
  end
39
29
 
30
+ class << self
31
+ def dangerous_attribute_methods # :nodoc:
32
+ @dangerous_attribute_methods ||= (
33
+ Base.instance_methods +
34
+ Base.private_instance_methods -
35
+ Base.superclass.instance_methods -
36
+ Base.superclass.private_instance_methods
37
+ ).map { |m| -m.to_s }.to_set.freeze
38
+ end
39
+ end
40
+
40
41
  module ClassMethods
41
- def inherited(child_class) #:nodoc:
42
+ def inherited(child_class) # :nodoc:
42
43
  child_class.initialize_generated_modules
43
44
  super
44
45
  end
45
46
 
46
47
  def initialize_generated_modules # :nodoc:
47
- @generated_attribute_methods = GeneratedAttributeMethods.new
48
+ @generated_attribute_methods = const_set(:GeneratedAttributeMethods, GeneratedAttributeMethods.new)
49
+ private_constant :GeneratedAttributeMethods
48
50
  @attribute_methods_generated = false
49
51
  include @generated_attribute_methods
50
52
 
@@ -59,7 +61,7 @@ module ActiveRecord
59
61
  # attribute methods.
60
62
  generated_attribute_methods.synchronize do
61
63
  return false if @attribute_methods_generated
62
- superclass.define_attribute_methods unless self == base_class
64
+ superclass.define_attribute_methods unless base_class?
63
65
  super(attribute_names)
64
66
  @attribute_methods_generated = true
65
67
  end
@@ -105,7 +107,7 @@ module ActiveRecord
105
107
  # A method name is 'dangerous' if it is already (re)defined by Active Record, but
106
108
  # not by any ancestors. (So 'puts' is not dangerous but 'save' is.)
107
109
  def dangerous_attribute_method?(name) # :nodoc:
108
- method_defined_within?(name, Base)
110
+ ::ActiveRecord::AttributeMethods.dangerous_attribute_methods.include?(name.to_s)
109
111
  end
110
112
 
111
113
  def method_defined_within?(name, klass, superklass = klass.superclass) # :nodoc:
@@ -123,13 +125,11 @@ module ActiveRecord
123
125
  # A class method is 'dangerous' if it is already (re)defined by Active Record, but
124
126
  # not by any ancestors. (So 'puts' is not dangerous but 'new' is.)
125
127
  def dangerous_class_method?(method_name)
126
- BLACKLISTED_CLASS_METHODS.include?(method_name.to_s) || class_method_defined_within?(method_name, Base)
127
- end
128
+ return true if RESTRICTED_CLASS_METHODS.include?(method_name.to_s)
128
129
 
129
- def class_method_defined_within?(name, klass, superklass = klass.superclass) # :nodoc:
130
- if klass.respond_to?(name, true)
131
- if superklass.respond_to?(name, true)
132
- klass.method(name).owner != superklass.method(name).owner
130
+ if Base.respond_to?(method_name, true)
131
+ if Object.respond_to?(method_name, true)
132
+ Base.method(method_name).owner != Object.method(method_name).owner
133
133
  else
134
134
  true
135
135
  end
@@ -148,7 +148,7 @@ module ActiveRecord
148
148
  # Person.attribute_method?(:age=) # => true
149
149
  # Person.attribute_method?(:nothing) # => false
150
150
  def attribute_method?(attribute)
151
- super || (table_exists? && column_names.include?(attribute.to_s.sub(/=$/, "")))
151
+ super || (table_exists? && column_names.include?(attribute.to_s.delete_suffix("=")))
152
152
  end
153
153
 
154
154
  # Returns an array of column names as strings if it's not an abstract class and
@@ -164,90 +164,27 @@ module ActiveRecord
164
164
  attribute_types.keys
165
165
  else
166
166
  []
167
- end
168
- end
169
-
170
- # Regexp whitelist. Matches the following:
171
- # "#{table_name}.#{column_name}"
172
- # "#{column_name}"
173
- COLUMN_NAME_WHITELIST = /\A(?:\w+\.)?\w+\z/i
174
-
175
- # Regexp whitelist. Matches the following:
176
- # "#{table_name}.#{column_name}"
177
- # "#{table_name}.#{column_name} #{direction}"
178
- # "#{table_name}.#{column_name} #{direction} NULLS FIRST"
179
- # "#{table_name}.#{column_name} NULLS LAST"
180
- # "#{column_name}"
181
- # "#{column_name} #{direction}"
182
- # "#{column_name} #{direction} NULLS FIRST"
183
- # "#{column_name} NULLS LAST"
184
- COLUMN_NAME_ORDER_WHITELIST = /
185
- \A
186
- (?:\w+\.)?
187
- \w+
188
- (?:\s+asc|\s+desc)?
189
- (?:\s+nulls\s+(?:first|last))?
190
- \z
191
- /ix
192
-
193
- def enforce_raw_sql_whitelist(args, whitelist: COLUMN_NAME_WHITELIST) # :nodoc:
194
- unexpected = args.reject do |arg|
195
- arg.kind_of?(Arel::Node) ||
196
- arg.is_a?(Arel::Nodes::SqlLiteral) ||
197
- arg.is_a?(Arel::Attributes::Attribute) ||
198
- arg.to_s.split(/\s*,\s*/).all? { |part| whitelist.match?(part) }
199
- end
200
-
201
- return if unexpected.none?
202
-
203
- if allow_unsafe_raw_sql == :deprecated
204
- ActiveSupport::Deprecation.warn(
205
- "Dangerous query method (method whose arguments are used as raw " \
206
- "SQL) called with non-attribute argument(s): " \
207
- "#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \
208
- "arguments will be disallowed in Rails 6.0. This method should " \
209
- "not be called with user-provided values, such as request " \
210
- "parameters or model attributes. Known-safe values can be passed " \
211
- "by wrapping them in Arel.sql()."
212
- )
213
- else
214
- raise(ActiveRecord::UnknownAttributeReference,
215
- "Query method called with non-attribute argument(s): " +
216
- unexpected.map(&:inspect).join(", ")
217
- )
218
- end
167
+ end.freeze
219
168
  end
220
169
 
221
170
  # Returns true if the given attribute exists, otherwise false.
222
171
  #
223
172
  # class Person < ActiveRecord::Base
173
+ # alias_attribute :new_name, :name
224
174
  # end
225
175
  #
226
- # Person.has_attribute?('name') # => true
227
- # Person.has_attribute?(:age) # => true
228
- # Person.has_attribute?(:nothing) # => false
176
+ # Person.has_attribute?('name') # => true
177
+ # Person.has_attribute?('new_name') # => true
178
+ # Person.has_attribute?(:age) # => true
179
+ # Person.has_attribute?(:nothing) # => false
229
180
  def has_attribute?(attr_name)
230
- attribute_types.key?(attr_name.to_s)
181
+ attr_name = attr_name.to_s
182
+ attr_name = attribute_aliases[attr_name] || attr_name
183
+ attribute_types.key?(attr_name)
231
184
  end
232
185
 
233
- # Returns the column object for the named attribute.
234
- # Returns a +ActiveRecord::ConnectionAdapters::NullColumn+ if the
235
- # named attribute does not exist.
236
- #
237
- # class Person < ActiveRecord::Base
238
- # end
239
- #
240
- # person = Person.new
241
- # person.column_for_attribute(:name) # the result depends on the ConnectionAdapter
242
- # # => #<ActiveRecord::ConnectionAdapters::Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>
243
- #
244
- # person.column_for_attribute(:nothing)
245
- # # => #<ActiveRecord::ConnectionAdapters::NullColumn:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...>
246
- def column_for_attribute(name)
247
- name = name.to_s
248
- columns_hash.fetch(name) do
249
- ConnectionAdapters::NullColumn.new(name)
250
- end
186
+ def _has_attribute?(attr_name) # :nodoc:
187
+ attribute_types.key?(attr_name)
251
188
  end
252
189
  end
253
190
 
@@ -270,21 +207,14 @@ module ActiveRecord
270
207
  def respond_to?(name, include_private = false)
271
208
  return false unless super
272
209
 
273
- case name
274
- when :to_partial_path
275
- name = "to_partial_path".freeze
276
- when :to_model
277
- name = "to_model".freeze
278
- else
279
- name = name.to_s
280
- end
281
-
282
210
  # If the result is true then check for the select case.
283
211
  # For queries selecting a subset of columns, return false for unselected columns.
284
212
  # We check defined?(@attributes) not to issue warnings if called on objects that
285
213
  # have been allocated but not yet initialized.
286
- if defined?(@attributes) && self.class.column_names.include?(name)
287
- return has_attribute?(name)
214
+ if defined?(@attributes)
215
+ if name = self.class.symbol_column_to_string(name.to_sym)
216
+ return _has_attribute?(name)
217
+ end
288
218
  end
289
219
 
290
220
  true
@@ -293,14 +223,22 @@ module ActiveRecord
293
223
  # Returns +true+ if the given attribute is in the attributes hash, otherwise +false+.
294
224
  #
295
225
  # class Person < ActiveRecord::Base
226
+ # alias_attribute :new_name, :name
296
227
  # end
297
228
  #
298
229
  # person = Person.new
299
- # person.has_attribute?(:name) # => true
300
- # person.has_attribute?('age') # => true
301
- # person.has_attribute?(:nothing) # => false
230
+ # person.has_attribute?(:name) # => true
231
+ # person.has_attribute?(:new_name) # => true
232
+ # person.has_attribute?('age') # => true
233
+ # person.has_attribute?(:nothing) # => false
302
234
  def has_attribute?(attr_name)
303
- @attributes.key?(attr_name.to_s)
235
+ attr_name = attr_name.to_s
236
+ attr_name = self.class.attribute_aliases[attr_name] || attr_name
237
+ @attributes.key?(attr_name)
238
+ end
239
+
240
+ def _has_attribute?(attr_name) # :nodoc:
241
+ @attributes.key?(attr_name)
304
242
  end
305
243
 
306
244
  # Returns an array of names for the attributes available on this object.
@@ -329,9 +267,8 @@ module ActiveRecord
329
267
 
330
268
  # Returns an <tt>#inspect</tt>-like string for the value of the
331
269
  # attribute +attr_name+. String attributes are truncated up to 50
332
- # characters, Date and Time attributes are returned in the
333
- # <tt>:db</tt> format. Other attributes return the value of
334
- # <tt>#inspect</tt> without modification.
270
+ # characters. Other attributes return the value of <tt>#inspect</tt>
271
+ # without modification.
335
272
  #
336
273
  # person = Person.create!(name: 'David Heinemeier Hansson ' * 3)
337
274
  #
@@ -339,20 +276,15 @@ module ActiveRecord
339
276
  # # => "\"David Heinemeier Hansson David Heinemeier Hansson ...\""
340
277
  #
341
278
  # person.attribute_for_inspect(:created_at)
342
- # # => "\"2012-10-22 00:15:07\""
279
+ # # => "\"2012-10-22 00:15:07.000000000 +0000\""
343
280
  #
344
281
  # person.attribute_for_inspect(:tag_ids)
345
282
  # # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
346
283
  def attribute_for_inspect(attr_name)
347
- value = read_attribute(attr_name)
348
-
349
- if value.is_a?(String) && value.length > 50
350
- "#{value[0, 50]}...".inspect
351
- elsif value.is_a?(Date) || value.is_a?(Time)
352
- %("#{value.to_s(:db)}")
353
- else
354
- value.inspect
355
- end
284
+ attr_name = attr_name.to_s
285
+ attr_name = self.class.attribute_aliases[attr_name] || attr_name
286
+ value = _read_attribute(attr_name)
287
+ format_for_inspect(attr_name, value)
356
288
  end
357
289
 
358
290
  # Returns +true+ if the specified +attribute+ has been set by the user or by a
@@ -370,8 +302,10 @@ module ActiveRecord
370
302
  # task.is_done = true
371
303
  # task.attribute_present?(:title) # => true
372
304
  # task.attribute_present?(:is_done) # => true
373
- def attribute_present?(attribute)
374
- value = _read_attribute(attribute)
305
+ def attribute_present?(attr_name)
306
+ attr_name = attr_name.to_s
307
+ attr_name = self.class.attribute_aliases[attr_name] || attr_name
308
+ value = _read_attribute(attr_name)
375
309
  !value.nil? && !(value.respond_to?(:empty?) && value.empty?)
376
310
  end
377
311
 
@@ -443,50 +377,53 @@ module ActiveRecord
443
377
  @attributes.accessed
444
378
  end
445
379
 
446
- protected
447
-
448
- def attribute_method?(attr_name) # :nodoc:
380
+ private
381
+ def attribute_method?(attr_name)
449
382
  # We check defined? because Syck calls respond_to? before actually calling initialize.
450
383
  defined?(@attributes) && @attributes.key?(attr_name)
451
384
  end
452
385
 
453
- private
454
-
455
- def attributes_with_values_for_create(attribute_names)
456
- attributes_with_values(attributes_for_create(attribute_names))
457
- end
458
-
459
- def attributes_with_values_for_update(attribute_names)
460
- attributes_with_values(attributes_for_update(attribute_names))
461
- end
462
-
463
386
  def attributes_with_values(attribute_names)
464
- attribute_names.each_with_object({}) do |name, attrs|
465
- attrs[name] = _read_attribute(name)
466
- end
387
+ attribute_names.index_with { |name| @attributes[name] }
467
388
  end
468
389
 
469
- # Filters the primary keys and readonly attributes from the attribute names.
390
+ # Filters the primary keys, readonly attributes and virtual columns from the attribute names.
470
391
  def attributes_for_update(attribute_names)
471
- attribute_names.reject do |name|
472
- readonly_attribute?(name)
392
+ attribute_names &= self.class.column_names
393
+ attribute_names.delete_if do |name|
394
+ self.class.readonly_attribute?(name) ||
395
+ column_for_attribute(name).virtual?
473
396
  end
474
397
  end
475
398
 
476
- # Filters out the primary keys, from the attribute names, when the primary
399
+ # Filters out the virtual columns and also primary keys, from the attribute names, when the primary
477
400
  # key is to be generated (e.g. the id attribute has no value).
478
401
  def attributes_for_create(attribute_names)
479
- attribute_names.reject do |name|
480
- pk_attribute?(name) && id.nil?
402
+ attribute_names &= self.class.column_names
403
+ attribute_names.delete_if do |name|
404
+ (pk_attribute?(name) && id.nil?) ||
405
+ column_for_attribute(name).virtual?
481
406
  end
482
407
  end
483
408
 
484
- def readonly_attribute?(name)
485
- self.class.readonly_attributes.include?(name)
409
+ def format_for_inspect(name, value)
410
+ if value.nil?
411
+ value.inspect
412
+ else
413
+ inspected_value = if value.is_a?(String) && value.length > 50
414
+ "#{value[0, 50]}...".inspect
415
+ elsif value.is_a?(Date) || value.is_a?(Time)
416
+ %("#{value.to_fs(:inspect)}")
417
+ else
418
+ value.inspect
419
+ end
420
+
421
+ inspection_filter.filter_param(name, inspected_value)
422
+ end
486
423
  end
487
424
 
488
425
  def pk_attribute?(name)
489
- name == self.class.primary_key
426
+ name == @primary_key
490
427
  end
491
428
  end
492
429
  end
@@ -41,6 +41,9 @@ module ActiveRecord
41
41
  # +range+ (PostgreSQL only) specifies that the type should be a range (see the
42
42
  # examples below).
43
43
  #
44
+ # When using a symbol for +cast_type+, extra options are forwarded to the
45
+ # constructor of the type object.
46
+ #
44
47
  # ==== Examples
45
48
  #
46
49
  # The type detected by Active Record can be overridden.
@@ -112,6 +115,16 @@ module ActiveRecord
112
115
  # my_float_range: 1.0..3.5
113
116
  # }
114
117
  #
118
+ # Passing options to the type constructor
119
+ #
120
+ # # app/models/my_model.rb
121
+ # class MyModel < ActiveRecord::Base
122
+ # attribute :small_int, :integer, limit: 2
123
+ # end
124
+ #
125
+ # MyModel.create(small_int: 65537)
126
+ # # => Error: 65537 is out of range for the limit of two bytes
127
+ #
115
128
  # ==== Creating Custom Types
116
129
  #
117
130
  # Users may also define their own custom types, as long as they respond
@@ -157,7 +170,7 @@ module ActiveRecord
157
170
  # class Money < Struct.new(:amount, :currency)
158
171
  # end
159
172
  #
160
- # class MoneyType < Type::Value
173
+ # class MoneyType < ActiveRecord::Type::Value
161
174
  # def initialize(currency_converter:)
162
175
  # @currency_converter = currency_converter
163
176
  # end
@@ -192,14 +205,31 @@ module ActiveRecord
192
205
  # tracking is performed. The methods +changed?+ and +changed_in_place?+
193
206
  # will be called from ActiveModel::Dirty. See the documentation for those
194
207
  # methods in ActiveModel::Type::Value for more details.
195
- def attribute(name, cast_type = Type::Value.new, **options)
208
+ def attribute(name, cast_type = nil, default: NO_DEFAULT_PROVIDED, **options)
196
209
  name = name.to_s
210
+ name = attribute_aliases[name] || name
211
+
197
212
  reload_schema_from_cache
198
213
 
214
+ case cast_type
215
+ when Symbol
216
+ cast_type = Type.lookup(cast_type, **options, adapter: Type.adapter_name_from(self))
217
+ when nil
218
+ if (prev_cast_type, prev_default = attributes_to_define_after_schema_loads[name])
219
+ default = prev_default if default == NO_DEFAULT_PROVIDED
220
+ else
221
+ prev_cast_type = -> subtype { subtype }
222
+ end
223
+
224
+ cast_type = if block_given?
225
+ -> subtype { yield Proc === prev_cast_type ? prev_cast_type[subtype] : prev_cast_type }
226
+ else
227
+ prev_cast_type
228
+ end
229
+ end
230
+
199
231
  self.attributes_to_define_after_schema_loads =
200
- attributes_to_define_after_schema_loads.merge(
201
- name => [cast_type, options]
202
- )
232
+ attributes_to_define_after_schema_loads.merge(name => [cast_type, default])
203
233
  end
204
234
 
205
235
  # This is the low level API which sits beneath +attribute+. It only
@@ -232,17 +262,13 @@ module ActiveRecord
232
262
 
233
263
  def load_schema! # :nodoc:
234
264
  super
235
- attributes_to_define_after_schema_loads.each do |name, (type, options)|
236
- if type.is_a?(Symbol)
237
- type = ActiveRecord::Type.lookup(type, **options.except(:default))
238
- end
239
-
240
- define_attribute(name, type, **options.slice(:default))
265
+ attributes_to_define_after_schema_loads.each do |name, (cast_type, default)|
266
+ cast_type = cast_type[type_for_attribute(name)] if Proc === cast_type
267
+ define_attribute(name, cast_type, default: default)
241
268
  end
242
269
  end
243
270
 
244
271
  private
245
-
246
272
  NO_DEFAULT_PROVIDED = Object.new # :nodoc:
247
273
  private_constant :NO_DEFAULT_PROVIDED
248
274