activerecord 4.2.11.3 → 6.0.0

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 (372) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +613 -1643
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +13 -12
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record.rb +41 -22
  8. data/lib/active_record/aggregations.rb +267 -251
  9. data/lib/active_record/association_relation.rb +11 -6
  10. data/lib/active_record/associations.rb +1737 -1597
  11. data/lib/active_record/associations/alias_tracker.rb +29 -35
  12. data/lib/active_record/associations/association.rb +125 -58
  13. data/lib/active_record/associations/association_scope.rb +103 -132
  14. data/lib/active_record/associations/belongs_to_association.rb +65 -60
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  16. data/lib/active_record/associations/builder/association.rb +27 -40
  17. data/lib/active_record/associations/builder/belongs_to.rb +69 -55
  18. data/lib/active_record/associations/builder/collection_association.rb +10 -33
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +52 -66
  20. data/lib/active_record/associations/builder/has_many.rb +8 -4
  21. data/lib/active_record/associations/builder/has_one.rb +46 -5
  22. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  23. data/lib/active_record/associations/collection_association.rb +131 -287
  24. data/lib/active_record/associations/collection_proxy.rb +241 -146
  25. data/lib/active_record/associations/foreign_association.rb +10 -1
  26. data/lib/active_record/associations/has_many_association.rb +34 -97
  27. data/lib/active_record/associations/has_many_through_association.rb +60 -87
  28. data/lib/active_record/associations/has_one_association.rb +61 -49
  29. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  30. data/lib/active_record/associations/join_dependency.rb +137 -167
  31. data/lib/active_record/associations/join_dependency/join_association.rb +38 -86
  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 +90 -92
  35. data/lib/active_record/associations/preloader/association.rb +90 -123
  36. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  37. data/lib/active_record/associations/singular_association.rb +18 -39
  38. data/lib/active_record/associations/through_association.rb +38 -18
  39. data/lib/active_record/attribute_assignment.rb +56 -183
  40. data/lib/active_record/attribute_decorators.rb +39 -15
  41. data/lib/active_record/attribute_methods.rb +120 -135
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -8
  43. data/lib/active_record/attribute_methods/dirty.rb +174 -144
  44. data/lib/active_record/attribute_methods/primary_key.rb +91 -83
  45. data/lib/active_record/attribute_methods/query.rb +6 -5
  46. data/lib/active_record/attribute_methods/read.rb +20 -76
  47. data/lib/active_record/attribute_methods/serialization.rb +40 -20
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
  49. data/lib/active_record/attribute_methods/write.rb +32 -54
  50. data/lib/active_record/attributes.rb +214 -82
  51. data/lib/active_record/autosave_association.rb +91 -37
  52. data/lib/active_record/base.rb +57 -45
  53. data/lib/active_record/callbacks.rb +100 -74
  54. data/lib/active_record/coders/json.rb +3 -1
  55. data/lib/active_record/coders/yaml_column.rb +24 -12
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +796 -296
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -115
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -23
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +170 -53
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -46
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +356 -227
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +664 -243
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +191 -83
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +460 -204
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +510 -635
  69. data/lib/active_record/connection_adapters/column.rb +56 -43
  70. data/lib/active_record/connection_adapters/connection_specification.rb +174 -152
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +58 -180
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -114
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
  96. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  100. data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
  102. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
  103. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +10 -5
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +470 -290
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +551 -356
  117. data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -345
  127. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  128. data/lib/active_record/connection_handling.rb +176 -41
  129. data/lib/active_record/core.rb +251 -231
  130. data/lib/active_record/counter_cache.rb +67 -49
  131. data/lib/active_record/database_configurations.rb +233 -0
  132. data/lib/active_record/database_configurations/database_config.rb +37 -0
  133. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  134. data/lib/active_record/database_configurations/url_config.rb +79 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +87 -105
  137. data/lib/active_record/enum.rb +163 -86
  138. data/lib/active_record/errors.rb +188 -53
  139. data/lib/active_record/explain.rb +23 -11
  140. data/lib/active_record/explain_registry.rb +4 -2
  141. data/lib/active_record/explain_subscriber.rb +10 -5
  142. data/lib/active_record/fixture_set/file.rb +35 -9
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +153 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  147. data/lib/active_record/fixtures.rb +228 -499
  148. data/lib/active_record/gem_version.rb +6 -4
  149. data/lib/active_record/inheritance.rb +158 -112
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +123 -29
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +21 -3
  154. data/lib/active_record/locale/en.yml +3 -2
  155. data/lib/active_record/locking/optimistic.rb +87 -96
  156. data/lib/active_record/locking/pessimistic.rb +18 -6
  157. data/lib/active_record/log_subscriber.rb +76 -33
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +621 -303
  162. data/lib/active_record/migration/command_recorder.rb +177 -90
  163. data/lib/active_record/migration/compatibility.rb +244 -0
  164. data/lib/active_record/migration/join_table.rb +8 -6
  165. data/lib/active_record/model_schema.rb +312 -112
  166. data/lib/active_record/nested_attributes.rb +264 -222
  167. data/lib/active_record/no_touching.rb +14 -1
  168. data/lib/active_record/null_relation.rb +24 -37
  169. data/lib/active_record/persistence.rb +557 -125
  170. data/lib/active_record/query_cache.rb +19 -23
  171. data/lib/active_record/querying.rb +43 -29
  172. data/lib/active_record/railtie.rb +143 -44
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +2 -0
  175. data/lib/active_record/railties/controller_runtime.rb +34 -33
  176. data/lib/active_record/railties/databases.rake +328 -185
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +428 -279
  179. data/lib/active_record/relation.rb +518 -341
  180. data/lib/active_record/relation/batches.rb +207 -55
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  182. data/lib/active_record/relation/calculations.rb +267 -253
  183. data/lib/active_record/relation/delegation.rb +70 -80
  184. data/lib/active_record/relation/finder_methods.rb +277 -241
  185. data/lib/active_record/relation/from_clause.rb +26 -0
  186. data/lib/active_record/relation/merger.rb +78 -87
  187. data/lib/active_record/relation/predicate_builder.rb +114 -119
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -26
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  195. data/lib/active_record/relation/query_attribute.rb +50 -0
  196. data/lib/active_record/relation/query_methods.rb +575 -394
  197. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  198. data/lib/active_record/relation/spawn_methods.rb +11 -13
  199. data/lib/active_record/relation/where_clause.rb +190 -0
  200. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  201. data/lib/active_record/result.rb +79 -42
  202. data/lib/active_record/runtime_registry.rb +6 -4
  203. data/lib/active_record/sanitization.rb +144 -121
  204. data/lib/active_record/schema.rb +21 -24
  205. data/lib/active_record/schema_dumper.rb +112 -93
  206. data/lib/active_record/schema_migration.rb +24 -17
  207. data/lib/active_record/scoping.rb +45 -26
  208. data/lib/active_record/scoping/default.rb +101 -85
  209. data/lib/active_record/scoping/named.rb +86 -33
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +5 -5
  212. data/lib/active_record/statement_cache.rb +73 -36
  213. data/lib/active_record/store.rb +127 -42
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +75 -0
  216. data/lib/active_record/tasks/database_tasks.rb +307 -100
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +55 -99
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -41
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +38 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +224 -0
  222. data/lib/active_record/timestamp.rb +86 -40
  223. data/lib/active_record/touch_later.rb +66 -0
  224. data/lib/active_record/transactions.rb +216 -150
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type.rb +78 -23
  227. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  228. data/lib/active_record/type/date.rb +4 -45
  229. data/lib/active_record/type/date_time.rb +4 -49
  230. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  231. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  232. data/lib/active_record/type/internal/timezone.rb +17 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +24 -15
  235. data/lib/active_record/type/text.rb +2 -2
  236. data/lib/active_record/type/time.rb +11 -16
  237. data/lib/active_record/type/type_map.rb +15 -17
  238. data/lib/active_record/type/unsigned_integer.rb +9 -7
  239. data/lib/active_record/type_caster.rb +9 -0
  240. data/lib/active_record/type_caster/connection.rb +34 -0
  241. data/lib/active_record/type_caster/map.rb +20 -0
  242. data/lib/active_record/validations.rb +39 -35
  243. data/lib/active_record/validations/absence.rb +25 -0
  244. data/lib/active_record/validations/associated.rb +13 -4
  245. data/lib/active_record/validations/length.rb +26 -0
  246. data/lib/active_record/validations/presence.rb +14 -13
  247. data/lib/active_record/validations/uniqueness.rb +42 -55
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/arel.rb +51 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +257 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +204 -0
  317. data/lib/arel/visitors/dot.rb +297 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +157 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +159 -0
  323. data/lib/arel/visitors/oracle12.rb +66 -0
  324. data/lib/arel/visitors/postgresql.rb +110 -0
  325. data/lib/arel/visitors/sqlite.rb +39 -0
  326. data/lib/arel/visitors/to_sql.rb +889 -0
  327. data/lib/arel/visitors/visitor.rb +46 -0
  328. data/lib/arel/visitors/where_sql.rb +23 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +7 -5
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration.rb +31 -1
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
  335. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  336. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -2
  337. data/lib/rails/generators/active_record/model/model_generator.rb +19 -22
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  340. metadata +164 -59
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  343. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  344. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  345. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  348. data/lib/active_record/attribute.rb +0 -163
  349. data/lib/active_record/attribute_set.rb +0 -81
  350. data/lib/active_record/attribute_set/builder.rb +0 -106
  351. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  352. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  353. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  354. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  355. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  356. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  357. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  358. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  359. data/lib/active_record/type/big_integer.rb +0 -13
  360. data/lib/active_record/type/binary.rb +0 -50
  361. data/lib/active_record/type/boolean.rb +0 -31
  362. data/lib/active_record/type/decimal.rb +0 -64
  363. data/lib/active_record/type/decorator.rb +0 -14
  364. data/lib/active_record/type/float.rb +0 -19
  365. data/lib/active_record/type/integer.rb +0 -59
  366. data/lib/active_record/type/mutable.rb +0 -16
  367. data/lib/active_record/type/numeric.rb +0 -36
  368. data/lib/active_record/type/string.rb +0 -40
  369. data/lib/active_record/type/time_value.rb +0 -38
  370. data/lib/active_record/type/value.rb +0 -110
  371. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
  372. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record Counter Cache
3
5
  module CounterCache
@@ -12,13 +14,21 @@ module ActiveRecord
12
14
  #
13
15
  # * +id+ - The id of the object you wish to reset a counter on.
14
16
  # * +counters+ - One or more association counters to reset. Association name or counter name can be given.
17
+ # * <tt>:touch</tt> - Touch timestamp columns when updating.
18
+ # Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
19
+ # touch that column or an array of symbols to touch just those ones.
15
20
  #
16
21
  # ==== Examples
17
22
  #
18
- # # For Post with id #1 records reset the comments_count
23
+ # # For the Post with id #1, reset the comments_count
19
24
  # Post.reset_counters(1, :comments)
20
- def reset_counters(id, *counters)
25
+ #
26
+ # # Like above, but also touch the +updated_at+ and/or +updated_on+
27
+ # # attributes.
28
+ # Post.reset_counters(1, :comments, touch: true)
29
+ def reset_counters(id, *counters, touch: nil)
21
30
  object = find(id)
31
+
22
32
  counters.each do |counter_association|
23
33
  has_many_association = _reflect_on_association(counter_association)
24
34
  unless has_many_association
@@ -26,7 +36,7 @@ module ActiveRecord
26
36
  has_many_association = has_many.find { |association| association.counter_cache_column && association.counter_cache_column.to_sym == counter_association.to_sym }
27
37
  counter_association = has_many_association.plural_name if has_many_association
28
38
  end
29
- raise ArgumentError, "'#{self.name}' has no association called '#{counter_association}'" unless has_many_association
39
+ raise ArgumentError, "'#{name}' has no association called '#{counter_association}'" unless has_many_association
30
40
 
31
41
  if has_many_association.is_a? ActiveRecord::Reflection::ThroughReflection
32
42
  has_many_association = has_many_association.through_reflection
@@ -37,25 +47,33 @@ module ActiveRecord
37
47
  reflection = child_class._reflections.values.find { |e| e.belongs_to? && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
38
48
  counter_name = reflection.counter_cache_column
39
49
 
40
- stmt = unscoped.where(arel_table[primary_key].eq(object.id)).arel.compile_update({
41
- arel_table[counter_name] => object.send(counter_association).count(:all)
42
- }, primary_key)
43
- connection.update stmt
50
+ updates = { counter_name => object.send(counter_association).count(:all) }
51
+
52
+ if touch
53
+ names = touch if touch != true
54
+ updates.merge!(touch_attributes_with_time(*names))
55
+ end
56
+
57
+ unscoped.where(primary_key => object.id).update_all(updates)
44
58
  end
45
- return true
59
+
60
+ true
46
61
  end
47
62
 
48
63
  # A generic "counter updater" implementation, intended primarily to be
49
- # used by increment_counter and decrement_counter, but which may also
64
+ # used by #increment_counter and #decrement_counter, but which may also
50
65
  # be useful on its own. It simply does a direct SQL update for the record
51
66
  # with the given ID, altering the given hash of counters by the amount
52
67
  # given by the corresponding value:
53
68
  #
54
69
  # ==== Parameters
55
70
  #
56
- # * +id+ - The id of the object you wish to update a counter on or an Array of ids.
71
+ # * +id+ - The id of the object you wish to update a counter on or an array of ids.
57
72
  # * +counters+ - A Hash containing the names of the fields
58
73
  # to update as keys and the amount to update the field by as values.
74
+ # * <tt>:touch</tt> option - Touch timestamp columns when updating.
75
+ # If attribute names are passed, they are updated along with updated_at/on
76
+ # attributes.
59
77
  #
60
78
  # ==== Examples
61
79
  #
@@ -74,75 +92,78 @@ module ActiveRecord
74
92
  # # UPDATE posts
75
93
  # # SET comment_count = COALESCE(comment_count, 0) + 1
76
94
  # # WHERE id IN (10, 15)
95
+ #
96
+ # # For the Posts with id of 10 and 15, increment the comment_count by 1
97
+ # # and update the updated_at value for each counter.
98
+ # Post.update_counters [10, 15], comment_count: 1, touch: true
99
+ # # Executes the following SQL:
100
+ # # UPDATE posts
101
+ # # SET comment_count = COALESCE(comment_count, 0) + 1,
102
+ # # `updated_at` = '2016-10-13T09:59:23-05:00'
103
+ # # WHERE id IN (10, 15)
77
104
  def update_counters(id, counters)
78
- updates = counters.map do |counter_name, value|
79
- operator = value < 0 ? '-' : '+'
80
- quoted_column = connection.quote_column_name(counter_name)
81
- "#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{value.abs}"
82
- end
83
-
84
- unscoped.where(primary_key => id).update_all updates.join(', ')
105
+ unscoped.where!(primary_key => id).update_counters(counters)
85
106
  end
86
107
 
87
108
  # Increment a numeric field by one, via a direct SQL update.
88
109
  #
89
110
  # This method is used primarily for maintaining counter_cache columns that are
90
- # used to store aggregate values. For example, a DiscussionBoard may cache
111
+ # used to store aggregate values. For example, a +DiscussionBoard+ may cache
91
112
  # posts_count and comments_count to avoid running an SQL query to calculate the
92
113
  # number of posts and comments there are, each time it is displayed.
93
114
  #
94
115
  # ==== Parameters
95
116
  #
96
117
  # * +counter_name+ - The name of the field that should be incremented.
97
- # * +id+ - The id of the object that should be incremented or an Array of ids.
118
+ # * +id+ - The id of the object that should be incremented or an array of ids.
119
+ # * <tt>:touch</tt> - Touch timestamp columns when updating.
120
+ # Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
121
+ # touch that column or an array of symbols to touch just those ones.
98
122
  #
99
123
  # ==== Examples
100
124
  #
101
- # # Increment the post_count column for the record with an id of 5
102
- # DiscussionBoard.increment_counter(:post_count, 5)
103
- def increment_counter(counter_name, id)
104
- update_counters(id, counter_name => 1)
125
+ # # Increment the posts_count column for the record with an id of 5
126
+ # DiscussionBoard.increment_counter(:posts_count, 5)
127
+ #
128
+ # # Increment the posts_count column for the record with an id of 5
129
+ # # and update the updated_at value.
130
+ # DiscussionBoard.increment_counter(:posts_count, 5, touch: true)
131
+ def increment_counter(counter_name, id, touch: nil)
132
+ update_counters(id, counter_name => 1, touch: touch)
105
133
  end
106
134
 
107
135
  # Decrement a numeric field by one, via a direct SQL update.
108
136
  #
109
- # This works the same as increment_counter but reduces the column value by
137
+ # This works the same as #increment_counter but reduces the column value by
110
138
  # 1 instead of increasing it.
111
139
  #
112
140
  # ==== Parameters
113
141
  #
114
142
  # * +counter_name+ - The name of the field that should be decremented.
115
- # * +id+ - The id of the object that should be decremented or an Array of ids.
143
+ # * +id+ - The id of the object that should be decremented or an array of ids.
144
+ # * <tt>:touch</tt> - Touch timestamp columns when updating.
145
+ # Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
146
+ # touch that column or an array of symbols to touch just those ones.
116
147
  #
117
148
  # ==== Examples
118
149
  #
119
- # # Decrement the post_count column for the record with an id of 5
120
- # DiscussionBoard.decrement_counter(:post_count, 5)
121
- def decrement_counter(counter_name, id)
122
- update_counters(id, counter_name => -1)
150
+ # # Decrement the posts_count column for the record with an id of 5
151
+ # DiscussionBoard.decrement_counter(:posts_count, 5)
152
+ #
153
+ # # Decrement the posts_count column for the record with an id of 5
154
+ # # and update the updated_at value.
155
+ # DiscussionBoard.decrement_counter(:posts_count, 5, touch: true)
156
+ def decrement_counter(counter_name, id, touch: nil)
157
+ update_counters(id, counter_name => -1, touch: touch)
123
158
  end
124
159
  end
125
160
 
126
- protected
127
-
128
- def actually_destroyed?
129
- @_actually_destroyed
130
- end
131
-
132
- def clear_destroy_state
133
- @_actually_destroyed = nil
134
- end
135
-
136
161
  private
137
-
138
- def _create_record(*)
162
+ def _create_record(attribute_names = self.attribute_names)
139
163
  id = super
140
164
 
141
165
  each_counter_cached_associations do |association|
142
- if send(association.reflection.name)
143
- association.increment_counters
144
- @_after_create_counter_called = true
145
- end
166
+ association.increment_counters
146
167
  end
147
168
 
148
169
  id
@@ -155,9 +176,7 @@ module ActiveRecord
155
176
  each_counter_cached_associations do |association|
156
177
  foreign_key = association.reflection.foreign_key.to_sym
157
178
  unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == foreign_key
158
- if send(association.reflection.name)
159
- association.decrement_counters
160
- end
179
+ association.decrement_counters
161
180
  end
162
181
  end
163
182
  end
@@ -170,6 +189,5 @@ module ActiveRecord
170
189
  yield association(name.to_sym) if reflection.belongs_to? && reflection.counter_cache_column
171
190
  end
172
191
  end
173
-
174
192
  end
175
193
  end
@@ -0,0 +1,233 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/database_configurations/database_config"
4
+ require "active_record/database_configurations/hash_config"
5
+ require "active_record/database_configurations/url_config"
6
+
7
+ module ActiveRecord
8
+ # ActiveRecord::DatabaseConfigurations returns an array of DatabaseConfig
9
+ # objects (either a HashConfig or UrlConfig) that are constructed from the
10
+ # application's database configuration hash or URL string.
11
+ class DatabaseConfigurations
12
+ class InvalidConfigurationError < StandardError; end
13
+
14
+ attr_reader :configurations
15
+ delegate :any?, to: :configurations
16
+
17
+ def initialize(configurations = {})
18
+ @configurations = build_configs(configurations)
19
+ end
20
+
21
+ # Collects the configs for the environment and optionally the specification
22
+ # name passed in. To include replica configurations pass <tt>include_replicas: true</tt>.
23
+ #
24
+ # If a spec name is provided a single DatabaseConfig object will be
25
+ # returned, otherwise an array of DatabaseConfig objects will be
26
+ # returned that corresponds with the environment and type requested.
27
+ #
28
+ # ==== Options
29
+ #
30
+ # * <tt>env_name:</tt> The environment name. Defaults to +nil+ which will collect
31
+ # configs for all environments.
32
+ # * <tt>spec_name:</tt> The specification name (i.e. primary, animals, etc.). Defaults
33
+ # to +nil+.
34
+ # * <tt>include_replicas:</tt> Determines whether to include replicas in
35
+ # the returned list. Most of the time we're only iterating over the write
36
+ # connection (i.e. migrations don't need to run for the write and read connection).
37
+ # Defaults to +false+.
38
+ def configs_for(env_name: nil, spec_name: nil, include_replicas: false)
39
+ configs = env_with_configs(env_name)
40
+
41
+ unless include_replicas
42
+ configs = configs.select do |db_config|
43
+ !db_config.replica?
44
+ end
45
+ end
46
+
47
+ if spec_name
48
+ configs.find do |db_config|
49
+ db_config.spec_name == spec_name
50
+ end
51
+ else
52
+ configs
53
+ end
54
+ end
55
+
56
+ # Returns the config hash that corresponds with the environment
57
+ #
58
+ # If the application has multiple databases +default_hash+ will
59
+ # return the first config hash for the environment.
60
+ #
61
+ # { database: "my_db", adapter: "mysql2" }
62
+ def default_hash(env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call.to_s)
63
+ default = find_db_config(env)
64
+ default.config if default
65
+ end
66
+ alias :[] :default_hash
67
+
68
+ # Returns a single DatabaseConfig object based on the requested environment.
69
+ #
70
+ # If the application has multiple databases +find_db_config+ will return
71
+ # the first DatabaseConfig for the environment.
72
+ def find_db_config(env)
73
+ configurations.find do |db_config|
74
+ db_config.env_name == env.to_s ||
75
+ (db_config.for_current_env? && db_config.spec_name == env.to_s)
76
+ end
77
+ end
78
+
79
+ # Returns the DatabaseConfigurations object as a Hash.
80
+ def to_h
81
+ configs = configurations.reverse.inject({}) do |memo, db_config|
82
+ memo.merge(db_config.to_legacy_hash)
83
+ end
84
+
85
+ Hash[configs.to_a.reverse]
86
+ end
87
+
88
+ # Checks if the application's configurations are empty.
89
+ #
90
+ # Aliased to blank?
91
+ def empty?
92
+ configurations.empty?
93
+ end
94
+ alias :blank? :empty?
95
+
96
+ def each
97
+ throw_getter_deprecation(:each)
98
+ configurations.each { |config|
99
+ yield [config.env_name, config.config]
100
+ }
101
+ end
102
+
103
+ def first
104
+ throw_getter_deprecation(:first)
105
+ config = configurations.first
106
+ [config.env_name, config.config]
107
+ end
108
+
109
+ private
110
+ def env_with_configs(env = nil)
111
+ if env
112
+ configurations.select { |db_config| db_config.env_name == env }
113
+ else
114
+ configurations
115
+ end
116
+ end
117
+
118
+ def build_configs(configs)
119
+ return configs.configurations if configs.is_a?(DatabaseConfigurations)
120
+ return configs if configs.is_a?(Array)
121
+
122
+ db_configs = configs.flat_map do |env_name, config|
123
+ if config.is_a?(Hash) && config.all? { |_, v| v.is_a?(Hash) }
124
+ walk_configs(env_name.to_s, config)
125
+ else
126
+ build_db_config_from_raw_config(env_name.to_s, "primary", config)
127
+ end
128
+ end
129
+
130
+ current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call.to_s
131
+
132
+ unless db_configs.find(&:for_current_env?)
133
+ db_configs << environment_url_config(current_env, "primary", {})
134
+ end
135
+
136
+ merge_db_environment_variables(current_env, db_configs.compact)
137
+ end
138
+
139
+ def walk_configs(env_name, config)
140
+ config.map do |spec_name, sub_config|
141
+ build_db_config_from_raw_config(env_name, spec_name.to_s, sub_config)
142
+ end
143
+ end
144
+
145
+ def build_db_config_from_raw_config(env_name, spec_name, config)
146
+ case config
147
+ when String
148
+ build_db_config_from_string(env_name, spec_name, config)
149
+ when Hash
150
+ build_db_config_from_hash(env_name, spec_name, config.stringify_keys)
151
+ else
152
+ raise InvalidConfigurationError, "'{ #{env_name} => #{config} }' is not a valid configuration. Expected '#{config}' to be a URL string or a Hash."
153
+ end
154
+ end
155
+
156
+ def build_db_config_from_string(env_name, spec_name, config)
157
+ url = config
158
+ uri = URI.parse(url)
159
+ if uri.scheme
160
+ ActiveRecord::DatabaseConfigurations::UrlConfig.new(env_name, spec_name, url)
161
+ else
162
+ raise InvalidConfigurationError, "'{ #{env_name} => #{config} }' is not a valid configuration. Expected '#{config}' to be a URL string or a Hash."
163
+ end
164
+ end
165
+
166
+ def build_db_config_from_hash(env_name, spec_name, config)
167
+ if config.has_key?("url")
168
+ url = config["url"]
169
+ config_without_url = config.dup
170
+ config_without_url.delete "url"
171
+
172
+ ActiveRecord::DatabaseConfigurations::UrlConfig.new(env_name, spec_name, url, config_without_url)
173
+ else
174
+ ActiveRecord::DatabaseConfigurations::HashConfig.new(env_name, spec_name, config)
175
+ end
176
+ end
177
+
178
+ def merge_db_environment_variables(current_env, configs)
179
+ configs.map do |config|
180
+ next config if config.url_config? || config.env_name != current_env
181
+
182
+ url_config = environment_url_config(current_env, config.spec_name, config.config)
183
+ url_config || config
184
+ end
185
+ end
186
+
187
+ def environment_url_config(env, spec_name, config)
188
+ url = environment_value_for(spec_name)
189
+ return unless url
190
+
191
+ ActiveRecord::DatabaseConfigurations::UrlConfig.new(env, spec_name, url, config)
192
+ end
193
+
194
+ def environment_value_for(spec_name)
195
+ spec_env_key = "#{spec_name.upcase}_DATABASE_URL"
196
+ url = ENV[spec_env_key]
197
+ url ||= ENV["DATABASE_URL"] if spec_name == "primary"
198
+ url
199
+ end
200
+
201
+ def method_missing(method, *args, &blk)
202
+ case method
203
+ when :fetch
204
+ throw_getter_deprecation(method)
205
+ configs_for(env_name: args.first)
206
+ when :values
207
+ throw_getter_deprecation(method)
208
+ configurations.map(&:config)
209
+ when :[]=
210
+ throw_setter_deprecation(method)
211
+
212
+ env_name = args[0]
213
+ config = args[1]
214
+
215
+ remaining_configs = configurations.reject { |db_config| db_config.env_name == env_name }
216
+ new_config = build_configs(env_name => config)
217
+ new_configs = remaining_configs + new_config
218
+
219
+ ActiveRecord::Base.configurations = new_configs
220
+ else
221
+ raise NotImplementedError, "`ActiveRecord::Base.configurations` in Rails 6 now returns an object instead of a hash. The `#{method}` method is not supported. Please use `configs_for` or consult the documentation for supported methods."
222
+ end
223
+ end
224
+
225
+ def throw_setter_deprecation(method)
226
+ ActiveSupport::Deprecation.warn("Setting `ActiveRecord::Base.configurations` with `#{method}` is deprecated. Use `ActiveRecord::Base.configurations=` directly to set the configurations instead.")
227
+ end
228
+
229
+ def throw_getter_deprecation(method)
230
+ ActiveSupport::Deprecation.warn("`ActiveRecord::Base.configurations` no longer returns a hash. Methods that act on the hash like `#{method}` are deprecated and will be removed in Rails 6.1. Use the `configs_for` method to collect and iterate over the database configurations.")
231
+ end
232
+ end
233
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class DatabaseConfigurations
5
+ # ActiveRecord::Base.configurations will return either a HashConfig or
6
+ # UrlConfig respectively. It will never return a DatabaseConfig object,
7
+ # as this is the parent class for the types of database configuration objects.
8
+ class DatabaseConfig # :nodoc:
9
+ attr_reader :env_name, :spec_name
10
+
11
+ def initialize(env_name, spec_name)
12
+ @env_name = env_name
13
+ @spec_name = spec_name
14
+ end
15
+
16
+ def replica?
17
+ raise NotImplementedError
18
+ end
19
+
20
+ def migrations_paths
21
+ raise NotImplementedError
22
+ end
23
+
24
+ def url_config?
25
+ false
26
+ end
27
+
28
+ def to_legacy_hash
29
+ { env_name => config }
30
+ end
31
+
32
+ def for_current_env?
33
+ env_name == ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
34
+ end
35
+ end
36
+ end
37
+ end