activerecord 4.2.9 → 6.1.4.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +964 -1382
  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 +266 -251
  8. data/lib/active_record/association_relation.rb +40 -15
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +162 -69
  11. data/lib/active_record/associations/association_scope.rb +105 -130
  12. data/lib/active_record/associations/belongs_to_association.rb +83 -65
  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 -37
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +49 -66
  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 +148 -287
  22. data/lib/active_record/associations/collection_proxy.rb +252 -150
  23. data/lib/active_record/associations/foreign_association.rb +23 -1
  24. data/lib/active_record/associations/has_many_association.rb +56 -98
  25. data/lib/active_record/associations/has_many_through_association.rb +68 -89
  26. data/lib/active_record/associations/has_one_association.rb +73 -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 -81
  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 +174 -169
  32. data/lib/active_record/associations/preloader/association.rb +108 -115
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +97 -94
  35. data/lib/active_record/associations/singular_association.rb +18 -39
  36. data/lib/active_record/associations/through_association.rb +39 -19
  37. data/lib/active_record/associations.rb +1845 -1598
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +18 -10
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -148
  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 +55 -36
  46. data/lib/active_record/attribute_methods/write.rb +24 -55
  47. data/lib/active_record/attribute_methods.rb +149 -154
  48. data/lib/active_record/attributes.rb +234 -78
  49. data/lib/active_record/autosave_association.rb +133 -60
  50. data/lib/active_record/base.rb +46 -46
  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 +34 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -323
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +292 -124
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +177 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +8 -6
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +473 -255
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +869 -286
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +257 -91
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +483 -230
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +557 -640
  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 +194 -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 +268 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +80 -192
  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 +75 -160
  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 -58
  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 +4 -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 +14 -19
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  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 -5
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  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 +145 -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 +496 -298
  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 +588 -375
  119. data/lib/active_record/connection_adapters/schema_cache.rb +167 -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 +144 -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 -373
  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 +458 -241
  133. data/lib/active_record/counter_cache.rb +70 -49
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -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 +272 -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 +211 -92
  143. data/lib/active_record/errors.rb +224 -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 +10 -5
  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 +275 -500
  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 +62 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +27 -5
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +98 -92
  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 +295 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +673 -325
  170. data/lib/active_record/model_schema.rb +418 -113
  171. data/lib/active_record/nested_attributes.rb +263 -224
  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 +572 -136
  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 +170 -51
  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 +523 -199
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +454 -291
  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 +324 -249
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +316 -242
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +95 -103
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -26
  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 +136 -122
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -413
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +18 -20
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -343
  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 -23
  209. data/lib/active_record/scoping/default.rb +96 -83
  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 +128 -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 +364 -130
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +67 -113
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +86 -49
  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 +287 -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 +182 -163
  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 -45
  231. data/lib/active_record/type/date_time.rb +4 -49
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  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 +27 -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 +63 -56
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +42 -29
  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 -4
  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/model/templates/{module.rb → module.rb.tt} +0 -0
  339. data/lib/rails/generators/active_record.rb +7 -5
  340. metadata +172 -65
  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_decorators.rb +0 -66
  350. data/lib/active_record/attribute_set/builder.rb +0 -106
  351. data/lib/active_record/attribute_set.rb +0 -81
  352. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  353. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  354. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  355. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  356. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  357. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  358. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  359. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  360. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  361. data/lib/active_record/type/big_integer.rb +0 -13
  362. data/lib/active_record/type/binary.rb +0 -50
  363. data/lib/active_record/type/boolean.rb +0 -31
  364. data/lib/active_record/type/decimal.rb +0 -64
  365. data/lib/active_record/type/decorator.rb +0 -14
  366. data/lib/active_record/type/float.rb +0 -19
  367. data/lib/active_record/type/integer.rb +0 -59
  368. data/lib/active_record/type/mutable.rb +0 -16
  369. data/lib/active_record/type/numeric.rb +0 -36
  370. data/lib/active_record/type/string.rb +0 -40
  371. data/lib/active_record/type/time_value.rb +0 -38
  372. data/lib/active_record/type/value.rb +0 -110
  373. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
  374. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,33 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_model/attribute/user_provided_default"
4
+
1
5
  module ActiveRecord
2
- module Attributes # :nodoc:
6
+ # See ActiveRecord::Attributes::ClassMethods for documentation
7
+ module Attributes
3
8
  extend ActiveSupport::Concern
4
9
 
5
- Type = ActiveRecord::Type
6
-
7
10
  included do
8
- class_attribute :user_provided_columns, instance_accessor: false # :internal:
9
- class_attribute :user_provided_defaults, instance_accessor: false # :internal:
10
- self.user_provided_columns = {}
11
- self.user_provided_defaults = {}
12
-
13
- delegate :persistable_attribute_names, to: :class
11
+ class_attribute :attributes_to_define_after_schema_loads, instance_accessor: false, default: {} # :internal:
14
12
  end
15
13
 
16
- module ClassMethods # :nodoc:
17
- # Defines or overrides a attribute on this model. This allows customization of
18
- # Active Record's type casting behavior, as well as adding support for user defined
19
- # types.
14
+ module ClassMethods
15
+ ##
16
+ # :call-seq: attribute(name, cast_type = nil, **options)
17
+ #
18
+ # Defines an attribute with a type on this model. It will override the
19
+ # type of existing attributes if needed. This allows control over how
20
+ # values are converted to and from SQL when assigned to a model. It also
21
+ # changes the behavior of values passed to
22
+ # {ActiveRecord::Base.where}[rdoc-ref:QueryMethods#where]. This will let you use
23
+ # your domain objects across much of Active Record, without having to
24
+ # rely on implementation details or monkey patching.
20
25
  #
21
- # +name+ The name of the methods to define attribute methods for, and the column which
22
- # this will persist to.
26
+ # +name+ The name of the methods to define attribute methods for, and the
27
+ # column which this will persist to.
23
28
  #
24
- # +cast_type+ A type object that contains information about how to type cast the value.
25
- # See the examples section for more information.
29
+ # +cast_type+ A symbol such as +:string+ or +:integer+, or a type object
30
+ # to be used for this attribute. See the examples below for more
31
+ # information about providing custom type objects.
26
32
  #
27
33
  # ==== Options
28
- # The options hash accepts the following options:
29
34
  #
30
- # +default+ is the default value that the column should use on a new record.
35
+ # The following options are accepted:
36
+ #
37
+ # +default+ The default value to use when no value is provided. If this option
38
+ # is not passed, the previous default value (if any) will be used.
39
+ # Otherwise, the default will be +nil+.
40
+ #
41
+ # +array+ (PostgreSQL only) specifies that the type should be an array (see the
42
+ # examples below).
43
+ #
44
+ # +range+ (PostgreSQL only) specifies that the type should be a range (see the
45
+ # examples below).
46
+ #
47
+ # When using a symbol for +cast_type+, extra options are forwarded to the
48
+ # constructor of the type object.
31
49
  #
32
50
  # ==== Examples
33
51
  #
@@ -45,103 +63,241 @@ module ActiveRecord
45
63
  # store_listing = StoreListing.new(price_in_cents: '10.1')
46
64
  #
47
65
  # # before
48
- # store_listing.price_in_cents # => BigDecimal.new(10.1)
66
+ # store_listing.price_in_cents # => BigDecimal(10.1)
49
67
  #
50
68
  # class StoreListing < ActiveRecord::Base
51
- # attribute :price_in_cents, Type::Integer.new
69
+ # attribute :price_in_cents, :integer
52
70
  # end
53
71
  #
54
72
  # # after
55
73
  # store_listing.price_in_cents # => 10
56
74
  #
57
- # Users may also define their own custom types, as long as they respond to the methods
58
- # defined on the value type. The `type_cast` method on your type object will be called
59
- # with values both from the database, and from your controllers. See
60
- # `ActiveRecord::Attributes::Type::Value` for the expected API. It is recommended that your
61
- # type objects inherit from an existing type, or the base value type.
75
+ # A default can also be provided.
76
+ #
77
+ # # db/schema.rb
78
+ # create_table :store_listings, force: true do |t|
79
+ # t.string :my_string, default: "original default"
80
+ # end
81
+ #
82
+ # StoreListing.new.my_string # => "original default"
83
+ #
84
+ # # app/models/store_listing.rb
85
+ # class StoreListing < ActiveRecord::Base
86
+ # attribute :my_string, :string, default: "new default"
87
+ # end
88
+ #
89
+ # StoreListing.new.my_string # => "new default"
90
+ #
91
+ # class Product < ActiveRecord::Base
92
+ # attribute :my_default_proc, :datetime, default: -> { Time.now }
93
+ # end
94
+ #
95
+ # Product.new.my_default_proc # => 2015-05-30 11:04:48 -0600
96
+ # sleep 1
97
+ # Product.new.my_default_proc # => 2015-05-30 11:04:49 -0600
98
+ #
99
+ # \Attributes do not need to be backed by a database column.
100
+ #
101
+ # # app/models/my_model.rb
102
+ # class MyModel < ActiveRecord::Base
103
+ # attribute :my_string, :string
104
+ # attribute :my_int_array, :integer, array: true
105
+ # attribute :my_float_range, :float, range: true
106
+ # end
107
+ #
108
+ # model = MyModel.new(
109
+ # my_string: "string",
110
+ # my_int_array: ["1", "2", "3"],
111
+ # my_float_range: "[1,3.5]",
112
+ # )
113
+ # model.attributes
114
+ # # =>
115
+ # {
116
+ # my_string: "string",
117
+ # my_int_array: [1, 2, 3],
118
+ # my_float_range: 1.0..3.5
119
+ # }
120
+ #
121
+ # Passing options to the type constructor
122
+ #
123
+ # # app/models/my_model.rb
124
+ # class MyModel < ActiveRecord::Base
125
+ # attribute :small_int, :integer, limit: 2
126
+ # end
127
+ #
128
+ # MyModel.create(small_int: 65537)
129
+ # # => Error: 65537 is out of range for the limit of two bytes
130
+ #
131
+ # ==== Creating Custom Types
132
+ #
133
+ # Users may also define their own custom types, as long as they respond
134
+ # to the methods defined on the value type. The method +deserialize+ or
135
+ # +cast+ will be called on your type object, with raw input from the
136
+ # database or from your controllers. See ActiveModel::Type::Value for the
137
+ # expected API. It is recommended that your type objects inherit from an
138
+ # existing type, or from ActiveRecord::Type::Value
62
139
  #
63
140
  # class MoneyType < ActiveRecord::Type::Integer
64
- # def type_cast(value)
65
- # if value.include?('$')
141
+ # def cast(value)
142
+ # if !value.kind_of?(Numeric) && value.include?('$')
66
143
  # price_in_dollars = value.gsub(/\$/, '').to_f
67
- # price_in_dollars * 100
144
+ # super(price_in_dollars * 100)
68
145
  # else
69
- # value.to_i
146
+ # super
70
147
  # end
71
148
  # end
72
149
  # end
73
150
  #
151
+ # # config/initializers/types.rb
152
+ # ActiveRecord::Type.register(:money, MoneyType)
153
+ #
154
+ # # app/models/store_listing.rb
74
155
  # class StoreListing < ActiveRecord::Base
75
- # attribute :price_in_cents, MoneyType.new
156
+ # attribute :price_in_cents, :money
76
157
  # end
77
158
  #
78
159
  # store_listing = StoreListing.new(price_in_cents: '$10.00')
79
160
  # store_listing.price_in_cents # => 1000
80
- def attribute(name, cast_type, options = {})
161
+ #
162
+ # For more details on creating custom types, see the documentation for
163
+ # ActiveModel::Type::Value. For more details on registering your types
164
+ # to be referenced by a symbol, see ActiveRecord::Type.register. You can
165
+ # also pass a type object directly, in place of a symbol.
166
+ #
167
+ # ==== \Querying
168
+ #
169
+ # When {ActiveRecord::Base.where}[rdoc-ref:QueryMethods#where] is called, it will
170
+ # use the type defined by the model class to convert the value to SQL,
171
+ # calling +serialize+ on your type object. For example:
172
+ #
173
+ # class Money < Struct.new(:amount, :currency)
174
+ # end
175
+ #
176
+ # class MoneyType < ActiveRecord::Type::Value
177
+ # def initialize(currency_converter:)
178
+ # @currency_converter = currency_converter
179
+ # end
180
+ #
181
+ # # value will be the result of +deserialize+ or
182
+ # # +cast+. Assumed to be an instance of +Money+ in
183
+ # # this case.
184
+ # def serialize(value)
185
+ # value_in_bitcoins = @currency_converter.convert_to_bitcoins(value)
186
+ # value_in_bitcoins.amount
187
+ # end
188
+ # end
189
+ #
190
+ # # config/initializers/types.rb
191
+ # ActiveRecord::Type.register(:money, MoneyType)
192
+ #
193
+ # # app/models/product.rb
194
+ # class Product < ActiveRecord::Base
195
+ # currency_converter = ConversionRatesFromTheInternet.new
196
+ # attribute :price_in_bitcoins, :money, currency_converter: currency_converter
197
+ # end
198
+ #
199
+ # Product.where(price_in_bitcoins: Money.new(5, "USD"))
200
+ # # => SELECT * FROM products WHERE price_in_bitcoins = 0.02230
201
+ #
202
+ # Product.where(price_in_bitcoins: Money.new(5, "GBP"))
203
+ # # => SELECT * FROM products WHERE price_in_bitcoins = 0.03412
204
+ #
205
+ # ==== Dirty Tracking
206
+ #
207
+ # The type of an attribute is given the opportunity to change how dirty
208
+ # tracking is performed. The methods +changed?+ and +changed_in_place?+
209
+ # will be called from ActiveModel::Dirty. See the documentation for those
210
+ # methods in ActiveModel::Type::Value for more details.
211
+ def attribute(name, cast_type = nil, **options, &block)
81
212
  name = name.to_s
82
- clear_caches_calculated_from_columns
83
- # Assign a new hash to ensure that subclasses do not share a hash
84
- self.user_provided_columns = user_provided_columns.merge(name => cast_type)
85
-
86
- if options.key?(:default)
87
- self.user_provided_defaults = user_provided_defaults.merge(name => options[:default])
88
- end
89
- end
213
+ reload_schema_from_cache
90
214
 
91
- # Returns an array of column objects for the table associated with this class.
92
- def columns
93
- @columns ||= add_user_provided_columns(connection.schema_cache.columns(table_name))
215
+ self.attributes_to_define_after_schema_loads =
216
+ attributes_to_define_after_schema_loads.merge(
217
+ name => [cast_type || block, options]
218
+ )
94
219
  end
95
220
 
96
- # Returns a hash of column objects for the table associated with this class.
97
- def columns_hash
98
- @columns_hash ||= Hash[columns.map { |c| [c.name, c] }]
99
- end
100
-
101
- def persistable_attribute_names # :nodoc:
102
- @persistable_attribute_names ||= connection.schema_cache.columns_hash(table_name).keys
221
+ # This is the low level API which sits beneath +attribute+. It only
222
+ # accepts type objects, and will do its work immediately instead of
223
+ # waiting for the schema to load. Automatic schema detection and
224
+ # ClassMethods#attribute both call this under the hood. While this method
225
+ # is provided so it can be used by plugin authors, application code
226
+ # should probably use ClassMethods#attribute.
227
+ #
228
+ # +name+ The name of the attribute being defined. Expected to be a +String+.
229
+ #
230
+ # +cast_type+ The type object to use for this attribute.
231
+ #
232
+ # +default+ The default value to use when no value is provided. If this option
233
+ # is not passed, the previous default value (if any) will be used.
234
+ # Otherwise, the default will be +nil+. A proc can also be passed, and
235
+ # will be called once each time a new value is needed.
236
+ #
237
+ # +user_provided_default+ Whether the default value should be cast using
238
+ # +cast+ or +deserialize+.
239
+ def define_attribute(
240
+ name,
241
+ cast_type,
242
+ default: NO_DEFAULT_PROVIDED,
243
+ user_provided_default: true
244
+ )
245
+ attribute_types[name] = cast_type
246
+ define_default_attribute(name, default, cast_type, from_user: user_provided_default)
103
247
  end
104
248
 
105
- def reset_column_information # :nodoc:
249
+ def load_schema! # :nodoc:
106
250
  super
107
- clear_caches_calculated_from_columns
251
+ attributes_to_define_after_schema_loads.each do |name, (type, options)|
252
+ define_attribute(name, _lookup_cast_type(name, type, options), **options.slice(:default))
253
+ end
108
254
  end
109
255
 
110
256
  private
257
+ NO_DEFAULT_PROVIDED = Object.new # :nodoc:
258
+ private_constant :NO_DEFAULT_PROVIDED
111
259
 
112
- def add_user_provided_columns(schema_columns)
113
- existing_columns = schema_columns.map do |column|
114
- new_type = user_provided_columns[column.name]
115
- if new_type
116
- column.with_type(new_type)
260
+ def define_default_attribute(name, value, type, from_user:)
261
+ if value == NO_DEFAULT_PROVIDED
262
+ default_attribute = _default_attributes[name].with_type(type)
263
+ elsif from_user
264
+ default_attribute = ActiveModel::Attribute::UserProvidedDefault.new(
265
+ name,
266
+ value,
267
+ type,
268
+ _default_attributes.fetch(name.to_s) { nil },
269
+ )
117
270
  else
118
- column
271
+ default_attribute = ActiveModel::Attribute.from_database(name, value, type)
119
272
  end
273
+ _default_attributes[name] = default_attribute
120
274
  end
121
275
 
122
- existing_column_names = existing_columns.map(&:name)
123
- new_columns = user_provided_columns.except(*existing_column_names).map do |(name, type)|
124
- connection.new_column(name, nil, type)
125
- end
276
+ def decorate_attribute_type(attr_name, **default)
277
+ type, options = attributes_to_define_after_schema_loads[attr_name]
126
278
 
127
- existing_columns + new_columns
128
- end
279
+ default.with_defaults!(default: options[:default]) if options&.key?(:default)
129
280
 
130
- def clear_caches_calculated_from_columns
131
- @attributes_builder = nil
132
- @column_names = nil
133
- @column_types = nil
134
- @columns = nil
135
- @columns_hash = nil
136
- @content_columns = nil
137
- @default_attributes = nil
138
- @persistable_attribute_names = nil
139
- @attribute_names = nil
140
- end
281
+ attribute(attr_name, **default) do |cast_type|
282
+ if type && !type.is_a?(Proc)
283
+ cast_type = _lookup_cast_type(attr_name, type, options)
284
+ end
141
285
 
142
- def raw_default_values
143
- super.merge(user_provided_defaults)
144
- end
286
+ yield cast_type
287
+ end
288
+ end
289
+
290
+ def _lookup_cast_type(name, type, options)
291
+ case type
292
+ when Symbol
293
+ adapter_name = ActiveRecord::Type.adapter_name_from(self)
294
+ ActiveRecord::Type.lookup(type, **options.except(:default), adapter: adapter_name)
295
+ when Proc
296
+ type[type_for_attribute(name)]
297
+ else
298
+ type || type_for_attribute(name)
299
+ end
300
+ end
145
301
  end
146
302
  end
147
303
  end