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
@@ -56,54 +56,60 @@ module ActiveRecord
56
56
  def touch_attributes_with_time(*names, time: nil)
57
57
  attribute_names = timestamp_attributes_for_update_in_model
58
58
  attribute_names |= names.map(&:to_s)
59
- time ||= current_time_from_proper_timezone
60
- attribute_names.each_with_object({}) { |attr_name, result| result[attr_name] = time }
59
+ attribute_names.index_with(time || current_time_from_proper_timezone)
61
60
  end
62
61
 
63
- private
64
- def timestamp_attributes_for_create_in_model
65
- timestamp_attributes_for_create.select { |c| column_names.include?(c) }
66
- end
62
+ def timestamp_attributes_for_create_in_model
63
+ @timestamp_attributes_for_create_in_model ||=
64
+ (timestamp_attributes_for_create & column_names).freeze
65
+ end
67
66
 
68
- def timestamp_attributes_for_update_in_model
69
- timestamp_attributes_for_update.select { |c| column_names.include?(c) }
70
- end
67
+ def timestamp_attributes_for_update_in_model
68
+ @timestamp_attributes_for_update_in_model ||=
69
+ (timestamp_attributes_for_update & column_names).freeze
70
+ end
71
71
 
72
- def all_timestamp_attributes_in_model
73
- timestamp_attributes_for_create_in_model + timestamp_attributes_for_update_in_model
74
- end
72
+ def all_timestamp_attributes_in_model
73
+ @all_timestamp_attributes_in_model ||=
74
+ (timestamp_attributes_for_create_in_model + timestamp_attributes_for_update_in_model).freeze
75
+ end
76
+
77
+ def current_time_from_proper_timezone
78
+ ActiveRecord.default_timezone == :utc ? Time.now.utc : Time.now
79
+ end
75
80
 
81
+ private
76
82
  def timestamp_attributes_for_create
77
- ["created_at", "created_on"]
83
+ ["created_at", "created_on"].map! { |name| attribute_aliases[name] || name }
78
84
  end
79
85
 
80
86
  def timestamp_attributes_for_update
81
- ["updated_at", "updated_on"]
87
+ ["updated_at", "updated_on"].map! { |name| attribute_aliases[name] || name }
82
88
  end
83
89
 
84
- def current_time_from_proper_timezone
85
- default_timezone == :utc ? Time.now.utc : Time.now
90
+ def reload_schema_from_cache
91
+ @timestamp_attributes_for_create_in_model = nil
92
+ @timestamp_attributes_for_update_in_model = nil
93
+ @all_timestamp_attributes_in_model = nil
94
+ super
86
95
  end
87
96
  end
88
97
 
89
98
  private
90
-
91
99
  def _create_record
92
100
  if record_timestamps
93
101
  current_time = current_time_from_proper_timezone
94
102
 
95
103
  all_timestamp_attributes_in_model.each do |column|
96
- if !attribute_present?(column)
97
- _write_attribute(column, current_time)
98
- end
104
+ _write_attribute(column, current_time) unless _read_attribute(column)
99
105
  end
100
106
  end
101
107
 
102
108
  super
103
109
  end
104
110
 
105
- def _update_record(*args, touch: true, **options)
106
- if touch && should_record_timestamps?
111
+ def _update_record
112
+ if @_touch_record && should_record_timestamps?
107
113
  current_time = current_time_from_proper_timezone
108
114
 
109
115
  timestamp_attributes_for_update_in_model.each do |column|
@@ -111,34 +117,38 @@ module ActiveRecord
111
117
  _write_attribute(column, current_time)
112
118
  end
113
119
  end
114
- super(*args)
120
+
121
+ super
122
+ end
123
+
124
+ def create_or_update(touch: true, **)
125
+ @_touch_record = touch
126
+ super
115
127
  end
116
128
 
117
129
  def should_record_timestamps?
118
- record_timestamps && (!partial_writes? || has_changes_to_save?)
130
+ record_timestamps && (!partial_updates? || has_changes_to_save?)
119
131
  end
120
132
 
121
133
  def timestamp_attributes_for_create_in_model
122
- self.class.send(:timestamp_attributes_for_create_in_model)
134
+ self.class.timestamp_attributes_for_create_in_model
123
135
  end
124
136
 
125
137
  def timestamp_attributes_for_update_in_model
126
- self.class.send(:timestamp_attributes_for_update_in_model)
138
+ self.class.timestamp_attributes_for_update_in_model
127
139
  end
128
140
 
129
141
  def all_timestamp_attributes_in_model
130
- self.class.send(:all_timestamp_attributes_in_model)
142
+ self.class.all_timestamp_attributes_in_model
131
143
  end
132
144
 
133
145
  def current_time_from_proper_timezone
134
- self.class.send(:current_time_from_proper_timezone)
146
+ self.class.current_time_from_proper_timezone
135
147
  end
136
148
 
137
- def max_updated_column_timestamp(timestamp_names = timestamp_attributes_for_update_in_model)
138
- timestamp_names
139
- .map { |attr| self[attr] }
140
- .compact
141
- .map(&:to_time)
149
+ def max_updated_column_timestamp
150
+ timestamp_attributes_for_update_in_model
151
+ .filter_map { |attr| self[attr]&.to_time }
142
152
  .max
143
153
  end
144
154
 
@@ -146,7 +156,7 @@ module ActiveRecord
146
156
  def clear_timestamp_attributes
147
157
  all_timestamp_attributes_in_model.each do |attribute_name|
148
158
  self[attribute_name] = nil
149
- clear_attribute_changes([attribute_name])
159
+ clear_attribute_change(attribute_name)
150
160
  end
151
161
  end
152
162
  end
@@ -2,27 +2,26 @@
2
2
 
3
3
  module ActiveRecord
4
4
  # = Active Record Touch Later
5
- module TouchLater
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- before_commit_without_transaction_enrollment :touch_deferred_attributes
5
+ module TouchLater # :nodoc:
6
+ def before_committed!
7
+ touch_deferred_attributes if has_defer_touch_attrs? && persisted?
8
+ super
10
9
  end
11
10
 
12
11
  def touch_later(*names) # :nodoc:
13
- unless persisted?
14
- raise ActiveRecordError, <<-MSG.squish
15
- cannot touch on a new or destroyed record object. Consider using
16
- persisted?, new_record?, or destroyed? before touching
17
- MSG
18
- end
12
+ _raise_record_not_touched_error unless persisted?
19
13
 
20
14
  @_defer_touch_attrs ||= timestamp_attributes_for_update_in_model
21
- @_defer_touch_attrs |= names
15
+ @_defer_touch_attrs |= names.map! do |name|
16
+ name = name.to_s
17
+ self.class.attribute_aliases[name] || name
18
+ end unless names.empty?
19
+
22
20
  @_touch_time = current_time_from_proper_timezone
23
21
 
24
22
  surreptitiously_touch @_defer_touch_attrs
25
- self.class.connection.add_transaction_record self
23
+ add_to_transaction
24
+ @_new_record_before_last_commit ||= false
26
25
 
27
26
  # touch the parents as we are not calling the after_save callbacks
28
27
  self.class.reflect_on_all_associations(:belongs_to).each do |r|
@@ -35,22 +34,24 @@ module ActiveRecord
35
34
  def touch(*names, time: nil) # :nodoc:
36
35
  if has_defer_touch_attrs?
37
36
  names |= @_defer_touch_attrs
37
+ super(*names, time: time)
38
+ @_defer_touch_attrs, @_touch_time = nil, nil
39
+ else
40
+ super
38
41
  end
39
- super(*names, time: time)
40
42
  end
41
43
 
42
44
  private
43
-
44
- def surreptitiously_touch(attrs)
45
- attrs.each { |attr| write_attribute attr, @_touch_time }
46
- clear_attribute_changes attrs
45
+ def surreptitiously_touch(attr_names)
46
+ attr_names.each do |attr_name|
47
+ _write_attribute(attr_name, @_touch_time)
48
+ clear_attribute_change(attr_name)
49
+ end
47
50
  end
48
51
 
49
52
  def touch_deferred_attributes
50
- if has_defer_touch_attrs? && persisted?
51
- touch(*@_defer_touch_attrs, time: @_touch_time)
52
- @_defer_touch_attrs, @_touch_time = nil, nil
53
- end
53
+ @_skip_dirty_tracking = true
54
+ touch(time: @_touch_time)
54
55
  end
55
56
 
56
57
  def has_defer_touch_attrs?
@@ -4,15 +4,12 @@ module ActiveRecord
4
4
  # See ActiveRecord::Transactions::ClassMethods for documentation.
5
5
  module Transactions
6
6
  extend ActiveSupport::Concern
7
- #:nodoc:
7
+ # :nodoc:
8
8
  ACTIONS = [:create, :destroy, :update]
9
9
 
10
10
  included do
11
11
  define_callbacks :commit, :rollback,
12
12
  :before_commit,
13
- :before_commit_without_transaction_enrollment,
14
- :commit_without_transaction_enrollment,
15
- :rollback_without_transaction_enrollment,
16
13
  scope: [:kind, :name]
17
14
  end
18
15
 
@@ -164,13 +161,13 @@ module ActiveRecord
164
161
  # end
165
162
  # end
166
163
  #
167
- # only "Kotori" is created. This works on MySQL and PostgreSQL. SQLite3 version >= '3.6.8' also supports it.
164
+ # only "Kotori" is created.
168
165
  #
169
166
  # Most databases don't support true nested transactions. At the time of
170
167
  # writing, the only database that we're aware of that supports true nested
171
168
  # transactions, is MS-SQL. Because of this, Active Record emulates nested
172
- # transactions by using savepoints on MySQL and PostgreSQL. See
173
- # https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
169
+ # transactions by using savepoints. See
170
+ # https://dev.mysql.com/doc/refman/en/savepoint.html
174
171
  # for more information about savepoints.
175
172
  #
176
173
  # === \Callbacks
@@ -208,8 +205,8 @@ module ActiveRecord
208
205
  # Note that "TRUNCATE" is also a MySQL DDL statement!
209
206
  module ClassMethods
210
207
  # See the ConnectionAdapters::DatabaseStatements#transaction API docs.
211
- def transaction(options = {}, &block)
212
- connection.transaction(options, &block)
208
+ def transaction(**options, &block)
209
+ connection.transaction(**options, &block)
213
210
  end
214
211
 
215
212
  def before_commit(*args, &block) # :nodoc:
@@ -234,6 +231,12 @@ module ActiveRecord
234
231
  set_callback(:commit, :after, *args, &block)
235
232
  end
236
233
 
234
+ # Shortcut for <tt>after_commit :hook, on: [ :create, :update ]</tt>.
235
+ def after_save_commit(*args, &block)
236
+ set_options_for_callbacks!(args, on: [ :create, :update ])
237
+ set_callback(:commit, :after, *args, &block)
238
+ end
239
+
237
240
  # Shortcut for <tt>after_commit :hook, on: :create</tt>.
238
241
  def after_create_commit(*args, &block)
239
242
  set_options_for_callbacks!(args, on: :create)
@@ -260,23 +263,7 @@ module ActiveRecord
260
263
  set_callback(:rollback, :after, *args, &block)
261
264
  end
262
265
 
263
- def before_commit_without_transaction_enrollment(*args, &block) # :nodoc:
264
- set_options_for_callbacks!(args)
265
- set_callback(:before_commit_without_transaction_enrollment, :before, *args, &block)
266
- end
267
-
268
- def after_commit_without_transaction_enrollment(*args, &block) # :nodoc:
269
- set_options_for_callbacks!(args)
270
- set_callback(:commit_without_transaction_enrollment, :after, *args, &block)
271
- end
272
-
273
- def after_rollback_without_transaction_enrollment(*args, &block) # :nodoc:
274
- set_options_for_callbacks!(args)
275
- set_callback(:rollback_without_transaction_enrollment, :after, *args, &block)
276
- end
277
-
278
266
  private
279
-
280
267
  def set_options_for_callbacks!(args, enforced_options = {})
281
268
  options = args.extract_options!.merge!(enforced_options)
282
269
  args << options
@@ -284,8 +271,10 @@ module ActiveRecord
284
271
  if options[:on]
285
272
  fire_on = Array(options[:on])
286
273
  assert_valid_transaction_action(fire_on)
287
- options[:if] = Array(options[:if])
288
- options[:if].unshift(-> { transaction_include_any_action?(fire_on) })
274
+ options[:if] = [
275
+ -> { transaction_include_any_action?(fire_on) },
276
+ *options[:if]
277
+ ]
289
278
  end
290
279
  end
291
280
 
@@ -297,41 +286,27 @@ module ActiveRecord
297
286
  end
298
287
 
299
288
  # See ActiveRecord::Transactions::ClassMethods for detailed documentation.
300
- def transaction(options = {}, &block)
301
- self.class.transaction(options, &block)
289
+ def transaction(**options, &block)
290
+ self.class.transaction(**options, &block)
302
291
  end
303
292
 
304
- def destroy #:nodoc:
293
+ def destroy # :nodoc:
305
294
  with_transaction_returning_status { super }
306
295
  end
307
296
 
308
- def save(*) #:nodoc:
309
- rollback_active_record_state! do
310
- with_transaction_returning_status { super }
311
- end
312
- end
313
-
314
- def save!(*) #:nodoc:
297
+ def save(**) # :nodoc:
315
298
  with_transaction_returning_status { super }
316
299
  end
317
300
 
318
- def touch(*) #:nodoc:
301
+ def save!(**) # :nodoc:
319
302
  with_transaction_returning_status { super }
320
303
  end
321
304
 
322
- # Reset id and @new_record if the transaction rolls back.
323
- def rollback_active_record_state!
324
- remember_transaction_record_state
325
- yield
326
- rescue Exception
327
- restore_transaction_record_state
328
- raise
329
- ensure
330
- clear_transaction_record_state
305
+ def touch(*, **) # :nodoc:
306
+ with_transaction_returning_status { super }
331
307
  end
332
308
 
333
309
  def before_committed! # :nodoc:
334
- _run_before_commit_without_transaction_enrollment_callbacks
335
310
  _run_before_commit_callbacks
336
311
  end
337
312
 
@@ -339,39 +314,26 @@ module ActiveRecord
339
314
  #
340
315
  # Ensure that it is not called if the object was never persisted (failed create),
341
316
  # but call it after the commit of a destroyed object.
342
- def committed!(should_run_callbacks: true) #:nodoc:
343
- force_clear_transaction_record_state
344
- if should_run_callbacks && (destroyed? || persisted?)
317
+ def committed!(should_run_callbacks: true) # :nodoc:
318
+ @_start_transaction_state = nil
319
+ if should_run_callbacks
345
320
  @_committed_already_called = true
346
- _run_commit_without_transaction_enrollment_callbacks
347
321
  _run_commit_callbacks
348
322
  end
349
323
  ensure
350
- @_committed_already_called = false
324
+ @_committed_already_called = @_trigger_update_callback = @_trigger_destroy_callback = false
351
325
  end
352
326
 
353
327
  # Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record
354
328
  # state should be rolled back to the beginning or just to the last savepoint.
355
- def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
329
+ def rolledback!(force_restore_state: false, should_run_callbacks: true) # :nodoc:
356
330
  if should_run_callbacks
357
331
  _run_rollback_callbacks
358
- _run_rollback_without_transaction_enrollment_callbacks
359
332
  end
360
333
  ensure
361
334
  restore_transaction_record_state(force_restore_state)
362
335
  clear_transaction_record_state
363
- end
364
-
365
- # Add the record to the current transaction so that the #after_rollback and #after_commit callbacks
366
- # can be called.
367
- def add_to_transaction
368
- if has_transactional_callbacks?
369
- self.class.connection.add_transaction_record(self)
370
- else
371
- sync_with_transaction_state
372
- set_transaction_state(self.class.connection.transaction_state)
373
- end
374
- remember_transaction_record_state
336
+ @_trigger_update_callback = @_trigger_destroy_callback = false if force_restore_state
375
337
  end
376
338
 
377
339
  # Executes +method+ within a transaction and captures its return value as a
@@ -382,36 +344,40 @@ module ActiveRecord
382
344
  # instance.
383
345
  def with_transaction_returning_status
384
346
  status = nil
385
- self.class.transaction do
386
- add_to_transaction
347
+ connection = self.class.connection
348
+ ensure_finalize = !connection.transaction_open?
349
+
350
+ connection.transaction do
351
+ add_to_transaction(ensure_finalize || has_transactional_callbacks?)
352
+ remember_transaction_record_state
353
+
387
354
  status = yield
388
355
  raise ActiveRecord::Rollback unless status
389
356
  end
390
357
  status
391
- ensure
392
- if @transaction_state && @transaction_state.committed?
393
- clear_transaction_record_state
394
- end
395
358
  end
396
359
 
397
- protected
398
- attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
360
+ def trigger_transactional_callbacks? # :nodoc:
361
+ (@_new_record_before_last_commit || _trigger_update_callback) && persisted? ||
362
+ _trigger_destroy_callback && destroyed?
363
+ end
399
364
 
400
365
  private
366
+ attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
401
367
 
402
368
  # Save the new record state and id of a record so it can be restored later if a transaction fails.
403
369
  def remember_transaction_record_state
404
- @_start_transaction_state.reverse_merge!(
370
+ @_start_transaction_state ||= {
405
371
  id: id,
406
372
  new_record: @new_record,
373
+ previously_new_record: @previously_new_record,
407
374
  destroyed: @destroyed,
375
+ attributes: @attributes,
408
376
  frozen?: frozen?,
409
- )
410
- @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
411
- remember_new_record_before_last_commit
412
- end
377
+ level: 0
378
+ }
379
+ @_start_transaction_state[:level] += 1
413
380
 
414
- def remember_new_record_before_last_commit
415
381
  if _committed_already_called
416
382
  @_new_record_before_last_commit = false
417
383
  else
@@ -421,27 +387,27 @@ module ActiveRecord
421
387
 
422
388
  # Clear the new record state and id of a record.
423
389
  def clear_transaction_record_state
424
- @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
425
- force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
426
- end
427
-
428
- # Force to clear the transaction record state.
429
- def force_clear_transaction_record_state
430
- @_start_transaction_state.clear
390
+ return unless @_start_transaction_state
391
+ @_start_transaction_state[:level] -= 1
392
+ @_start_transaction_state = nil if @_start_transaction_state[:level] < 1
431
393
  end
432
394
 
433
395
  # Restore the new record state and id of a record that was previously saved by a call to save_record_state.
434
- def restore_transaction_record_state(force = false)
435
- unless @_start_transaction_state.empty?
436
- transaction_level = (@_start_transaction_state[:level] || 0) - 1
437
- if transaction_level < 1 || force
438
- restore_state = @_start_transaction_state
439
- thaw
396
+ def restore_transaction_record_state(force_restore_state = false)
397
+ if restore_state = @_start_transaction_state
398
+ if force_restore_state || restore_state[:level] <= 1
440
399
  @new_record = restore_state[:new_record]
400
+ @previously_new_record = restore_state[:previously_new_record]
441
401
  @destroyed = restore_state[:destroyed]
442
- pk = self.class.primary_key
443
- if pk && _read_attribute(pk) != restore_state[:id]
444
- _write_attribute(pk, restore_state[:id])
402
+ @attributes = restore_state[:attributes].map do |attr|
403
+ value = @attributes.fetch_value(attr.name)
404
+ attr = attr.with_value_from_user(value) if attr.value != value
405
+ attr
406
+ end
407
+ @mutations_from_database = nil
408
+ @mutations_before_last_save = nil
409
+ if @attributes.fetch_value(@primary_key) != restore_state[:id]
410
+ @attributes.write_from_user(@primary_key, restore_state[:id])
445
411
  end
446
412
  freeze if restore_state[:frozen?]
447
413
  end
@@ -462,41 +428,14 @@ module ActiveRecord
462
428
  end
463
429
  end
464
430
 
465
- def set_transaction_state(state)
466
- @transaction_state = state
431
+ # Add the record to the current transaction so that the #after_rollback and #after_commit
432
+ # callbacks can be called.
433
+ def add_to_transaction(ensure_finalize = true)
434
+ self.class.connection.add_transaction_record(self, ensure_finalize)
467
435
  end
468
436
 
469
437
  def has_transactional_callbacks?
470
438
  !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
471
439
  end
472
-
473
- # Updates the attributes on this particular Active Record object so that
474
- # if it's associated with a transaction, then the state of the Active Record
475
- # object will be updated to reflect the current state of the transaction.
476
- #
477
- # The <tt>@transaction_state</tt> variable stores the states of the associated
478
- # transaction. This relies on the fact that a transaction can only be in
479
- # one rollback or commit (otherwise a list of states would be required).
480
- # Each Active Record object inside of a transaction carries that transaction's
481
- # TransactionState.
482
- #
483
- # This method checks to see if the ActiveRecord object's state reflects
484
- # the TransactionState, and rolls back or commits the Active Record object
485
- # as appropriate.
486
- #
487
- # Since Active Record objects can be inside multiple transactions, this
488
- # method recursively goes through the parent of the TransactionState and
489
- # checks if the Active Record object reflects the state of the object.
490
- def sync_with_transaction_state
491
- update_attributes_from_transaction_state(@transaction_state)
492
- end
493
-
494
- def update_attributes_from_transaction_state(transaction_state)
495
- if transaction_state && transaction_state.finalized?
496
- restore_transaction_record_state(transaction_state.fully_rolledback?) if transaction_state.rolledback?
497
- force_clear_transaction_record_state if transaction_state.fully_committed?
498
- clear_transaction_record_state if transaction_state.fully_completed?
499
- end
500
- end
501
440
  end
502
441
  end
@@ -5,19 +5,19 @@ module ActiveRecord
5
5
  include ActiveModel::Translation
6
6
 
7
7
  # Set the lookup ancestors for ActiveModel.
8
- def lookup_ancestors #:nodoc:
8
+ def lookup_ancestors # :nodoc:
9
9
  klass = self
10
10
  classes = [klass]
11
11
  return classes if klass == ActiveRecord::Base
12
12
 
13
- while klass != klass.base_class
13
+ while !klass.base_class?
14
14
  classes << klass = klass.superclass
15
15
  end
16
16
  classes
17
17
  end
18
18
 
19
19
  # Set the i18n scope to overwrite ActiveModel.
20
- def i18n_scope #:nodoc:
20
+ def i18n_scope # :nodoc:
21
21
  :activerecord
22
22
  end
23
23
  end
@@ -5,25 +5,49 @@ require "active_model/type/registry"
5
5
  module ActiveRecord
6
6
  # :stopdoc:
7
7
  module Type
8
- class AdapterSpecificRegistry < ActiveModel::Type::Registry
8
+ class AdapterSpecificRegistry # :nodoc:
9
+ def initialize
10
+ @registrations = []
11
+ end
12
+
13
+ def initialize_copy(other)
14
+ @registrations = @registrations.dup
15
+ super
16
+ end
17
+
9
18
  def add_modifier(options, klass, **args)
10
19
  registrations << DecorationRegistration.new(options, klass, **args)
11
20
  end
12
21
 
13
- private
22
+ def register(type_name, klass = nil, **options, &block)
23
+ unless block_given?
24
+ block = proc { |_, *args| klass.new(*args) }
25
+ block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
26
+ end
27
+ registrations << Registration.new(type_name, block, **options)
28
+ end
29
+
30
+ def lookup(symbol, *args, **kwargs)
31
+ registration = find_registration(symbol, *args, **kwargs)
14
32
 
15
- def registration_klass
16
- Registration
33
+ if registration
34
+ registration.call(self, symbol, *args, **kwargs)
35
+ else
36
+ raise ArgumentError, "Unknown type #{symbol.inspect}"
17
37
  end
38
+ end
18
39
 
19
- def find_registration(symbol, *args)
40
+ private
41
+ attr_reader :registrations
42
+
43
+ def find_registration(symbol, *args, **kwargs)
20
44
  registrations
21
- .select { |registration| registration.matches?(symbol, *args) }
45
+ .select { |registration| registration.matches?(symbol, *args, **kwargs) }
22
46
  .max
23
47
  end
24
48
  end
25
49
 
26
- class Registration
50
+ class Registration # :nodoc:
27
51
  def initialize(name, block, adapter: nil, override: nil)
28
52
  @name = name
29
53
  @block = block
@@ -52,10 +76,7 @@ module ActiveRecord
52
76
  priority <=> other.priority
53
77
  end
54
78
 
55
- # TODO Change this to private once we've dropped Ruby 2.2 support.
56
- # Workaround for Ruby 2.2 "private attribute?" warning.
57
79
  protected
58
-
59
80
  attr_reader :name, :block, :adapter, :override
60
81
 
61
82
  def priority
@@ -74,7 +95,6 @@ module ActiveRecord
74
95
  end
75
96
 
76
97
  private
77
-
78
98
  def matches_adapter?(adapter: nil, **)
79
99
  (self.adapter.nil? || adapter == self.adapter)
80
100
  end
@@ -94,7 +114,7 @@ module ActiveRecord
94
114
  end
95
115
  end
96
116
 
97
- class DecorationRegistration < Registration
117
+ class DecorationRegistration < Registration # :nodoc:
98
118
  def initialize(options, klass, adapter: nil)
99
119
  @options = options
100
120
  @klass = klass
@@ -114,13 +134,8 @@ module ActiveRecord
114
134
  super | 4
115
135
  end
116
136
 
117
- # TODO Change this to private once we've dropped Ruby 2.2 support.
118
- # Workaround for Ruby 2.2 "private attribute?" warning.
119
- protected
120
-
121
- attr_reader :options, :klass
122
-
123
137
  private
138
+ attr_reader :options, :klass
124
139
 
125
140
  def matches_options?(**kwargs)
126
141
  options.all? do |key, value|
@@ -130,7 +145,7 @@ module ActiveRecord
130
145
  end
131
146
  end
132
147
 
133
- class TypeConflictError < StandardError
148
+ class TypeConflictError < StandardError # :nodoc:
134
149
  end
135
150
  # :startdoc:
136
151
  end