activerecord 4.2.0 → 6.1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1221 -796
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +267 -249
  8. data/lib/active_record/association_relation.rb +45 -7
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +172 -67
  11. data/lib/active_record/associations/association_scope.rb +105 -129
  12. data/lib/active_record/associations/belongs_to_association.rb +85 -59
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -33
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +168 -279
  22. data/lib/active_record/associations/collection_proxy.rb +263 -155
  23. data/lib/active_record/associations/foreign_association.rb +33 -0
  24. data/lib/active_record/associations/has_many_association.rb +57 -84
  25. data/lib/active_record/associations/has_many_through_association.rb +70 -82
  26. data/lib/active_record/associations/has_one_association.rb +74 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +175 -164
  32. data/lib/active_record/associations/preloader/association.rb +107 -112
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +99 -96
  35. data/lib/active_record/associations/singular_association.rb +18 -45
  36. data/lib/active_record/associations/through_association.rb +49 -24
  37. data/lib/active_record/associations.rb +1845 -1597
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -138
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -36
  46. data/lib/active_record/attribute_methods/write.rb +25 -56
  47. data/lib/active_record/attribute_methods.rb +153 -162
  48. data/lib/active_record/attributes.rb +234 -70
  49. data/lib/active_record/autosave_association.rb +157 -69
  50. data/lib/active_record/base.rb +49 -50
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +46 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +271 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +78 -161
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -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 +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +499 -293
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +595 -382
  119. data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -389
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +488 -243
  133. data/lib/active_record/counter_cache.rb +71 -50
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +273 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +212 -94
  143. data/lib/active_record/errors.rb +225 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +11 -6
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +273 -496
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +64 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +52 -0
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +103 -95
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +298 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +685 -309
  170. data/lib/active_record/model_schema.rb +420 -113
  171. data/lib/active_record/nested_attributes.rb +265 -216
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +574 -135
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +175 -54
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +533 -216
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +485 -310
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +326 -244
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +318 -256
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +99 -84
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +139 -96
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -409
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +23 -21
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -342
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -26
  209. data/lib/active_record/scoping/default.rb +96 -82
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +133 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +366 -129
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +291 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +181 -152
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -41
  231. data/lib/active_record/type/date_time.rb +4 -38
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +33 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +65 -48
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +44 -28
  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/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -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/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -10
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  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.tt +22 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +175 -65
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  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 -23
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  347. data/lib/active_record/attribute.rb +0 -149
  348. data/lib/active_record/attribute_decorators.rb +0 -66
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  352. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  353. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  354. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  355. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  356. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  357. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  358. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  359. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  360. data/lib/active_record/type/big_integer.rb +0 -13
  361. data/lib/active_record/type/binary.rb +0 -50
  362. data/lib/active_record/type/boolean.rb +0 -30
  363. data/lib/active_record/type/decimal.rb +0 -40
  364. data/lib/active_record/type/decorator.rb +0 -14
  365. data/lib/active_record/type/float.rb +0 -19
  366. data/lib/active_record/type/integer.rb +0 -55
  367. data/lib/active_record/type/mutable.rb +0 -16
  368. data/lib/active_record/type/numeric.rb +0 -36
  369. data/lib/active_record/type/string.rb +0 -36
  370. data/lib/active_record/type/time_value.rb +0 -38
  371. data/lib/active_record/type/value.rb +0 -101
  372. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  373. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  374. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,7 +1,10 @@
1
- require 'thread'
2
- require 'active_support/core_ext/hash/indifferent_access'
3
- require 'active_support/core_ext/object/duplicable'
4
- require 'active_support/core_ext/string/filters'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/enumerable"
4
+ require "active_support/core_ext/hash/indifferent_access"
5
+ require "active_support/core_ext/string/filters"
6
+ require "active_support/parameter_filter"
7
+ require "concurrent/map"
5
8
 
6
9
  module ActiveRecord
7
10
  module Core
@@ -16,9 +19,28 @@ module ActiveRecord
16
19
  # retrieved on both a class and instance level by calling +logger+.
17
20
  mattr_accessor :logger, instance_writer: false
18
21
 
22
+ ##
23
+ # :singleton-method:
24
+ #
25
+ # Specifies if the methods calling database queries should be logged below
26
+ # their relevant queries. Defaults to false.
27
+ mattr_accessor :verbose_query_logs, instance_writer: false, default: false
28
+
29
+ ##
30
+ # :singleton-method:
31
+ #
32
+ # Specifies the names of the queues used by background jobs.
33
+ mattr_accessor :queues, instance_accessor: false, default: {}
34
+
35
+ ##
36
+ # :singleton-method:
37
+ #
38
+ # Specifies the job used to destroy associations in the background
39
+ class_attribute :destroy_association_async_job, instance_writer: false, instance_predicate: false, default: false
40
+
19
41
  ##
20
42
  # Contains the database configuration - as is typically stored in config/database.yml -
21
- # as a Hash.
43
+ # as an ActiveRecord::DatabaseConfigurations object.
22
44
  #
23
45
  # For example, the following database.yml...
24
46
  #
@@ -32,22 +54,18 @@ module ActiveRecord
32
54
  #
33
55
  # ...would result in ActiveRecord::Base.configurations to look like this:
34
56
  #
35
- # {
36
- # 'development' => {
37
- # 'adapter' => 'sqlite3',
38
- # 'database' => 'db/development.sqlite3'
39
- # },
40
- # 'production' => {
41
- # 'adapter' => 'sqlite3',
42
- # 'database' => 'db/production.sqlite3'
43
- # }
44
- # }
57
+ # #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
58
+ # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
59
+ # @name="primary", @config={adapter: "sqlite3", database: "db/development.sqlite3"}>,
60
+ # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
61
+ # @name="primary", @config={adapter: "sqlite3", database: "db/production.sqlite3"}>
62
+ # ]>
45
63
  def self.configurations=(config)
46
- @@configurations = ActiveRecord::ConnectionHandling::MergeAndResolveDefaultUrlConfig.new(config).resolve
64
+ @@configurations = ActiveRecord::DatabaseConfigurations.new(config)
47
65
  end
48
66
  self.configurations = {}
49
67
 
50
- # Returns fully resolved configurations hash
68
+ # Returns fully resolved ActiveRecord::DatabaseConfigurations object
51
69
  def self.configurations
52
70
  @@configurations
53
71
  end
@@ -56,8 +74,7 @@ module ActiveRecord
56
74
  # :singleton-method:
57
75
  # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
58
76
  # dates and times from the database. This is set to :utc by default.
59
- mattr_accessor :default_timezone, instance_writer: false
60
- self.default_timezone = :utc
77
+ mattr_accessor :default_timezone, instance_writer: false, default: :utc
61
78
 
62
79
  ##
63
80
  # :singleton-method:
@@ -67,148 +84,363 @@ module ActiveRecord
67
84
  # ActiveRecord::Schema file which can be loaded into any database that
68
85
  # supports migrations. Use :ruby if you want to have different database
69
86
  # adapters for, e.g., your development and test environments.
70
- mattr_accessor :schema_format, instance_writer: false
71
- self.schema_format = :ruby
87
+ mattr_accessor :schema_format, instance_writer: false, default: :ruby
88
+
89
+ ##
90
+ # :singleton-method:
91
+ # Specifies if an error should be raised if the query has an order being
92
+ # ignored when doing batch queries. Useful in applications where the
93
+ # scope being ignored is error-worthy, rather than a warning.
94
+ mattr_accessor :error_on_ignored_order, instance_writer: false, default: false
72
95
 
73
96
  ##
74
97
  # :singleton-method:
75
98
  # Specify whether or not to use timestamps for migration versions
76
- mattr_accessor :timestamped_migrations, instance_writer: false
77
- self.timestamped_migrations = true
99
+ mattr_accessor :timestamped_migrations, instance_writer: false, default: true
78
100
 
79
101
  ##
80
102
  # :singleton-method:
81
103
  # Specify whether schema dump should happen at the end of the
82
- # db:migrate rake task. This is true by default, which is useful for the
104
+ # db:migrate rails command. This is true by default, which is useful for the
83
105
  # development environment. This should ideally be false in the production
84
106
  # environment where dumping schema is rarely needed.
85
- mattr_accessor :dump_schema_after_migration, instance_writer: false
86
- self.dump_schema_after_migration = true
107
+ mattr_accessor :dump_schema_after_migration, instance_writer: false, default: true
108
+
109
+ ##
110
+ # :singleton-method:
111
+ # Specifies which database schemas to dump when calling db:schema:dump.
112
+ # If the value is :schema_search_path (the default), any schemas listed in
113
+ # schema_search_path are dumped. Use :all to dump all schemas regardless
114
+ # of schema_search_path, or a string of comma separated schemas for a
115
+ # custom list.
116
+ mattr_accessor :dump_schemas, instance_writer: false, default: :schema_search_path
117
+
118
+ ##
119
+ # :singleton-method:
120
+ # Specify a threshold for the size of query result sets. If the number of
121
+ # records in the set exceeds the threshold, a warning is logged. This can
122
+ # be used to identify queries which load thousands of records and
123
+ # potentially cause memory bloat.
124
+ mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false
125
+
126
+ ##
127
+ # :singleton-method:
128
+ # Show a warning when Rails couldn't parse your database.yml
129
+ # for multiple databases.
130
+ mattr_accessor :suppress_multiple_database_warning, instance_writer: false, default: false
87
131
 
88
132
  mattr_accessor :maintain_test_schema, instance_accessor: false
89
133
 
90
- def self.disable_implicit_join_references=(value)
91
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
92
- Implicit join references were removed with Rails 4.1.
93
- Make sure to remove this configuration because it does nothing.
94
- MSG
95
- end
134
+ class_attribute :belongs_to_required_by_default, instance_accessor: false
135
+
136
+ ##
137
+ # :singleton-method:
138
+ # Set the application to log or raise when an association violates strict loading.
139
+ # Defaults to :raise.
140
+ mattr_accessor :action_on_strict_loading_violation, instance_accessor: false, default: :raise
141
+
142
+ class_attribute :strict_loading_by_default, instance_accessor: false, default: false
143
+
144
+ mattr_accessor :writing_role, instance_accessor: false, default: :writing
145
+
146
+ mattr_accessor :reading_role, instance_accessor: false, default: :reading
147
+
148
+ mattr_accessor :has_many_inversing, instance_accessor: false, default: false
96
149
 
97
150
  class_attribute :default_connection_handler, instance_writer: false
98
- class_attribute :find_by_statement_cache
151
+
152
+ class_attribute :default_role, instance_writer: false
153
+
154
+ class_attribute :default_shard, instance_writer: false
155
+
156
+ mattr_accessor :legacy_connection_handling, instance_writer: false, default: true
157
+
158
+ # Application configurable boolean that instructs the YAML Coder to use
159
+ # an unsafe load if set to true.
160
+ mattr_accessor :use_yaml_unsafe_load, instance_writer: false, default: false
161
+
162
+ # Application configurable array that provides additional permitted classes
163
+ # to Psych safe_load in the YAML Coder
164
+ mattr_accessor :yaml_column_permitted_classes, instance_writer: false, default: [Symbol]
165
+
166
+ ##
167
+ # :singleton-method:
168
+ # Application configurable boolean that denotes whether or not to raise
169
+ # an exception when the PostgreSQLAdapter is provided with an integer that is
170
+ # wider than signed 64bit representation
171
+ mattr_accessor :raise_int_wider_than_64bit, instance_writer: false, default: true
172
+
173
+ self.filter_attributes = []
99
174
 
100
175
  def self.connection_handler
101
- ActiveRecord::RuntimeRegistry.connection_handler || default_connection_handler
176
+ Thread.current.thread_variable_get(:ar_connection_handler) || default_connection_handler
102
177
  end
103
178
 
104
179
  def self.connection_handler=(handler)
105
- ActiveRecord::RuntimeRegistry.connection_handler = handler
180
+ Thread.current.thread_variable_set(:ar_connection_handler, handler)
181
+ end
182
+
183
+ def self.connection_handlers
184
+ unless legacy_connection_handling
185
+ raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
186
+ end
187
+
188
+ @@connection_handlers ||= {}
189
+ end
190
+
191
+ def self.connection_handlers=(handlers)
192
+ unless legacy_connection_handling
193
+ raise NotImplementedError, "The new connection handling does not setting support multiple connection handlers."
194
+ end
195
+
196
+ @@connection_handlers = handlers
197
+ end
198
+
199
+ # Returns the symbol representing the current connected role.
200
+ #
201
+ # ActiveRecord::Base.connected_to(role: :writing) do
202
+ # ActiveRecord::Base.current_role #=> :writing
203
+ # end
204
+ #
205
+ # ActiveRecord::Base.connected_to(role: :reading) do
206
+ # ActiveRecord::Base.current_role #=> :reading
207
+ # end
208
+ def self.current_role
209
+ if ActiveRecord::Base.legacy_connection_handling
210
+ connection_handlers.key(connection_handler) || default_role
211
+ else
212
+ connected_to_stack.reverse_each do |hash|
213
+ return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
214
+ return hash[:role] if hash[:role] && hash[:klasses].include?(connection_classes)
215
+ end
216
+
217
+ default_role
218
+ end
219
+ end
220
+
221
+ # Returns the symbol representing the current connected shard.
222
+ #
223
+ # ActiveRecord::Base.connected_to(role: :reading) do
224
+ # ActiveRecord::Base.current_shard #=> :default
225
+ # end
226
+ #
227
+ # ActiveRecord::Base.connected_to(role: :writing, shard: :one) do
228
+ # ActiveRecord::Base.current_shard #=> :one
229
+ # end
230
+ def self.current_shard
231
+ connected_to_stack.reverse_each do |hash|
232
+ return hash[:shard] if hash[:shard] && hash[:klasses].include?(Base)
233
+ return hash[:shard] if hash[:shard] && hash[:klasses].include?(connection_classes)
234
+ end
235
+
236
+ default_shard
237
+ end
238
+
239
+ # Returns the symbol representing the current setting for
240
+ # preventing writes.
241
+ #
242
+ # ActiveRecord::Base.connected_to(role: :reading) do
243
+ # ActiveRecord::Base.current_preventing_writes #=> true
244
+ # end
245
+ #
246
+ # ActiveRecord::Base.connected_to(role: :writing) do
247
+ # ActiveRecord::Base.current_preventing_writes #=> false
248
+ # end
249
+ def self.current_preventing_writes
250
+ if legacy_connection_handling
251
+ connection_handler.prevent_writes
252
+ else
253
+ connected_to_stack.reverse_each do |hash|
254
+ return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
255
+ return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_classes)
256
+ end
257
+
258
+ false
259
+ end
260
+ end
261
+
262
+ def self.connected_to_stack # :nodoc:
263
+ if connected_to_stack = Thread.current.thread_variable_get(:ar_connected_to_stack)
264
+ connected_to_stack
265
+ else
266
+ connected_to_stack = Concurrent::Array.new
267
+ Thread.current.thread_variable_set(:ar_connected_to_stack, connected_to_stack)
268
+ connected_to_stack
269
+ end
270
+ end
271
+
272
+ def self.connection_class=(b) # :nodoc:
273
+ @connection_class = b
274
+ end
275
+
276
+ def self.connection_class # :nodoc
277
+ @connection_class ||= false
278
+ end
279
+
280
+ def self.connection_class? # :nodoc:
281
+ self.connection_class
282
+ end
283
+
284
+ def self.connection_classes # :nodoc:
285
+ klass = self
286
+
287
+ until klass == Base
288
+ break if klass.connection_class?
289
+ klass = klass.superclass
290
+ end
291
+
292
+ klass
293
+ end
294
+
295
+ def self.allow_unsafe_raw_sql # :nodoc:
296
+ ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql is deprecated and will be removed in Rails 7.0")
297
+ end
298
+
299
+ def self.allow_unsafe_raw_sql=(value) # :nodoc:
300
+ ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql= is deprecated and will be removed in Rails 7.0")
106
301
  end
107
302
 
108
303
  self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
304
+ self.default_role = writing_role
305
+ self.default_shard = :default
306
+
307
+ def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
308
+ case action_on_strict_loading_violation
309
+ when :raise
310
+ message = "`#{owner}` is marked for strict_loading. The `#{reflection.klass}` association named `:#{reflection.name}` cannot be lazily loaded."
311
+ raise ActiveRecord::StrictLoadingViolationError.new(message)
312
+ when :log
313
+ name = "strict_loading_violation.active_record"
314
+ ActiveSupport::Notifications.instrument(name, owner: owner, reflection: reflection)
315
+ end
316
+ end
109
317
  end
110
318
 
111
319
  module ClassMethods
112
- def allocate
113
- define_attribute_methods
114
- super
115
- end
116
-
117
- def initialize_find_by_cache
118
- self.find_by_statement_cache = {}.extend(Mutex_m)
320
+ def initialize_find_by_cache # :nodoc:
321
+ @find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
119
322
  end
120
323
 
121
- def inherited(child_class)
324
+ def inherited(child_class) # :nodoc:
325
+ # initialize cache at class definition for thread safety
122
326
  child_class.initialize_find_by_cache
327
+ unless child_class.base_class?
328
+ klass = self
329
+ until klass.base_class?
330
+ klass.initialize_find_by_cache
331
+ klass = klass.superclass
332
+ end
333
+ end
123
334
  super
124
335
  end
125
336
 
126
- def find(*ids)
337
+ def find(*ids) # :nodoc:
127
338
  # We don't have cache keys for this stuff yet
128
339
  return super unless ids.length == 1
129
- # Allow symbols to super to maintain compatibility for deprecated finders until Rails 5
130
- return super if ids.first.kind_of?(Symbol)
131
- return super if block_given? ||
132
- primary_key.nil? ||
133
- default_scopes.any? ||
134
- columns_hash.include?(inheritance_column) ||
135
- ids.first.kind_of?(Array)
136
-
137
- id = ids.first
138
- if ActiveRecord::Base === id
139
- id = id.id
140
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
141
- You are passing an instance of ActiveRecord::Base to `find`.
142
- Please pass the id of the object by calling `.id`
143
- MSG
144
- end
340
+ return super if block_given? || primary_key.nil? || scope_attributes?
341
+
342
+ id = ids.first
343
+
344
+ return super if StatementCache.unsupported_value?(id)
345
+
145
346
  key = primary_key
146
347
 
147
- s = find_by_statement_cache[key] || find_by_statement_cache.synchronize {
148
- find_by_statement_cache[key] ||= StatementCache.create(connection) { |params|
149
- where(key => params.bind).limit(1)
150
- }
348
+ statement = cached_find_by_statement(key) { |params|
349
+ where(key => params.bind).limit(1)
151
350
  }
152
- record = s.execute([id], self, connection).first
153
- unless record
154
- raise RecordNotFound, "Couldn't find #{name} with '#{primary_key}'=#{id}"
155
- end
156
- record
157
- rescue RangeError
158
- raise RecordNotFound, "Couldn't find #{name} with an out of range value for '#{primary_key}'"
351
+
352
+ statement.execute([id], connection).first ||
353
+ raise(RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id))
159
354
  end
160
355
 
161
- def find_by(*args)
162
- return super if current_scope || !(Hash === args.first) || reflect_on_all_aggregations.any?
163
- return super if default_scopes.any?
356
+ def find_by(*args) # :nodoc:
357
+ return super if scope_attributes?
164
358
 
165
359
  hash = args.first
360
+ return super unless Hash === hash
166
361
 
167
- return super if hash.values.any? { |v|
168
- v.nil? || Array === v || Hash === v
169
- }
362
+ hash = hash.each_with_object({}) do |(key, value), h|
363
+ key = key.to_s
364
+ key = attribute_aliases[key] || key
170
365
 
171
- # We can't cache Post.find_by(author: david) ...yet
172
- return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
366
+ return super if reflect_on_aggregation(key)
173
367
 
174
- key = hash.keys
368
+ reflection = _reflect_on_association(key)
175
369
 
176
- klass = self
177
- s = find_by_statement_cache[key] || find_by_statement_cache.synchronize {
178
- find_by_statement_cache[key] ||= StatementCache.create(connection) { |params|
179
- wheres = key.each_with_object({}) { |param,o|
180
- o[param] = params.bind
181
- }
182
- klass.where(wheres).limit(1)
183
- }
370
+ if !reflection
371
+ value = value.id if value.respond_to?(:id)
372
+ elsif reflection.belongs_to? && !reflection.polymorphic?
373
+ key = reflection.join_foreign_key
374
+ pkey = reflection.join_primary_key
375
+ value = value.public_send(pkey) if value.respond_to?(pkey)
376
+ end
377
+
378
+ if !columns_hash.key?(key) || StatementCache.unsupported_value?(value)
379
+ return super
380
+ end
381
+
382
+ h[key] = value
383
+ end
384
+
385
+ keys = hash.keys
386
+ statement = cached_find_by_statement(keys) { |params|
387
+ wheres = keys.index_with { params.bind }
388
+ where(wheres).limit(1)
184
389
  }
390
+
185
391
  begin
186
- s.execute(hash.values, self, connection).first
187
- rescue TypeError => e
188
- raise ActiveRecord::StatementInvalid.new(e.message, e)
189
- rescue RangeError
190
- nil
392
+ statement.execute(hash.values, connection).first
393
+ rescue TypeError
394
+ raise ActiveRecord::StatementInvalid
191
395
  end
192
396
  end
193
397
 
194
- def find_by!(*args)
195
- find_by(*args) or raise RecordNotFound.new("Couldn't find #{name}")
398
+ def find_by!(*args) # :nodoc:
399
+ find_by(*args) || raise(RecordNotFound.new("Couldn't find #{name}", name))
196
400
  end
197
401
 
198
- def initialize_generated_modules
402
+ def initialize_generated_modules # :nodoc:
199
403
  generated_association_methods
200
404
  end
201
405
 
202
- def generated_association_methods
406
+ def generated_association_methods # :nodoc:
203
407
  @generated_association_methods ||= begin
204
408
  mod = const_set(:GeneratedAssociationMethods, Module.new)
409
+ private_constant :GeneratedAssociationMethods
205
410
  include mod
411
+
206
412
  mod
207
413
  end
208
414
  end
209
415
 
416
+ # Returns columns which shouldn't be exposed while calling +#inspect+.
417
+ def filter_attributes
418
+ if defined?(@filter_attributes)
419
+ @filter_attributes
420
+ else
421
+ superclass.filter_attributes
422
+ end
423
+ end
424
+
425
+ # Specifies columns which shouldn't be exposed while calling +#inspect+.
426
+ def filter_attributes=(filter_attributes)
427
+ @inspection_filter = nil
428
+ @filter_attributes = filter_attributes
429
+ end
430
+
431
+ def inspection_filter # :nodoc:
432
+ if defined?(@filter_attributes)
433
+ @inspection_filter ||= begin
434
+ mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
435
+ ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
436
+ end
437
+ else
438
+ superclass.inspection_filter
439
+ end
440
+ end
441
+
210
442
  # Returns a string like 'Post(id:integer, title:string, body:text)'
211
- def inspect
443
+ def inspect # :nodoc:
212
444
  if self == Base
213
445
  super
214
446
  elsif abstract_class?
@@ -216,48 +448,63 @@ module ActiveRecord
216
448
  elsif !connected?
217
449
  "#{super} (call '#{super}.connection' to establish a connection)"
218
450
  elsif table_exists?
219
- attr_list = columns.map { |c| "#{c.name}: #{c.type}" } * ', '
451
+ attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
220
452
  "#{super}(#{attr_list})"
221
453
  else
222
454
  "#{super}(Table doesn't exist)"
223
455
  end
224
456
  end
225
457
 
226
- # Overwrite the default class equality method to provide support for association proxies.
227
- def ===(object)
458
+ # Overwrite the default class equality method to provide support for decorated models.
459
+ def ===(object) # :nodoc:
228
460
  object.is_a?(self)
229
461
  end
230
462
 
231
463
  # Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
232
464
  #
233
465
  # class Post < ActiveRecord::Base
234
- # scope :published_and_commented, -> { published.and(self.arel_table[:comments_count].gt(0)) }
466
+ # scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
235
467
  # end
236
468
  def arel_table # :nodoc:
237
- @arel_table ||= Arel::Table.new(table_name, arel_engine)
469
+ @arel_table ||= Arel::Table.new(table_name, klass: self)
238
470
  end
239
471
 
240
- # Returns the Arel engine.
241
- def arel_engine # :nodoc:
242
- @arel_engine ||=
243
- if Base == self || connection_handler.retrieve_connection_pool(self)
244
- self
245
- else
246
- superclass.arel_engine
247
- end
472
+ def arel_attribute(name, table = arel_table) # :nodoc:
473
+ table[name]
474
+ end
475
+ deprecate :arel_attribute
476
+
477
+ def predicate_builder # :nodoc:
478
+ @predicate_builder ||= PredicateBuilder.new(table_metadata)
479
+ end
480
+
481
+ def type_caster # :nodoc:
482
+ TypeCaster::Map.new(self)
483
+ end
484
+
485
+ def _internal? # :nodoc:
486
+ false
487
+ end
488
+
489
+ def cached_find_by_statement(key, &block) # :nodoc:
490
+ cache = @find_by_statement_cache[connection.prepared_statements]
491
+ cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
248
492
  end
249
493
 
250
494
  private
495
+ def relation
496
+ relation = Relation.create(self)
251
497
 
252
- def relation #:nodoc:
253
- relation = Relation.create(self, arel_table)
498
+ if finder_needs_type_condition? && !ignore_default_scope?
499
+ relation.where!(type_condition)
500
+ else
501
+ relation
502
+ end
503
+ end
254
504
 
255
- if finder_needs_type_condition?
256
- relation.where(type_condition).create_with(inheritance_column.to_sym => sti_name)
257
- else
258
- relation
505
+ def table_metadata
506
+ TableMetadata.new(self, arel_table)
259
507
  end
260
- end
261
508
  end
262
509
 
263
510
  # New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
@@ -268,39 +515,50 @@ module ActiveRecord
268
515
  # ==== Example:
269
516
  # # Instantiates a single new object
270
517
  # User.new(first_name: 'Jamie')
271
- def initialize(attributes = nil, options = {})
272
- @attributes = self.class._default_attributes.dup
518
+ def initialize(attributes = nil)
519
+ @new_record = true
520
+ @attributes = self.class._default_attributes.deep_dup
273
521
 
274
522
  init_internals
275
523
  initialize_internals_callback
276
524
 
277
- self.class.define_attribute_methods
278
- # +options+ argument is only needed to make protected_attributes gem easier to hook.
279
- # Remove it when we drop support to this gem.
280
- init_attributes(attributes, options) if attributes
525
+ assign_attributes(attributes) if attributes
281
526
 
282
527
  yield self if block_given?
283
528
  _run_initialize_callbacks
284
529
  end
285
530
 
286
- # Initialize an empty model object from +coder+. +coder+ must contain
287
- # the attributes necessary for initializing an empty model object. For
288
- # example:
531
+ # Initialize an empty model object from +coder+. +coder+ should be
532
+ # the result of previously encoding an Active Record model, using
533
+ # #encode_with.
289
534
  #
290
535
  # class Post < ActiveRecord::Base
291
536
  # end
292
537
  #
538
+ # old_post = Post.new(title: "hello world")
539
+ # coder = {}
540
+ # old_post.encode_with(coder)
541
+ #
293
542
  # post = Post.allocate
294
- # post.init_with('attributes' => { 'title' => 'hello world' })
543
+ # post.init_with(coder)
295
544
  # post.title # => 'hello world'
296
- def init_with(coder)
297
- @attributes = coder['attributes']
545
+ def init_with(coder, &block)
546
+ coder = LegacyYamlAdapter.convert(self.class, coder)
547
+ attributes = self.class.yaml_encoder.decode(coder)
548
+ init_with_attributes(attributes, coder["new_record"], &block)
549
+ end
298
550
 
299
- init_internals
551
+ ##
552
+ # Initialize an empty model object from +attributes+.
553
+ # +attributes+ should be an attributes object, and unlike the
554
+ # `initialize` method, no assignment calls are made per attribute.
555
+ def init_with_attributes(attributes, new_record = false) # :nodoc:
556
+ @new_record = new_record
557
+ @attributes = attributes
300
558
 
301
- @new_record = coder['new_record']
559
+ init_internals
302
560
 
303
- self.class.define_attribute_methods
561
+ yield self if block_given?
304
562
 
305
563
  _run_find_callbacks
306
564
  _run_initialize_callbacks
@@ -336,23 +594,22 @@ module ActiveRecord
336
594
 
337
595
  ##
338
596
  def initialize_dup(other) # :nodoc:
339
- @attributes = @attributes.dup
340
- @attributes.reset(self.class.primary_key)
597
+ @attributes = @attributes.deep_dup
598
+ @attributes.reset(@primary_key)
341
599
 
342
600
  _run_initialize_callbacks
343
601
 
344
- @aggregation_cache = {}
345
- @association_cache = {}
346
-
347
- @new_record = true
348
- @destroyed = false
602
+ @new_record = true
603
+ @previously_new_record = false
604
+ @destroyed = false
605
+ @_start_transaction_state = nil
349
606
 
350
607
  super
351
608
  end
352
609
 
353
610
  # Populate +coder+ with attributes about this record that should be
354
611
  # serialized. The structure of +coder+ defined in this method is
355
- # guaranteed to match the structure of +coder+ passed to the +init_with+
612
+ # guaranteed to match the structure of +coder+ passed to the #init_with
356
613
  # method.
357
614
  #
358
615
  # Example:
@@ -363,10 +620,9 @@ module ActiveRecord
363
620
  # Post.new.encode_with(coder)
364
621
  # coder # => {"attributes" => {"id" => nil, ... }}
365
622
  def encode_with(coder)
366
- # FIXME: Remove this when we better serialize attributes
367
- coder['raw_attributes'] = attributes_before_type_cast
368
- coder['attributes'] = @attributes
369
- coder['new_record'] = new_record?
623
+ self.class.yaml_encoder.encode(@attributes, coder)
624
+ coder["new_record"] = new_record?
625
+ coder["active_record_yaml_version"] = 2
370
626
  end
371
627
 
372
628
  # Returns true if +comparison_object+ is the same exact object, or +comparison_object+
@@ -390,7 +646,7 @@ module ActiveRecord
390
646
  # [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
391
647
  def hash
392
648
  if id
393
- id.hash
649
+ self.class.hash ^ id.hash
394
650
  else
395
651
  super
396
652
  end
@@ -412,18 +668,41 @@ module ActiveRecord
412
668
  # Allows sort on objects
413
669
  def <=>(other_object)
414
670
  if other_object.is_a?(self.class)
415
- self.to_key <=> other_object.to_key
671
+ to_key <=> other_object.to_key
416
672
  else
417
673
  super
418
674
  end
419
675
  end
420
676
 
421
- # Returns +true+ if the record is read only. Records loaded through joins with piggy-back
422
- # attributes will be marked as read only since they cannot be saved.
677
+ def present? # :nodoc:
678
+ true
679
+ end
680
+
681
+ def blank? # :nodoc:
682
+ false
683
+ end
684
+
685
+ # Returns +true+ if the record is read only.
423
686
  def readonly?
424
687
  @readonly
425
688
  end
426
689
 
690
+ # Returns +true+ if the record is in strict_loading mode.
691
+ def strict_loading?
692
+ @strict_loading
693
+ end
694
+
695
+ # Sets the record to strict_loading mode. This will raise an error
696
+ # if the record tries to lazily load an association.
697
+ #
698
+ # user = User.first
699
+ # user.strict_loading!
700
+ # user.comments.to_a
701
+ # => ActiveRecord::StrictLoadingViolationError
702
+ def strict_loading!
703
+ @strict_loading = true
704
+ end
705
+
427
706
  # Marks this record as read only.
428
707
  def readonly!
429
708
  @readonly = true
@@ -438,129 +717,95 @@ module ActiveRecord
438
717
  # We check defined?(@attributes) not to issue warnings if the object is
439
718
  # allocated but not initialized.
440
719
  inspection = if defined?(@attributes) && @attributes
441
- self.class.column_names.collect { |name|
442
- if has_attribute?(name)
443
- "#{name}: #{attribute_for_inspect(name)}"
444
- end
445
- }.compact.join(", ")
446
- else
447
- "not initialized"
448
- end
720
+ self.class.attribute_names.collect do |name|
721
+ if _has_attribute?(name)
722
+ "#{name}: #{attribute_for_inspect(name)}"
723
+ end
724
+ end.compact.join(", ")
725
+ else
726
+ "not initialized"
727
+ end
728
+
449
729
  "#<#{self.class} #{inspection}>"
450
730
  end
451
731
 
452
- # Takes a PP and prettily prints this record to it, allowing you to get a nice result from `pp record`
732
+ # Takes a PP and prettily prints this record to it, allowing you to get a nice result from <tt>pp record</tt>
453
733
  # when pp is required.
454
734
  def pretty_print(pp)
735
+ return super if custom_inspect_method_defined?
455
736
  pp.object_address_group(self) do
456
737
  if defined?(@attributes) && @attributes
457
- column_names = self.class.column_names.select { |name| has_attribute?(name) || new_record? }
458
- pp.seplist(column_names, proc { pp.text ',' }) do |column_name|
459
- column_value = read_attribute(column_name)
460
- pp.breakable ' '
738
+ attr_names = self.class.attribute_names.select { |name| _has_attribute?(name) }
739
+ pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
740
+ pp.breakable " "
461
741
  pp.group(1) do
462
- pp.text column_name
463
- pp.text ':'
742
+ pp.text attr_name
743
+ pp.text ":"
464
744
  pp.breakable
465
- pp.pp column_value
745
+ value = _read_attribute(attr_name)
746
+ value = inspection_filter.filter_param(attr_name, value) unless value.nil?
747
+ pp.pp value
466
748
  end
467
749
  end
468
750
  else
469
- pp.breakable ' '
470
- pp.text 'not initialized'
751
+ pp.breakable " "
752
+ pp.text "not initialized"
471
753
  end
472
754
  end
473
755
  end
474
756
 
475
757
  # Returns a hash of the given methods with their names as keys and returned values as values.
476
758
  def slice(*methods)
477
- Hash[methods.map! { |method| [method, public_send(method)] }].with_indifferent_access
478
- end
479
-
480
- def set_transaction_state(state) # :nodoc:
481
- @transaction_state = state
759
+ methods.flatten.index_with { |method| public_send(method) }.with_indifferent_access
482
760
  end
483
761
 
484
- def has_transactional_callbacks? # :nodoc:
485
- !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_create_callbacks.empty?
762
+ # Returns an array of the values returned by the given methods.
763
+ def values_at(*methods)
764
+ methods.flatten.map! { |method| public_send(method) }
486
765
  end
487
766
 
488
767
  private
489
-
490
- # Updates the attributes on this particular ActiveRecord object so that
491
- # if it is associated with a transaction, then the state of the AR object
492
- # will be updated to reflect the current state of the transaction
493
- #
494
- # The @transaction_state variable stores the states of the associated
495
- # transaction. This relies on the fact that a transaction can only be in
496
- # one rollback or commit (otherwise a list of states would be required)
497
- # Each AR object inside of a transaction carries that transaction's
498
- # TransactionState.
499
- #
500
- # This method checks to see if the ActiveRecord object's state reflects
501
- # the TransactionState, and rolls back or commits the ActiveRecord object
502
- # as appropriate.
503
- #
504
- # Since ActiveRecord objects can be inside multiple transactions, this
505
- # method recursively goes through the parent of the TransactionState and
506
- # checks if the ActiveRecord object reflects the state of the object.
507
- def sync_with_transaction_state
508
- update_attributes_from_transaction_state(@transaction_state, 0)
509
- end
510
-
511
- def update_attributes_from_transaction_state(transaction_state, depth)
512
- if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
513
- unless @reflects_state[depth]
514
- restore_transaction_record_state if transaction_state.rolledback?
515
- clear_transaction_record_state
516
- @reflects_state[depth] = true
517
- end
518
-
519
- if transaction_state.parent && !@reflects_state[depth+1]
520
- update_attributes_from_transaction_state(transaction_state.parent, depth+1)
521
- end
768
+ # +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
769
+ # the array, and then rescues from the possible +NoMethodError+. If those elements are
770
+ # +ActiveRecord::Base+'s, then this triggers the various +method_missing+'s that we have,
771
+ # which significantly impacts upon performance.
772
+ #
773
+ # So we can avoid the +method_missing+ hit by explicitly defining +#to_ary+ as +nil+ here.
774
+ #
775
+ # See also https://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html
776
+ def to_ary
777
+ nil
522
778
  end
523
- end
524
779
 
525
- # Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements
526
- # of the array, and then rescues from the possible NoMethodError. If those elements are
527
- # ActiveRecord::Base's, then this triggers the various method_missing's that we have,
528
- # which significantly impacts upon performance.
529
- #
530
- # So we can avoid the method_missing hit by explicitly defining #to_ary as nil here.
531
- #
532
- # See also http://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html
533
- def to_ary # :nodoc:
534
- nil
535
- end
780
+ def init_internals
781
+ @primary_key = self.class.primary_key
782
+ @readonly = false
783
+ @previously_new_record = false
784
+ @destroyed = false
785
+ @marked_for_destruction = false
786
+ @destroyed_by_association = nil
787
+ @_start_transaction_state = nil
788
+ @strict_loading = self.class.strict_loading_by_default
789
+
790
+ self.class.define_attribute_methods
791
+ end
536
792
 
537
- def init_internals
538
- @aggregation_cache = {}
539
- @association_cache = {}
540
- @readonly = false
541
- @destroyed = false
542
- @marked_for_destruction = false
543
- @destroyed_by_association = nil
544
- @new_record = true
545
- @txn = nil
546
- @_start_transaction_state = {}
547
- @transaction_state = nil
548
- @reflects_state = [false]
549
- end
793
+ def initialize_internals_callback
794
+ end
550
795
 
551
- def initialize_internals_callback
552
- end
796
+ def custom_inspect_method_defined?
797
+ self.class.instance_method(:inspect).owner != ActiveRecord::Base.instance_method(:inspect).owner
798
+ end
553
799
 
554
- # This method is needed to make protected_attributes gem easier to hook.
555
- # Remove it when we drop support to this gem.
556
- def init_attributes(attributes, options)
557
- assign_attributes(attributes)
558
- end
800
+ class InspectionMask < DelegateClass(::String)
801
+ def pretty_print(pp)
802
+ pp.text __getobj__
803
+ end
804
+ end
805
+ private_constant :InspectionMask
559
806
 
560
- def thaw
561
- if frozen?
562
- @attributes = @attributes.dup
807
+ def inspection_filter
808
+ self.class.inspection_filter
563
809
  end
564
- end
565
810
  end
566
811
  end