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
@@ -1,4 +1,6 @@
1
- require 'active_support/core_ext/string/filters'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/filters"
2
4
 
3
5
  module ActiveRecord
4
6
  module Integration
@@ -7,17 +9,32 @@ module ActiveRecord
7
9
  included do
8
10
  ##
9
11
  # :singleton-method:
10
- # Indicates the format used to generate the timestamp in the cache key.
11
- # Accepts any of the symbols in <tt>Time::DATE_FORMATS</tt>.
12
+ # Indicates the format used to generate the timestamp in the cache key, if
13
+ # versioning is off. Accepts any of the symbols in <tt>Time::DATE_FORMATS</tt>.
12
14
  #
13
15
  # This is +:usec+, by default.
14
- class_attribute :cache_timestamp_format, :instance_writer => false
15
- self.cache_timestamp_format = :usec
16
+ class_attribute :cache_timestamp_format, instance_writer: false, default: :usec
17
+
18
+ ##
19
+ # :singleton-method:
20
+ # Indicates whether to use a stable #cache_key method that is accompanied
21
+ # by a changing version in the #cache_version method.
22
+ #
23
+ # This is +true+, by default on Rails 5.2 and above.
24
+ class_attribute :cache_versioning, instance_writer: false, default: false
25
+
26
+ ##
27
+ # :singleton-method:
28
+ # Indicates whether to use a stable #cache_key method that is accompanied
29
+ # by a changing version in the #cache_version method on collections.
30
+ #
31
+ # This is +false+, by default until Rails 6.1.
32
+ class_attribute :collection_cache_versioning, instance_writer: false, default: false
16
33
  end
17
34
 
18
- # Returns a String, which Action Pack uses for constructing a URL to this
19
- # object. The default implementation returns this record's id as a String,
20
- # or nil if this record's unsaved.
35
+ # Returns a +String+, which Action Pack uses for constructing a URL to this
36
+ # object. The default implementation returns this record's id as a +String+,
37
+ # or +nil+ if this record's unsaved.
21
38
  #
22
39
  # For example, suppose that you have a User model, and that you have a
23
40
  # <tt>resources :users</tt> route. Normally, +user_path+ will
@@ -42,32 +59,62 @@ module ActiveRecord
42
59
  id && id.to_s # Be sure to stringify the id for routes
43
60
  end
44
61
 
45
- # Returns a cache key that can be used to identify this record.
62
+ # Returns a stable cache key that can be used to identify this record.
46
63
  #
47
64
  # Product.new.cache_key # => "products/new"
48
- # Product.find(5).cache_key # => "products/5" (updated_at not available)
49
- # Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available)
65
+ # Product.find(5).cache_key # => "products/5"
50
66
  #
51
- # You can also pass a list of named timestamps, and the newest in the list will be
52
- # used to generate the key:
67
+ # If ActiveRecord::Base.cache_versioning is turned off, as it was in Rails 5.1 and earlier,
68
+ # the cache key will also include a version.
53
69
  #
54
- # Person.find(5).cache_key(:updated_at, :last_reviewed_at)
55
- def cache_key(*timestamp_names)
70
+ # Product.cache_versioning = false
71
+ # Product.find(5).cache_key # => "products/5-20071224150000" (updated_at available)
72
+ def cache_key
56
73
  if new_record?
57
74
  "#{model_name.cache_key}/new"
58
75
  else
59
- timestamp = if timestamp_names.any?
60
- max_updated_column_timestamp(timestamp_names)
76
+ if cache_version
77
+ "#{model_name.cache_key}/#{id}"
61
78
  else
62
- max_updated_column_timestamp
79
+ timestamp = max_updated_column_timestamp
80
+
81
+ if timestamp
82
+ timestamp = timestamp.utc.to_s(cache_timestamp_format)
83
+ "#{model_name.cache_key}/#{id}-#{timestamp}"
84
+ else
85
+ "#{model_name.cache_key}/#{id}"
86
+ end
63
87
  end
88
+ end
89
+ end
64
90
 
65
- if timestamp
66
- timestamp = timestamp.utc.to_s(cache_timestamp_format)
67
- "#{model_name.cache_key}/#{id}-#{timestamp}"
68
- else
69
- "#{model_name.cache_key}/#{id}"
91
+ # Returns a cache version that can be used together with the cache key to form
92
+ # a recyclable caching scheme. By default, the #updated_at column is used for the
93
+ # cache_version, but this method can be overwritten to return something else.
94
+ #
95
+ # Note, this method will return nil if ActiveRecord::Base.cache_versioning is set to
96
+ # +false+.
97
+ def cache_version
98
+ return unless cache_versioning
99
+
100
+ if has_attribute?("updated_at")
101
+ timestamp = updated_at_before_type_cast
102
+ if can_use_fast_cache_version?(timestamp)
103
+ raw_timestamp_to_cache_version(timestamp)
104
+ elsif timestamp = updated_at
105
+ timestamp.utc.to_s(cache_timestamp_format)
70
106
  end
107
+ elsif self.class.has_attribute?("updated_at")
108
+ raise ActiveModel::MissingAttributeError, "missing attribute: updated_at"
109
+ end
110
+ end
111
+
112
+ # Returns a cache key along with the version.
113
+ def cache_key_with_version
114
+ if version = cache_version
115
+ "#{cache_key}-#{version}"
116
+ else
117
+ cache_key
71
118
  end
72
119
  end
73
120
 
@@ -89,7 +136,7 @@ module ActiveRecord
89
136
  #
90
137
  # user = User.find_by(name: 'David Heinemeier Hansson')
91
138
  # user.id # => 125
92
- # user_path(user) # => "/users/125-david"
139
+ # user_path(user) # => "/users/125-david-heinemeier"
93
140
  #
94
141
  # Because the generated param begins with the record's +id+, it is
95
142
  # suitable for passing to +find+. In a controller, for example:
@@ -103,7 +150,7 @@ module ActiveRecord
103
150
  define_method :to_param do
104
151
  if (default = super()) &&
105
152
  (result = send(method_name).to_s).present? &&
106
- (param = result.squish.truncate(20, separator: /\s/, omission: nil).parameterize).present?
153
+ (param = result.squish.parameterize.truncate(20, separator: /-/, omission: "")).present?
107
154
  "#{default}-#{param}"
108
155
  else
109
156
  default
@@ -111,6 +158,48 @@ module ActiveRecord
111
158
  end
112
159
  end
113
160
  end
161
+
162
+ def collection_cache_key(collection = all, timestamp_column = :updated_at) # :nodoc:
163
+ collection.send(:compute_cache_key, timestamp_column)
164
+ end
114
165
  end
166
+
167
+ private
168
+ # Detects if the value before type cast
169
+ # can be used to generate a cache_version.
170
+ #
171
+ # The fast cache version only works with a
172
+ # string value directly from the database.
173
+ #
174
+ # We also must check if the timestamp format has been changed
175
+ # or if the timezone is not set to UTC then
176
+ # we cannot apply our transformations correctly.
177
+ def can_use_fast_cache_version?(timestamp)
178
+ timestamp.is_a?(String) &&
179
+ cache_timestamp_format == :usec &&
180
+ default_timezone == :utc &&
181
+ !updated_at_came_from_user?
182
+ end
183
+
184
+ # Converts a raw database string to `:usec`
185
+ # format.
186
+ #
187
+ # Example:
188
+ #
189
+ # timestamp = "2018-10-15 20:02:15.266505"
190
+ # raw_timestamp_to_cache_version(timestamp)
191
+ # # => "20181015200215266505"
192
+ #
193
+ # PostgreSQL truncates trailing zeros,
194
+ # https://github.com/postgres/postgres/commit/3e1beda2cde3495f41290e1ece5d544525810214
195
+ # to account for this we pad the output with zeros
196
+ def raw_timestamp_to_cache_version(timestamp)
197
+ key = timestamp.delete("- :.")
198
+ if key.length < 20
199
+ key.ljust(20, "0")
200
+ else
201
+ key
202
+ end
203
+ end
115
204
  end
116
205
  end
@@ -1,56 +1,62 @@
1
- require 'active_record/scoping/default'
2
- require 'active_record/scoping/named'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/scoping/default"
4
+ require "active_record/scoping/named"
3
5
 
4
6
  module ActiveRecord
5
7
  # This class is used to create a table that keeps track of values and keys such
6
8
  # as which environment migrations were run in.
9
+ #
10
+ # This is enabled by default. To disable this functionality set
11
+ # `use_metadata_table` to false in your database configuration.
7
12
  class InternalMetadata < ActiveRecord::Base # :nodoc:
8
13
  class << self
14
+ def enabled?
15
+ ActiveRecord::Base.connection.use_metadata_table?
16
+ end
17
+
18
+ def _internal?
19
+ true
20
+ end
21
+
9
22
  def primary_key
10
23
  "key"
11
24
  end
12
25
 
13
26
  def table_name
14
- "#{table_name_prefix}#{ActiveRecord::Base.internal_metadata_table_name}#{table_name_suffix}"
15
- end
16
-
17
- def original_table_name
18
- "#{table_name_prefix}active_record_internal_metadatas#{table_name_suffix}"
27
+ "#{table_name_prefix}#{internal_metadata_table_name}#{table_name_suffix}"
19
28
  end
20
29
 
21
30
  def []=(key, value)
22
- find_or_initialize_by(key: key).update_attributes!(value: value)
23
- end
31
+ return unless enabled?
24
32
 
25
- def [](key)
26
- where(key: key).pluck(:value).first
33
+ find_or_initialize_by(key: key).update!(value: value)
27
34
  end
28
35
 
29
- def table_exists?
30
- ActiveSupport::Deprecation.silence { connection.table_exists?(table_name) }
31
- end
36
+ def [](key)
37
+ return unless enabled?
32
38
 
33
- def original_table_exists?
34
- # This method will be removed in Rails 5.1
35
- # Since it is only necessary when `active_record_internal_metadatas` could exist
36
- ActiveSupport::Deprecation.silence { connection.table_exists?(original_table_name) }
39
+ where(key: key).pluck(:value).first
37
40
  end
38
41
 
39
42
  # Creates an internal metadata table with columns +key+ and +value+
40
43
  def create_table
41
- if original_table_exists?
42
- connection.rename_table(original_table_name, table_name)
43
- end
44
- unless table_exists?
45
- key_options = connection.internal_string_options_for_primary_key
44
+ return unless enabled?
46
45
 
46
+ unless connection.table_exists?(table_name)
47
47
  connection.create_table(table_name, id: false) do |t|
48
- t.string :key, key_options
48
+ t.string :key, **connection.internal_string_options_for_primary_key
49
49
  t.string :value
50
50
  t.timestamps
51
51
  end
52
52
  end
53
53
  end
54
+
55
+ def drop_table
56
+ return unless enabled?
57
+
58
+ connection.drop_table table_name, if_exists: true
59
+ end
54
60
  end
55
61
  end
56
62
  end
@@ -1,12 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
- module LegacyYamlAdapter
4
+ module LegacyYamlAdapter # :nodoc:
3
5
  def self.convert(klass, coder)
4
6
  return coder unless coder.is_a?(Psych::Coder)
5
7
 
6
8
  case coder["active_record_yaml_version"]
7
- when 1 then coder
9
+ when 1, 2 then coder
8
10
  else
9
- if coder["attributes"].is_a?(AttributeSet)
11
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
12
+ YAML loading from legacy format older than Rails 5.0 is deprecated
13
+ and will be removed in Rails 6.2.
14
+ MSG
15
+ if coder["attributes"].is_a?(ActiveModel::AttributeSet)
10
16
  Rails420.convert(klass, coder)
11
17
  else
12
18
  Rails41.convert(klass, coder)
@@ -14,7 +20,7 @@ module ActiveRecord
14
20
  end
15
21
  end
16
22
 
17
- module Rails420
23
+ module Rails420 # :nodoc:
18
24
  def self.convert(klass, coder)
19
25
  attribute_set = coder["attributes"]
20
26
 
@@ -30,7 +36,7 @@ module ActiveRecord
30
36
  end
31
37
  end
32
38
 
33
- module Rails41
39
+ module Rails41 # :nodoc:
34
40
  def self.convert(klass, coder)
35
41
  attributes = klass.attributes_builder
36
42
  .build_from_database(coder["attributes"])
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Locking
3
5
  # == What is Optimistic Locking
@@ -51,22 +53,24 @@ module ActiveRecord
51
53
  extend ActiveSupport::Concern
52
54
 
53
55
  included do
54
- class_attribute :lock_optimistically, instance_writer: false
55
- self.lock_optimistically = true
56
+ class_attribute :lock_optimistically, instance_writer: false, default: true
56
57
  end
57
58
 
58
59
  def locking_enabled? #:nodoc:
59
60
  self.class.locking_enabled?
60
61
  end
61
62
 
62
- private
63
- def increment_lock
64
- lock_col = self.class.locking_column
65
- previous_lock_value = send(lock_col).to_i
66
- send(lock_col + '=', previous_lock_value + 1)
63
+ def increment!(*, **) #:nodoc:
64
+ super.tap do
65
+ if locking_enabled?
66
+ self[self.class.locking_column] += 1
67
+ clear_attribute_change(self.class.locking_column)
68
+ end
67
69
  end
70
+ end
68
71
 
69
- def _create_record(attribute_names = self.attribute_names, *) # :nodoc:
72
+ private
73
+ def _create_record(attribute_names = self.attribute_names)
70
74
  if locking_enabled?
71
75
  # We always want to persist the locking version, even if we don't detect
72
76
  # a change from the default, since the database might have no default
@@ -75,118 +79,110 @@ module ActiveRecord
75
79
  super
76
80
  end
77
81
 
78
- def _update_record(attribute_names = self.attribute_names) #:nodoc:
82
+ def _touch_row(attribute_names, time)
83
+ @_touch_attr_names << self.class.locking_column if locking_enabled?
84
+ super
85
+ end
86
+
87
+ def _update_row(attribute_names, attempted_action = "update")
79
88
  return super unless locking_enabled?
80
- return 0 if attribute_names.empty?
81
89
 
82
- lock_col = self.class.locking_column
83
- previous_lock_value = send(lock_col).to_i
84
- increment_lock
90
+ begin
91
+ locking_column = self.class.locking_column
92
+ previous_lock_value = attribute_before_type_cast(locking_column)
93
+ attribute_names = attribute_names.dup if attribute_names.frozen?
94
+ attribute_names << locking_column
85
95
 
86
- attribute_names += [lock_col]
87
- attribute_names.uniq!
96
+ self[locking_column] += 1
88
97
 
89
- begin
90
- relation = self.class.unscoped
91
-
92
- affected_rows = relation.where(
93
- self.class.primary_key => id,
94
- lock_col => previous_lock_value,
95
- ).update_all(
96
- attributes_for_update(attribute_names).map do |name|
97
- [name, _read_attribute(name)]
98
- end.to_h
98
+ affected_rows = self.class._update_record(
99
+ attributes_with_values(attribute_names),
100
+ @primary_key => id_in_database,
101
+ locking_column => @attributes[locking_column].original_value_for_database
99
102
  )
100
103
 
101
- unless affected_rows == 1
102
- raise ActiveRecord::StaleObjectError.new(self, "update")
104
+ if affected_rows != 1
105
+ raise ActiveRecord::StaleObjectError.new(self, attempted_action)
103
106
  end
104
107
 
105
108
  affected_rows
106
109
 
107
- # If something went wrong, revert the version.
110
+ # If something went wrong, revert the locking_column value.
108
111
  rescue Exception
109
- send(lock_col + '=', previous_lock_value)
112
+ self[locking_column] = previous_lock_value.to_i
110
113
  raise
111
114
  end
112
115
  end
113
116
 
114
117
  def destroy_row
115
- affected_rows = super
118
+ return super unless locking_enabled?
119
+
120
+ locking_column = self.class.locking_column
116
121
 
117
- if locking_enabled? && affected_rows != 1
122
+ affected_rows = self.class._delete_record(
123
+ @primary_key => id_in_database,
124
+ locking_column => attribute_before_type_cast(locking_column)
125
+ )
126
+
127
+ if affected_rows != 1
118
128
  raise ActiveRecord::StaleObjectError.new(self, "destroy")
119
129
  end
120
130
 
121
131
  affected_rows
122
132
  end
123
133
 
124
- def relation_for_destroy
125
- relation = super
134
+ module ClassMethods
135
+ DEFAULT_LOCKING_COLUMN = "lock_version"
126
136
 
127
- if locking_enabled?
128
- locking_column = self.class.locking_column
129
- relation = relation.where(locking_column => _read_attribute(locking_column))
137
+ # Returns true if the +lock_optimistically+ flag is set to true
138
+ # (which it is, by default) and the table includes the
139
+ # +locking_column+ column (defaults to +lock_version+).
140
+ def locking_enabled?
141
+ lock_optimistically && columns_hash[locking_column]
130
142
  end
131
143
 
132
- relation
133
- end
134
-
135
- module ClassMethods
136
- DEFAULT_LOCKING_COLUMN = 'lock_version'
137
-
138
- # Returns true if the +lock_optimistically+ flag is set to true
139
- # (which it is, by default) and the table includes the
140
- # +locking_column+ column (defaults to +lock_version+).
141
- def locking_enabled?
142
- lock_optimistically && columns_hash[locking_column]
143
- end
144
-
145
- # Set the column to use for optimistic locking. Defaults to +lock_version+.
146
- def locking_column=(value)
147
- reload_schema_from_cache
148
- @locking_column = value.to_s
149
- end
144
+ # Set the column to use for optimistic locking. Defaults to +lock_version+.
145
+ def locking_column=(value)
146
+ reload_schema_from_cache
147
+ @locking_column = value.to_s
148
+ end
150
149
 
151
- # The version column used for optimistic locking. Defaults to +lock_version+.
152
- def locking_column
153
- @locking_column = DEFAULT_LOCKING_COLUMN unless defined?(@locking_column)
154
- @locking_column
155
- end
150
+ # The version column used for optimistic locking. Defaults to +lock_version+.
151
+ def locking_column
152
+ @locking_column = DEFAULT_LOCKING_COLUMN unless defined?(@locking_column)
153
+ @locking_column
154
+ end
156
155
 
157
- # Reset the column used for optimistic locking back to the +lock_version+ default.
158
- def reset_locking_column
159
- self.locking_column = DEFAULT_LOCKING_COLUMN
160
- end
156
+ # Reset the column used for optimistic locking back to the +lock_version+ default.
157
+ def reset_locking_column
158
+ self.locking_column = DEFAULT_LOCKING_COLUMN
159
+ end
161
160
 
162
- # Make sure the lock version column gets updated when counters are
163
- # updated.
164
- def update_counters(id, counters)
165
- counters = counters.merge(locking_column => 1) if locking_enabled?
166
- super
167
- end
161
+ # Make sure the lock version column gets updated when counters are
162
+ # updated.
163
+ def update_counters(id, counters)
164
+ counters = counters.merge(locking_column => 1) if locking_enabled?
165
+ super
166
+ end
168
167
 
169
- private
170
-
171
- # We need to apply this decorator here, rather than on module inclusion. The closure
172
- # created by the matcher would otherwise evaluate for `ActiveRecord::Base`, not the
173
- # sub class being decorated. As such, changes to `lock_optimistically`, or
174
- # `locking_column` would not be picked up.
175
- def inherited(subclass)
176
- subclass.class_eval do
177
- is_lock_column = ->(name, _) { lock_optimistically && name == locking_column }
178
- decorate_matching_attribute_types(is_lock_column, :_optimistic_locking) do |type|
179
- LockingType.new(type)
168
+ def define_attribute(name, cast_type, **) # :nodoc:
169
+ if lock_optimistically && name == locking_column
170
+ cast_type = LockingType.new(cast_type)
180
171
  end
172
+ super
181
173
  end
182
- super
183
174
  end
184
- end
185
175
  end
186
176
 
177
+ # In de/serialize we change `nil` to 0, so that we can allow passing
178
+ # `nil` values to `lock_version`, and not result in `ActiveRecord::StaleObjectError`
179
+ # during update record.
187
180
  class LockingType < DelegateClass(Type::Value) # :nodoc:
181
+ def self.new(subtype)
182
+ self === subtype ? subtype : super
183
+ end
184
+
188
185
  def deserialize(value)
189
- # `nil` *should* be changed to 0
190
186
  super.to_i
191
187
  end
192
188
 
@@ -195,11 +191,11 @@ module ActiveRecord
195
191
  end
196
192
 
197
193
  def init_with(coder)
198
- __setobj__(coder['subtype'])
194
+ __setobj__(coder["subtype"])
199
195
  end
200
196
 
201
197
  def encode_with(coder)
202
- coder['subtype'] = __getobj__
198
+ coder["subtype"] = __getobj__
203
199
  end
204
200
  end
205
201
  end