activerecord 5.0.7.2 → 6.1.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 (363) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +829 -2015
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +11 -9
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record.rb +37 -29
  8. data/lib/active_record/aggregations.rb +249 -247
  9. data/lib/active_record/association_relation.rb +30 -18
  10. data/lib/active_record/associations.rb +1714 -1596
  11. data/lib/active_record/associations/alias_tracker.rb +36 -42
  12. data/lib/active_record/associations/association.rb +143 -68
  13. data/lib/active_record/associations/association_scope.rb +98 -94
  14. data/lib/active_record/associations/belongs_to_association.rb +76 -46
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  16. data/lib/active_record/associations/builder/association.rb +27 -28
  17. data/lib/active_record/associations/builder/belongs_to.rb +52 -60
  18. data/lib/active_record/associations/builder/collection_association.rb +12 -22
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +40 -62
  20. data/lib/active_record/associations/builder/has_many.rb +10 -2
  21. data/lib/active_record/associations/builder/has_one.rb +35 -2
  22. data/lib/active_record/associations/builder/singular_association.rb +5 -1
  23. data/lib/active_record/associations/collection_association.rb +104 -259
  24. data/lib/active_record/associations/collection_proxy.rb +169 -125
  25. data/lib/active_record/associations/foreign_association.rb +22 -0
  26. data/lib/active_record/associations/has_many_association.rb +46 -31
  27. data/lib/active_record/associations/has_many_through_association.rb +66 -46
  28. data/lib/active_record/associations/has_one_association.rb +71 -52
  29. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  30. data/lib/active_record/associations/join_dependency.rb +169 -180
  31. data/lib/active_record/associations/join_dependency/join_association.rb +53 -79
  32. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  33. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  34. data/lib/active_record/associations/preloader.rb +97 -104
  35. data/lib/active_record/associations/preloader/association.rb +109 -97
  36. data/lib/active_record/associations/preloader/through_association.rb +77 -76
  37. data/lib/active_record/associations/singular_association.rb +12 -45
  38. data/lib/active_record/associations/through_association.rb +27 -15
  39. data/lib/active_record/attribute_assignment.rb +55 -60
  40. data/lib/active_record/attribute_methods.rb +111 -141
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -9
  42. data/lib/active_record/attribute_methods/dirty.rb +172 -112
  43. data/lib/active_record/attribute_methods/primary_key.rb +88 -91
  44. data/lib/active_record/attribute_methods/query.rb +6 -8
  45. data/lib/active_record/attribute_methods/read.rb +18 -50
  46. data/lib/active_record/attribute_methods/serialization.rb +38 -10
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -66
  48. data/lib/active_record/attribute_methods/write.rb +25 -32
  49. data/lib/active_record/attributes.rb +69 -31
  50. data/lib/active_record/autosave_association.rb +102 -66
  51. data/lib/active_record/base.rb +16 -25
  52. data/lib/active_record/callbacks.rb +202 -43
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +11 -12
  55. data/lib/active_record/connection_adapters.rb +50 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +661 -375
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +14 -38
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +269 -105
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +54 -35
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +137 -93
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +155 -113
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -162
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +591 -259
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +229 -91
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +392 -244
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +457 -582
  69. data/lib/active_record/connection_adapters/column.rb +55 -13
  70. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  71. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +135 -49
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +79 -49
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +66 -56
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +20 -12
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +74 -37
  82. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  83. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  84. data/lib/active_record/connection_adapters/postgresql/column.rb +39 -28
  85. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +70 -101
  86. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  87. data/lib/active_record/connection_adapters/postgresql/oid.rb +26 -21
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  90. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -6
  93. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -4
  95. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  96. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
  98. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  104. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
  106. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
  107. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  109. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  110. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  112. data/lib/active_record/connection_adapters/postgresql/quoting.rb +98 -38
  113. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +21 -27
  114. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  116. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
  117. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +426 -324
  118. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +32 -23
  119. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
  120. data/lib/active_record/connection_adapters/postgresql_adapter.rb +418 -293
  121. data/lib/active_record/connection_adapters/schema_cache.rb +135 -18
  122. data/lib/active_record/connection_adapters/sql_type_metadata.rb +22 -7
  123. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
  124. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  125. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
  126. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -6
  127. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  128. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  129. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  130. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +282 -290
  131. data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
  132. data/lib/active_record/connection_handling.rb +287 -45
  133. data/lib/active_record/core.rb +385 -181
  134. data/lib/active_record/counter_cache.rb +60 -28
  135. data/lib/active_record/database_configurations.rb +272 -0
  136. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  137. data/lib/active_record/database_configurations/database_config.rb +80 -0
  138. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  139. data/lib/active_record/database_configurations/url_config.rb +53 -0
  140. data/lib/active_record/delegated_type.rb +209 -0
  141. data/lib/active_record/destroy_association_async_job.rb +36 -0
  142. data/lib/active_record/dynamic_matchers.rb +87 -87
  143. data/lib/active_record/enum.rb +122 -47
  144. data/lib/active_record/errors.rb +153 -22
  145. data/lib/active_record/explain.rb +13 -8
  146. data/lib/active_record/explain_registry.rb +3 -1
  147. data/lib/active_record/explain_subscriber.rb +9 -4
  148. data/lib/active_record/fixture_set/file.rb +20 -22
  149. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  150. data/lib/active_record/fixture_set/render_context.rb +17 -0
  151. data/lib/active_record/fixture_set/table_row.rb +152 -0
  152. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  153. data/lib/active_record/fixtures.rb +246 -507
  154. data/lib/active_record/gem_version.rb +6 -4
  155. data/lib/active_record/inheritance.rb +168 -95
  156. data/lib/active_record/insert_all.rb +208 -0
  157. data/lib/active_record/integration.rb +114 -25
  158. data/lib/active_record/internal_metadata.rb +30 -24
  159. data/lib/active_record/legacy_yaml_adapter.rb +11 -5
  160. data/lib/active_record/locking/optimistic.rb +81 -85
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +68 -31
  163. data/lib/active_record/middleware/database_selector.rb +77 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  166. data/lib/active_record/migration.rb +439 -342
  167. data/lib/active_record/migration/command_recorder.rb +152 -98
  168. data/lib/active_record/migration/compatibility.rb +229 -60
  169. data/lib/active_record/migration/join_table.rb +8 -7
  170. data/lib/active_record/model_schema.rb +230 -122
  171. data/lib/active_record/nested_attributes.rb +213 -203
  172. data/lib/active_record/no_touching.rb +11 -2
  173. data/lib/active_record/null_relation.rb +12 -34
  174. data/lib/active_record/persistence.rb +471 -97
  175. data/lib/active_record/query_cache.rb +23 -12
  176. data/lib/active_record/querying.rb +43 -25
  177. data/lib/active_record/railtie.rb +155 -43
  178. data/lib/active_record/railties/console_sandbox.rb +2 -0
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +507 -195
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +245 -269
  183. data/lib/active_record/relation.rb +475 -324
  184. data/lib/active_record/relation/batches.rb +125 -72
  185. data/lib/active_record/relation/batches/batch_enumerator.rb +28 -10
  186. data/lib/active_record/relation/calculations.rb +267 -171
  187. data/lib/active_record/relation/delegation.rb +73 -69
  188. data/lib/active_record/relation/finder_methods.rb +238 -248
  189. data/lib/active_record/relation/from_clause.rb +7 -9
  190. data/lib/active_record/relation/merger.rb +95 -77
  191. data/lib/active_record/relation/predicate_builder.rb +109 -110
  192. data/lib/active_record/relation/predicate_builder/array_handler.rb +22 -17
  193. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  194. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  195. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +55 -0
  196. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  197. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  198. data/lib/active_record/relation/query_attribute.rb +33 -2
  199. data/lib/active_record/relation/query_methods.rb +654 -374
  200. data/lib/active_record/relation/record_fetch_warning.rb +8 -6
  201. data/lib/active_record/relation/spawn_methods.rb +15 -14
  202. data/lib/active_record/relation/where_clause.rb +171 -109
  203. data/lib/active_record/result.rb +88 -51
  204. data/lib/active_record/runtime_registry.rb +5 -3
  205. data/lib/active_record/sanitization.rb +73 -100
  206. data/lib/active_record/schema.rb +7 -14
  207. data/lib/active_record/schema_dumper.rb +101 -69
  208. data/lib/active_record/schema_migration.rb +16 -12
  209. data/lib/active_record/scoping.rb +20 -20
  210. data/lib/active_record/scoping/default.rb +92 -95
  211. data/lib/active_record/scoping/named.rb +39 -30
  212. data/lib/active_record/secure_token.rb +19 -9
  213. data/lib/active_record/serialization.rb +7 -3
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +80 -29
  216. data/lib/active_record/store.rb +122 -42
  217. data/lib/active_record/suppressor.rb +6 -3
  218. data/lib/active_record/table_metadata.rb +51 -39
  219. data/lib/active_record/tasks/database_tasks.rb +332 -115
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +66 -104
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -56
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +40 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +246 -0
  225. data/lib/active_record/timestamp.rb +70 -38
  226. data/lib/active_record/touch_later.rb +26 -24
  227. data/lib/active_record/transactions.rb +121 -184
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type.rb +29 -17
  230. data/lib/active_record/type/adapter_specific_registry.rb +44 -48
  231. data/lib/active_record/type/date.rb +2 -0
  232. data/lib/active_record/type/date_time.rb +2 -0
  233. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  234. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  235. data/lib/active_record/type/internal/timezone.rb +2 -0
  236. data/lib/active_record/type/json.rb +30 -0
  237. data/lib/active_record/type/serialized.rb +20 -9
  238. data/lib/active_record/type/text.rb +11 -0
  239. data/lib/active_record/type/time.rb +12 -1
  240. data/lib/active_record/type/type_map.rb +14 -17
  241. data/lib/active_record/type/unsigned_integer.rb +16 -0
  242. data/lib/active_record/type_caster.rb +4 -2
  243. data/lib/active_record/type_caster/connection.rb +17 -13
  244. data/lib/active_record/type_caster/map.rb +10 -6
  245. data/lib/active_record/validations.rb +8 -5
  246. data/lib/active_record/validations/absence.rb +2 -0
  247. data/lib/active_record/validations/associated.rb +4 -3
  248. data/lib/active_record/validations/length.rb +2 -0
  249. data/lib/active_record/validations/numericality.rb +35 -0
  250. data/lib/active_record/validations/presence.rb +4 -2
  251. data/lib/active_record/validations/uniqueness.rb +52 -45
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/arel.rb +54 -0
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes.rb +70 -0
  269. data/lib/arel/nodes/and.rb +32 -0
  270. data/lib/arel/nodes/ascending.rb +23 -0
  271. data/lib/arel/nodes/binary.rb +126 -0
  272. data/lib/arel/nodes/bind_param.rb +44 -0
  273. data/lib/arel/nodes/case.rb +55 -0
  274. data/lib/arel/nodes/casted.rb +62 -0
  275. data/lib/arel/nodes/comment.rb +29 -0
  276. data/lib/arel/nodes/count.rb +12 -0
  277. data/lib/arel/nodes/delete_statement.rb +45 -0
  278. data/lib/arel/nodes/descending.rb +23 -0
  279. data/lib/arel/nodes/equality.rb +15 -0
  280. data/lib/arel/nodes/extract.rb +24 -0
  281. data/lib/arel/nodes/false.rb +16 -0
  282. data/lib/arel/nodes/full_outer_join.rb +8 -0
  283. data/lib/arel/nodes/function.rb +44 -0
  284. data/lib/arel/nodes/grouping.rb +11 -0
  285. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  286. data/lib/arel/nodes/in.rb +15 -0
  287. data/lib/arel/nodes/infix_operation.rb +92 -0
  288. data/lib/arel/nodes/inner_join.rb +8 -0
  289. data/lib/arel/nodes/insert_statement.rb +37 -0
  290. data/lib/arel/nodes/join_source.rb +20 -0
  291. data/lib/arel/nodes/matches.rb +18 -0
  292. data/lib/arel/nodes/named_function.rb +23 -0
  293. data/lib/arel/nodes/node.rb +51 -0
  294. data/lib/arel/nodes/node_expression.rb +13 -0
  295. data/lib/arel/nodes/ordering.rb +27 -0
  296. data/lib/arel/nodes/outer_join.rb +8 -0
  297. data/lib/arel/nodes/over.rb +15 -0
  298. data/lib/arel/nodes/regexp.rb +16 -0
  299. data/lib/arel/nodes/right_outer_join.rb +8 -0
  300. data/lib/arel/nodes/select_core.rb +67 -0
  301. data/lib/arel/nodes/select_statement.rb +41 -0
  302. data/lib/arel/nodes/sql_literal.rb +19 -0
  303. data/lib/arel/nodes/string_join.rb +11 -0
  304. data/lib/arel/nodes/table_alias.rb +31 -0
  305. data/lib/arel/nodes/terminal.rb +16 -0
  306. data/lib/arel/nodes/true.rb +16 -0
  307. data/lib/arel/nodes/unary.rb +44 -0
  308. data/lib/arel/nodes/unary_operation.rb +20 -0
  309. data/lib/arel/nodes/unqualified_column.rb +22 -0
  310. data/lib/arel/nodes/update_statement.rb +41 -0
  311. data/lib/arel/nodes/values_list.rb +9 -0
  312. data/lib/arel/nodes/window.rb +126 -0
  313. data/lib/arel/nodes/with.rb +11 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors.rb +13 -0
  321. data/lib/arel/visitors/dot.rb +308 -0
  322. data/lib/arel/visitors/mysql.rb +93 -0
  323. data/lib/arel/visitors/postgresql.rb +120 -0
  324. data/lib/arel/visitors/sqlite.rb +38 -0
  325. data/lib/arel/visitors/to_sql.rb +899 -0
  326. data/lib/arel/visitors/visitor.rb +45 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/rails/generators/active_record.rb +7 -5
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  331. data/lib/rails/generators/active_record/migration.rb +22 -3
  332. data/lib/rails/generators/active_record/migration/migration_generator.rb +38 -35
  333. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +3 -1
  334. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +7 -5
  335. data/lib/rails/generators/active_record/model/model_generator.rb +41 -25
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  338. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  339. metadata +141 -57
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  347. data/lib/active_record/attribute.rb +0 -213
  348. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  349. data/lib/active_record/attribute_decorators.rb +0 -67
  350. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  351. data/lib/active_record/attribute_set.rb +0 -110
  352. data/lib/active_record/attribute_set/builder.rb +0 -132
  353. data/lib/active_record/collection_cache_key.rb +0 -50
  354. data/lib/active_record/connection_adapters/connection_specification.rb +0 -263
  355. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -22
  356. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  357. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  358. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  359. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -17
  360. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  361. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  362. data/lib/active_record/relation/where_clause_factory.rb +0 -38
  363. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/testing/parallelization"
4
+
5
+ module ActiveRecord
6
+ module TestDatabases # :nodoc:
7
+ ActiveSupport::Testing::Parallelization.after_fork_hook do |i|
8
+ create_and_load_schema(i, env_name: ActiveRecord::ConnectionHandling::DEFAULT_ENV.call)
9
+ end
10
+
11
+ def self.create_and_load_schema(i, env_name:)
12
+ old, ENV["VERBOSE"] = ENV["VERBOSE"], "false"
13
+
14
+ ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
15
+ db_config._database = "#{db_config.database}-#{i}"
16
+
17
+ ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, ActiveRecord::Base.schema_format, nil)
18
+ end
19
+ ensure
20
+ ActiveRecord::Base.establish_connection
21
+ ENV["VERBOSE"] = old
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,246 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/enumerable"
4
+
5
+ module ActiveRecord
6
+ module TestFixtures
7
+ extend ActiveSupport::Concern
8
+
9
+ def before_setup # :nodoc:
10
+ setup_fixtures
11
+ super
12
+ end
13
+
14
+ def after_teardown # :nodoc:
15
+ super
16
+ teardown_fixtures
17
+ end
18
+
19
+ included do
20
+ class_attribute :fixture_path, instance_writer: false
21
+ class_attribute :fixture_table_names, default: []
22
+ class_attribute :fixture_class_names, default: {}
23
+ class_attribute :use_transactional_tests, default: true
24
+ class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
25
+ class_attribute :pre_loaded_fixtures, default: false
26
+ class_attribute :lock_threads, default: true
27
+ end
28
+
29
+ module ClassMethods
30
+ # Sets the model class for a fixture when the class name cannot be inferred from the fixture name.
31
+ #
32
+ # Examples:
33
+ #
34
+ # set_fixture_class some_fixture: SomeModel,
35
+ # 'namespaced/fixture' => Another::Model
36
+ #
37
+ # The keys must be the fixture names, that coincide with the short paths to the fixture files.
38
+ def set_fixture_class(class_names = {})
39
+ self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys)
40
+ end
41
+
42
+ def fixtures(*fixture_set_names)
43
+ if fixture_set_names.first == :all
44
+ raise StandardError, "No fixture path found. Please set `#{self}.fixture_path`." if fixture_path.blank?
45
+ fixture_set_names = Dir[::File.join(fixture_path, "{**,*}/*.{yml}")].uniq
46
+ fixture_set_names.reject! { |f| f.start_with?(file_fixture_path.to_s) } if defined?(file_fixture_path) && file_fixture_path
47
+ fixture_set_names.map! { |f| f[fixture_path.to_s.size..-5].delete_prefix("/") }
48
+ else
49
+ fixture_set_names = fixture_set_names.flatten.map(&:to_s)
50
+ end
51
+
52
+ self.fixture_table_names |= fixture_set_names
53
+ setup_fixture_accessors(fixture_set_names)
54
+ end
55
+
56
+ def setup_fixture_accessors(fixture_set_names = nil)
57
+ fixture_set_names = Array(fixture_set_names || fixture_table_names)
58
+ methods = Module.new do
59
+ fixture_set_names.each do |fs_name|
60
+ fs_name = fs_name.to_s
61
+ accessor_name = fs_name.tr("/", "_").to_sym
62
+
63
+ define_method(accessor_name) do |*fixture_names|
64
+ force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
65
+ return_single_record = fixture_names.size == 1
66
+ fixture_names = @loaded_fixtures[fs_name].fixtures.keys if fixture_names.empty?
67
+
68
+ @fixture_cache[fs_name] ||= {}
69
+
70
+ instances = fixture_names.map do |f_name|
71
+ f_name = f_name.to_s if f_name.is_a?(Symbol)
72
+ @fixture_cache[fs_name].delete(f_name) if force_reload
73
+
74
+ if @loaded_fixtures[fs_name][f_name]
75
+ @fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
76
+ else
77
+ raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
78
+ end
79
+ end
80
+
81
+ return_single_record ? instances.first : instances
82
+ end
83
+ private accessor_name
84
+ end
85
+ end
86
+ include methods
87
+ end
88
+
89
+ def uses_transaction(*methods)
90
+ @uses_transaction = [] unless defined?(@uses_transaction)
91
+ @uses_transaction.concat methods.map(&:to_s)
92
+ end
93
+
94
+ def uses_transaction?(method)
95
+ @uses_transaction = [] unless defined?(@uses_transaction)
96
+ @uses_transaction.include?(method.to_s)
97
+ end
98
+ end
99
+
100
+ def run_in_transaction?
101
+ use_transactional_tests &&
102
+ !self.class.uses_transaction?(name)
103
+ end
104
+
105
+ def setup_fixtures(config = ActiveRecord::Base)
106
+ if pre_loaded_fixtures && !use_transactional_tests
107
+ raise RuntimeError, "pre_loaded_fixtures requires use_transactional_tests"
108
+ end
109
+
110
+ @fixture_cache = {}
111
+ @fixture_connections = []
112
+ @@already_loaded_fixtures ||= {}
113
+ @connection_subscriber = nil
114
+
115
+ # Load fixtures once and begin transaction.
116
+ if run_in_transaction?
117
+ if @@already_loaded_fixtures[self.class]
118
+ @loaded_fixtures = @@already_loaded_fixtures[self.class]
119
+ else
120
+ @loaded_fixtures = load_fixtures(config)
121
+ @@already_loaded_fixtures[self.class] = @loaded_fixtures
122
+ end
123
+
124
+ # Begin transactions for connections already established
125
+ @fixture_connections = enlist_fixture_connections
126
+ @fixture_connections.each do |connection|
127
+ connection.begin_transaction joinable: false, _lazy: false
128
+ connection.pool.lock_thread = true if lock_threads
129
+ end
130
+
131
+ # When connections are established in the future, begin a transaction too
132
+ @connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
133
+ spec_name = payload[:spec_name] if payload.key?(:spec_name)
134
+ shard = payload[:shard] if payload.key?(:shard)
135
+ setup_shared_connection_pool
136
+
137
+ if spec_name
138
+ begin
139
+ connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name, shard: shard)
140
+ rescue ConnectionNotEstablished
141
+ connection = nil
142
+ end
143
+
144
+ if connection && !@fixture_connections.include?(connection)
145
+ connection.begin_transaction joinable: false, _lazy: false
146
+ connection.pool.lock_thread = true if lock_threads
147
+ @fixture_connections << connection
148
+ end
149
+ end
150
+ end
151
+
152
+ # Load fixtures for every test.
153
+ else
154
+ ActiveRecord::FixtureSet.reset_cache
155
+ @@already_loaded_fixtures[self.class] = nil
156
+ @loaded_fixtures = load_fixtures(config)
157
+ end
158
+
159
+ # Instantiate fixtures for every test if requested.
160
+ instantiate_fixtures if use_instantiated_fixtures
161
+ end
162
+
163
+ def teardown_fixtures
164
+ # Rollback changes if a transaction is active.
165
+ if run_in_transaction?
166
+ ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
167
+ @fixture_connections.each do |connection|
168
+ connection.rollback_transaction if connection.transaction_open?
169
+ connection.pool.lock_thread = false
170
+ end
171
+ @fixture_connections.clear
172
+ else
173
+ ActiveRecord::FixtureSet.reset_cache
174
+ end
175
+
176
+ ActiveRecord::Base.clear_active_connections!
177
+ end
178
+
179
+ def enlist_fixture_connections
180
+ setup_shared_connection_pool
181
+
182
+ ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
183
+ end
184
+
185
+ private
186
+ # Shares the writing connection pool with connections on
187
+ # other handlers.
188
+ #
189
+ # In an application with a primary and replica the test fixtures
190
+ # need to share a connection pool so that the reading connection
191
+ # can see data in the open transaction on the writing connection.
192
+ def setup_shared_connection_pool
193
+ if ActiveRecord::Base.legacy_connection_handling
194
+ writing_handler = ActiveRecord::Base.connection_handlers[ActiveRecord::Base.writing_role]
195
+
196
+ ActiveRecord::Base.connection_handlers.values.each do |handler|
197
+ if handler != writing_handler
198
+ handler.connection_pool_names.each do |name|
199
+ writing_pool_manager = writing_handler.send(:owner_to_pool_manager)[name]
200
+ return unless writing_pool_manager
201
+
202
+ pool_manager = handler.send(:owner_to_pool_manager)[name]
203
+ pool_manager.shard_names.each do |shard_name|
204
+ writing_pool_config = writing_pool_manager.get_pool_config(nil, shard_name)
205
+ pool_manager.set_pool_config(nil, shard_name, writing_pool_config)
206
+ end
207
+ end
208
+ end
209
+ end
210
+ else
211
+ handler = ActiveRecord::Base.connection_handler
212
+
213
+ handler.connection_pool_names.each do |name|
214
+ pool_manager = handler.send(:owner_to_pool_manager)[name]
215
+ pool_manager.shard_names.each do |shard_name|
216
+ writing_pool_config = pool_manager.get_pool_config(ActiveRecord::Base.writing_role, shard_name)
217
+ pool_manager.role_names.each do |role|
218
+ next unless pool_manager.get_pool_config(role, shard_name)
219
+ pool_manager.set_pool_config(role, shard_name, writing_pool_config)
220
+ end
221
+ end
222
+ end
223
+ end
224
+ end
225
+
226
+ def load_fixtures(config)
227
+ ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config).index_by(&:name)
228
+ end
229
+
230
+ def instantiate_fixtures
231
+ if pre_loaded_fixtures
232
+ raise RuntimeError, "Load fixtures before instantiating them." if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
233
+ ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
234
+ else
235
+ raise RuntimeError, "Load fixtures before instantiating them." if @loaded_fixtures.nil?
236
+ @loaded_fixtures.each_value do |fixture_set|
237
+ ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
238
+ end
239
+ end
240
+ end
241
+
242
+ def load_instances?
243
+ use_instantiated_fixtures != :no_instances
244
+ end
245
+ end
246
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record \Timestamp
3
5
  #
@@ -42,8 +44,7 @@ module ActiveRecord
42
44
  extend ActiveSupport::Concern
43
45
 
44
46
  included do
45
- class_attribute :record_timestamps
46
- self.record_timestamps = true
47
+ class_attribute :record_timestamps, default: true
47
48
  end
48
49
 
49
50
  def initialize_dup(other) # :nodoc:
@@ -51,81 +52,112 @@ module ActiveRecord
51
52
  clear_timestamp_attributes
52
53
  end
53
54
 
54
- private
55
+ module ClassMethods # :nodoc:
56
+ def touch_attributes_with_time(*names, time: nil)
57
+ attribute_names = timestamp_attributes_for_update_in_model
58
+ attribute_names |= names.map(&:to_s)
59
+ attribute_names.index_with(time || current_time_from_proper_timezone)
60
+ end
61
+
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
66
+
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
+
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
+ default_timezone == :utc ? Time.now.utc : Time.now
79
+ end
80
+
81
+ private
82
+ def timestamp_attributes_for_create
83
+ ["created_at", "created_on"].map! { |name| attribute_aliases[name] || name }
84
+ end
85
+
86
+ def timestamp_attributes_for_update
87
+ ["updated_at", "updated_on"].map! { |name| attribute_aliases[name] || name }
88
+ end
89
+
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
95
+ end
96
+ end
55
97
 
98
+ private
56
99
  def _create_record
57
- if self.record_timestamps
100
+ if record_timestamps
58
101
  current_time = current_time_from_proper_timezone
59
102
 
60
- all_timestamp_attributes.each do |column|
61
- column = column.to_s
62
- if has_attribute?(column) && !attribute_present?(column)
63
- write_attribute(column, current_time)
64
- end
103
+ all_timestamp_attributes_in_model.each do |column|
104
+ _write_attribute(column, current_time) unless _read_attribute(column)
65
105
  end
66
106
  end
67
107
 
68
108
  super
69
109
  end
70
110
 
71
- def _update_record(*args, touch: true, **options)
72
- if touch && should_record_timestamps?
111
+ def _update_record
112
+ if @_touch_record && should_record_timestamps?
73
113
  current_time = current_time_from_proper_timezone
74
114
 
75
115
  timestamp_attributes_for_update_in_model.each do |column|
76
- column = column.to_s
77
- next if attribute_changed?(column)
78
- write_attribute(column, current_time)
116
+ next if will_save_change_to_attribute?(column)
117
+ _write_attribute(column, current_time)
79
118
  end
80
119
  end
81
- super(*args)
120
+
121
+ super
122
+ end
123
+
124
+ def create_or_update(touch: true, **)
125
+ @_touch_record = touch
126
+ super
82
127
  end
83
128
 
84
129
  def should_record_timestamps?
85
- self.record_timestamps && (!partial_writes? || changed?)
130
+ record_timestamps && (!partial_writes? || has_changes_to_save?)
86
131
  end
87
132
 
88
133
  def timestamp_attributes_for_create_in_model
89
- timestamp_attributes_for_create.select { |c| self.class.column_names.include?(c.to_s) }
134
+ self.class.timestamp_attributes_for_create_in_model
90
135
  end
91
136
 
92
137
  def timestamp_attributes_for_update_in_model
93
- timestamp_attributes_for_update.select { |c| self.class.column_names.include?(c.to_s) }
138
+ self.class.timestamp_attributes_for_update_in_model
94
139
  end
95
140
 
96
141
  def all_timestamp_attributes_in_model
97
- timestamp_attributes_for_create_in_model + timestamp_attributes_for_update_in_model
142
+ self.class.all_timestamp_attributes_in_model
98
143
  end
99
144
 
100
- def timestamp_attributes_for_update
101
- [:updated_at, :updated_on]
102
- end
103
-
104
- def timestamp_attributes_for_create
105
- [:created_at, :created_on]
106
- end
107
-
108
- def all_timestamp_attributes
109
- timestamp_attributes_for_create + timestamp_attributes_for_update
145
+ def current_time_from_proper_timezone
146
+ self.class.current_time_from_proper_timezone
110
147
  end
111
148
 
112
- def max_updated_column_timestamp(timestamp_names = timestamp_attributes_for_update)
113
- timestamp_names
114
- .map { |attr| self[attr] }
149
+ def max_updated_column_timestamp
150
+ timestamp_attributes_for_update_in_model
151
+ .map { |attr| self[attr]&.to_time }
115
152
  .compact
116
- .map(&:to_time)
117
153
  .max
118
154
  end
119
155
 
120
- def current_time_from_proper_timezone
121
- self.class.default_timezone == :utc ? Time.now.utc : Time.now
122
- end
123
-
124
156
  # Clear attributes and changed_attributes
125
157
  def clear_timestamp_attributes
126
158
  all_timestamp_attributes_in_model.each do |attribute_name|
127
159
  self[attribute_name] = nil
128
- clear_attribute_changes([attribute_name])
160
+ clear_attribute_change(attribute_name)
129
161
  end
130
162
  end
131
163
  end
@@ -1,31 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record Touch Later
3
- module TouchLater
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- 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
8
9
  end
9
10
 
10
11
  def touch_later(*names) # :nodoc:
11
- unless persisted?
12
- raise ActiveRecordError, <<-MSG.squish
13
- cannot touch on a new or destroyed record object. Consider using
14
- persisted?, new_record?, or destroyed? before touching
15
- MSG
16
- end
12
+ _raise_record_not_touched_error unless persisted?
17
13
 
18
14
  @_defer_touch_attrs ||= timestamp_attributes_for_update_in_model
19
- @_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
+
20
20
  @_touch_time = current_time_from_proper_timezone
21
21
 
22
22
  surreptitiously_touch @_defer_touch_attrs
23
- self.class.connection.add_transaction_record self
23
+ add_to_transaction
24
+ @_new_record_before_last_commit ||= false
24
25
 
25
26
  # touch the parents as we are not calling the after_save callbacks
26
27
  self.class.reflect_on_all_associations(:belongs_to).each do |r|
27
28
  if touch = r.options[:touch]
28
- ActiveRecord::Associations::Builder::BelongsTo.touch_record(self, r.foreign_key, r.name, touch, :touch_later)
29
+ ActiveRecord::Associations::Builder::BelongsTo.touch_record(self, changes_to_save, r.foreign_key, r.name, touch, :touch_later)
29
30
  end
30
31
  end
31
32
  end
@@ -33,22 +34,24 @@ module ActiveRecord
33
34
  def touch(*names, time: nil) # :nodoc:
34
35
  if has_defer_touch_attrs?
35
36
  names |= @_defer_touch_attrs
37
+ super(*names, time: time)
38
+ @_defer_touch_attrs, @_touch_time = nil, nil
39
+ else
40
+ super
36
41
  end
37
- super(*names, time: time)
38
42
  end
39
43
 
40
44
  private
41
-
42
- def surreptitiously_touch(attrs)
43
- attrs.each { |attr| write_attribute attr, @_touch_time }
44
- 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
45
50
  end
46
51
 
47
52
  def touch_deferred_attributes
48
- if has_defer_touch_attrs? && persisted?
49
- touch(*@_defer_touch_attrs, time: @_touch_time)
50
- @_defer_touch_attrs, @_touch_time = nil, nil
51
- end
53
+ @_skip_dirty_tracking = true
54
+ touch(time: @_touch_time)
52
55
  end
53
56
 
54
57
  def has_defer_touch_attrs?
@@ -58,6 +61,5 @@ module ActiveRecord
58
61
  def belongs_to_touch_method
59
62
  :touch_later
60
63
  end
61
-
62
64
  end
63
65
  end