activerecord 4.2.11.1 → 6.0.3.5

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 (373) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +721 -1522
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +14 -13
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/advisory_lock_base.rb +18 -0
  8. data/lib/active_record/aggregations.rb +266 -251
  9. data/lib/active_record/association_relation.rb +20 -13
  10. data/lib/active_record/associations/alias_tracker.rb +29 -36
  11. data/lib/active_record/associations/association.rb +128 -57
  12. data/lib/active_record/associations/association_scope.rb +103 -132
  13. data/lib/active_record/associations/belongs_to_association.rb +65 -60
  14. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  15. data/lib/active_record/associations/builder/association.rb +27 -40
  16. data/lib/active_record/associations/builder/belongs_to.rb +69 -55
  17. data/lib/active_record/associations/builder/collection_association.rb +10 -33
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +50 -66
  19. data/lib/active_record/associations/builder/has_many.rb +8 -4
  20. data/lib/active_record/associations/builder/has_one.rb +46 -5
  21. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  22. data/lib/active_record/associations/collection_association.rb +136 -288
  23. data/lib/active_record/associations/collection_proxy.rb +241 -147
  24. data/lib/active_record/associations/foreign_association.rb +10 -1
  25. data/lib/active_record/associations/has_many_association.rb +34 -98
  26. data/lib/active_record/associations/has_many_through_association.rb +60 -87
  27. data/lib/active_record/associations/has_one_association.rb +61 -49
  28. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  29. data/lib/active_record/associations/join_dependency/join_association.rb +38 -86
  30. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  31. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  32. data/lib/active_record/associations/join_dependency.rb +149 -166
  33. data/lib/active_record/associations/preloader/association.rb +90 -123
  34. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  35. data/lib/active_record/associations/preloader.rb +90 -93
  36. data/lib/active_record/associations/singular_association.rb +18 -39
  37. data/lib/active_record/associations/through_association.rb +38 -18
  38. data/lib/active_record/associations.rb +1737 -1597
  39. data/lib/active_record/attribute_assignment.rb +57 -185
  40. data/lib/active_record/attribute_decorators.rb +39 -17
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
  42. data/lib/active_record/attribute_methods/dirty.rb +174 -144
  43. data/lib/active_record/attribute_methods/primary_key.rb +90 -84
  44. data/lib/active_record/attribute_methods/query.rb +6 -5
  45. data/lib/active_record/attribute_methods/read.rb +20 -77
  46. data/lib/active_record/attribute_methods/serialization.rb +40 -21
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +57 -37
  48. data/lib/active_record/attribute_methods/write.rb +32 -55
  49. data/lib/active_record/attribute_methods.rb +120 -135
  50. data/lib/active_record/attributes.rb +213 -82
  51. data/lib/active_record/autosave_association.rb +97 -41
  52. data/lib/active_record/base.rb +57 -45
  53. data/lib/active_record/callbacks.rb +101 -76
  54. data/lib/active_record/coders/json.rb +3 -1
  55. data/lib/active_record/coders/yaml_column.rb +23 -12
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +804 -297
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +240 -115
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +83 -24
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +170 -53
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -47
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +371 -242
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +694 -256
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +190 -83
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +473 -202
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +507 -639
  69. data/lib/active_record/connection_adapters/column.rb +56 -43
  70. data/lib/active_record/connection_adapters/connection_specification.rb +174 -153
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +71 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +58 -181
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +70 -114
  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 +5 -1
  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 +9 -22
  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/jsonb.rb +3 -11
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  99. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +51 -34
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +9 -5
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -296
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +558 -356
  117. data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +299 -349
  127. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  128. data/lib/active_record/connection_handling.rb +167 -41
  129. data/lib/active_record/core.rb +252 -230
  130. data/lib/active_record/counter_cache.rb +70 -49
  131. data/lib/active_record/database_configurations/database_config.rb +37 -0
  132. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  133. data/lib/active_record/database_configurations/url_config.rb +78 -0
  134. data/lib/active_record/database_configurations.rb +233 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +87 -106
  137. data/lib/active_record/enum.rb +163 -86
  138. data/lib/active_record/errors.rb +188 -53
  139. data/lib/active_record/explain.rb +22 -11
  140. data/lib/active_record/explain_registry.rb +4 -2
  141. data/lib/active_record/explain_subscriber.rb +10 -5
  142. data/lib/active_record/fixture_set/file.rb +35 -9
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +152 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  147. data/lib/active_record/fixtures.rb +227 -501
  148. data/lib/active_record/gem_version.rb +6 -4
  149. data/lib/active_record/inheritance.rb +158 -115
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +123 -29
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +21 -3
  154. data/lib/active_record/locale/en.yml +3 -2
  155. data/lib/active_record/locking/optimistic.rb +86 -96
  156. data/lib/active_record/locking/pessimistic.rb +18 -6
  157. data/lib/active_record/log_subscriber.rb +76 -33
  158. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  160. data/lib/active_record/middleware/database_selector.rb +74 -0
  161. data/lib/active_record/migration/command_recorder.rb +166 -91
  162. data/lib/active_record/migration/compatibility.rb +244 -0
  163. data/lib/active_record/migration/join_table.rb +8 -7
  164. data/lib/active_record/migration.rb +623 -305
  165. data/lib/active_record/model_schema.rb +313 -112
  166. data/lib/active_record/nested_attributes.rb +263 -223
  167. data/lib/active_record/no_touching.rb +15 -2
  168. data/lib/active_record/null_relation.rb +24 -38
  169. data/lib/active_record/persistence.rb +557 -126
  170. data/lib/active_record/query_cache.rb +19 -23
  171. data/lib/active_record/querying.rb +44 -30
  172. data/lib/active_record/railtie.rb +143 -44
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +2 -0
  175. data/lib/active_record/railties/controller_runtime.rb +34 -33
  176. data/lib/active_record/railties/databases.rake +331 -185
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +430 -281
  179. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  180. data/lib/active_record/relation/batches.rb +206 -55
  181. data/lib/active_record/relation/calculations.rb +268 -254
  182. data/lib/active_record/relation/delegation.rb +75 -84
  183. data/lib/active_record/relation/finder_methods.rb +285 -241
  184. data/lib/active_record/relation/from_clause.rb +30 -0
  185. data/lib/active_record/relation/merger.rb +78 -88
  186. data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -26
  187. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  188. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  189. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  190. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  191. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  192. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  193. data/lib/active_record/relation/predicate_builder.rb +110 -119
  194. data/lib/active_record/relation/query_attribute.rb +50 -0
  195. data/lib/active_record/relation/query_methods.rb +603 -397
  196. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  197. data/lib/active_record/relation/spawn_methods.rb +11 -14
  198. data/lib/active_record/relation/where_clause.rb +189 -0
  199. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  200. data/lib/active_record/relation.rb +530 -341
  201. data/lib/active_record/result.rb +79 -43
  202. data/lib/active_record/runtime_registry.rb +6 -4
  203. data/lib/active_record/sanitization.rb +144 -121
  204. data/lib/active_record/schema.rb +21 -24
  205. data/lib/active_record/schema_dumper.rb +112 -93
  206. data/lib/active_record/schema_migration.rb +24 -17
  207. data/lib/active_record/scoping/default.rb +98 -83
  208. data/lib/active_record/scoping/named.rb +86 -33
  209. data/lib/active_record/scoping.rb +45 -27
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +5 -5
  212. data/lib/active_record/statement_cache.rb +73 -36
  213. data/lib/active_record/store.rb +127 -42
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +90 -0
  216. data/lib/active_record/tasks/database_tasks.rb +307 -100
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +55 -100
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +80 -41
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +37 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +225 -0
  222. data/lib/active_record/timestamp.rb +86 -41
  223. data/lib/active_record/touch_later.rb +65 -0
  224. data/lib/active_record/transactions.rb +223 -157
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  227. data/lib/active_record/type/date.rb +4 -45
  228. data/lib/active_record/type/date_time.rb +4 -49
  229. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  230. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  231. data/lib/active_record/type/internal/timezone.rb +17 -0
  232. data/lib/active_record/type/json.rb +30 -0
  233. data/lib/active_record/type/serialized.rb +23 -15
  234. data/lib/active_record/type/text.rb +2 -2
  235. data/lib/active_record/type/time.rb +11 -16
  236. data/lib/active_record/type/type_map.rb +16 -19
  237. data/lib/active_record/type/unsigned_integer.rb +9 -8
  238. data/lib/active_record/type.rb +77 -23
  239. data/lib/active_record/type_caster/connection.rb +34 -0
  240. data/lib/active_record/type_caster/map.rb +20 -0
  241. data/lib/active_record/type_caster.rb +9 -0
  242. data/lib/active_record/validations/absence.rb +25 -0
  243. data/lib/active_record/validations/associated.rb +12 -4
  244. data/lib/active_record/validations/length.rb +26 -0
  245. data/lib/active_record/validations/presence.rb +14 -13
  246. data/lib/active_record/validations/uniqueness.rb +42 -55
  247. data/lib/active_record/validations.rb +38 -35
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/active_record.rb +42 -22
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes/attribute.rb +37 -0
  252. data/lib/arel/attributes.rb +22 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes/and.rb +32 -0
  266. data/lib/arel/nodes/ascending.rb +23 -0
  267. data/lib/arel/nodes/binary.rb +52 -0
  268. data/lib/arel/nodes/bind_param.rb +36 -0
  269. data/lib/arel/nodes/case.rb +55 -0
  270. data/lib/arel/nodes/casted.rb +50 -0
  271. data/lib/arel/nodes/comment.rb +29 -0
  272. data/lib/arel/nodes/count.rb +12 -0
  273. data/lib/arel/nodes/delete_statement.rb +45 -0
  274. data/lib/arel/nodes/descending.rb +23 -0
  275. data/lib/arel/nodes/equality.rb +18 -0
  276. data/lib/arel/nodes/extract.rb +24 -0
  277. data/lib/arel/nodes/false.rb +16 -0
  278. data/lib/arel/nodes/full_outer_join.rb +8 -0
  279. data/lib/arel/nodes/function.rb +44 -0
  280. data/lib/arel/nodes/grouping.rb +8 -0
  281. data/lib/arel/nodes/in.rb +8 -0
  282. data/lib/arel/nodes/infix_operation.rb +80 -0
  283. data/lib/arel/nodes/inner_join.rb +8 -0
  284. data/lib/arel/nodes/insert_statement.rb +37 -0
  285. data/lib/arel/nodes/join_source.rb +20 -0
  286. data/lib/arel/nodes/matches.rb +18 -0
  287. data/lib/arel/nodes/named_function.rb +23 -0
  288. data/lib/arel/nodes/node.rb +50 -0
  289. data/lib/arel/nodes/node_expression.rb +13 -0
  290. data/lib/arel/nodes/outer_join.rb +8 -0
  291. data/lib/arel/nodes/over.rb +15 -0
  292. data/lib/arel/nodes/regexp.rb +16 -0
  293. data/lib/arel/nodes/right_outer_join.rb +8 -0
  294. data/lib/arel/nodes/select_core.rb +67 -0
  295. data/lib/arel/nodes/select_statement.rb +41 -0
  296. data/lib/arel/nodes/sql_literal.rb +16 -0
  297. data/lib/arel/nodes/string_join.rb +11 -0
  298. data/lib/arel/nodes/table_alias.rb +27 -0
  299. data/lib/arel/nodes/terminal.rb +16 -0
  300. data/lib/arel/nodes/true.rb +16 -0
  301. data/lib/arel/nodes/unary.rb +45 -0
  302. data/lib/arel/nodes/unary_operation.rb +20 -0
  303. data/lib/arel/nodes/unqualified_column.rb +22 -0
  304. data/lib/arel/nodes/update_statement.rb +41 -0
  305. data/lib/arel/nodes/values_list.rb +9 -0
  306. data/lib/arel/nodes/window.rb +126 -0
  307. data/lib/arel/nodes/with.rb +11 -0
  308. data/lib/arel/nodes.rb +68 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +256 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors/depth_first.rb +203 -0
  316. data/lib/arel/visitors/dot.rb +296 -0
  317. data/lib/arel/visitors/ibm_db.rb +34 -0
  318. data/lib/arel/visitors/informix.rb +62 -0
  319. data/lib/arel/visitors/mssql.rb +156 -0
  320. data/lib/arel/visitors/mysql.rb +83 -0
  321. data/lib/arel/visitors/oracle.rb +158 -0
  322. data/lib/arel/visitors/oracle12.rb +65 -0
  323. data/lib/arel/visitors/postgresql.rb +109 -0
  324. data/lib/arel/visitors/sqlite.rb +38 -0
  325. data/lib/arel/visitors/to_sql.rb +888 -0
  326. data/lib/arel/visitors/visitor.rb +45 -0
  327. data/lib/arel/visitors/where_sql.rb +22 -0
  328. data/lib/arel/visitors.rb +20 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/arel.rb +62 -0
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
  334. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  335. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -2
  336. data/lib/rails/generators/active_record/migration.rb +30 -1
  337. data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  340. data/lib/rails/generators/active_record.rb +7 -5
  341. metadata +168 -59
  342. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  343. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  344. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  345. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  346. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  347. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  348. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  349. data/lib/active_record/attribute.rb +0 -163
  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/mysql_adapter.rb +0 -498
  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 -31
  363. data/lib/active_record/type/decimal.rb +0 -64
  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 -59
  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 -40
  370. data/lib/active_record/type/time_value.rb +0 -38
  371. data/lib/active_record/type/value.rb +0 -110
  372. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
  373. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,33 +1,48 @@
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
+ # Defines an attribute with a type on this model. It will override the
16
+ # type of existing attributes if needed. This allows control over how
17
+ # values are converted to and from SQL when assigned to a model. It also
18
+ # changes the behavior of values passed to
19
+ # {ActiveRecord::Base.where}[rdoc-ref:QueryMethods#where]. This will let you use
20
+ # your domain objects across much of Active Record, without having to
21
+ # rely on implementation details or monkey patching.
20
22
  #
21
- # +name+ The name of the methods to define attribute methods for, and the column which
22
- # this will persist to.
23
+ # +name+ The name of the methods to define attribute methods for, and the
24
+ # column which this will persist to.
23
25
  #
24
- # +cast_type+ A type object that contains information about how to type cast the value.
25
- # See the examples section for more information.
26
+ # +cast_type+ A symbol such as +:string+ or +:integer+, or a type object
27
+ # to be used for this attribute. See the examples below for more
28
+ # information about providing custom type objects.
26
29
  #
27
30
  # ==== Options
28
- # The options hash accepts the following options:
29
31
  #
30
- # +default+ is the default value that the column should use on a new record.
32
+ # The following options are accepted:
33
+ #
34
+ # +default+ The default value to use when no value is provided. If this option
35
+ # is not passed, the previous default value (if any) will be used.
36
+ # Otherwise, the default will be +nil+.
37
+ #
38
+ # +array+ (PostgreSQL only) specifies that the type should be an array (see the
39
+ # examples below).
40
+ #
41
+ # +range+ (PostgreSQL only) specifies that the type should be a range (see the
42
+ # examples below).
43
+ #
44
+ # When using a symbol for +cast_type+, extra options are forwarded to the
45
+ # constructor of the type object.
31
46
  #
32
47
  # ==== Examples
33
48
  #
@@ -45,103 +60,219 @@ module ActiveRecord
45
60
  # store_listing = StoreListing.new(price_in_cents: '10.1')
46
61
  #
47
62
  # # before
48
- # store_listing.price_in_cents # => BigDecimal.new(10.1)
63
+ # store_listing.price_in_cents # => BigDecimal(10.1)
49
64
  #
50
65
  # class StoreListing < ActiveRecord::Base
51
- # attribute :price_in_cents, Type::Integer.new
66
+ # attribute :price_in_cents, :integer
52
67
  # end
53
68
  #
54
69
  # # after
55
70
  # store_listing.price_in_cents # => 10
56
71
  #
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.
72
+ # A default can also be provided.
73
+ #
74
+ # # db/schema.rb
75
+ # create_table :store_listings, force: true do |t|
76
+ # t.string :my_string, default: "original default"
77
+ # end
78
+ #
79
+ # StoreListing.new.my_string # => "original default"
80
+ #
81
+ # # app/models/store_listing.rb
82
+ # class StoreListing < ActiveRecord::Base
83
+ # attribute :my_string, :string, default: "new default"
84
+ # end
85
+ #
86
+ # StoreListing.new.my_string # => "new default"
87
+ #
88
+ # class Product < ActiveRecord::Base
89
+ # attribute :my_default_proc, :datetime, default: -> { Time.now }
90
+ # end
91
+ #
92
+ # Product.new.my_default_proc # => 2015-05-30 11:04:48 -0600
93
+ # sleep 1
94
+ # Product.new.my_default_proc # => 2015-05-30 11:04:49 -0600
95
+ #
96
+ # \Attributes do not need to be backed by a database column.
97
+ #
98
+ # # app/models/my_model.rb
99
+ # class MyModel < ActiveRecord::Base
100
+ # attribute :my_string, :string
101
+ # attribute :my_int_array, :integer, array: true
102
+ # attribute :my_float_range, :float, range: true
103
+ # end
104
+ #
105
+ # model = MyModel.new(
106
+ # my_string: "string",
107
+ # my_int_array: ["1", "2", "3"],
108
+ # my_float_range: "[1,3.5]",
109
+ # )
110
+ # model.attributes
111
+ # # =>
112
+ # {
113
+ # my_string: "string",
114
+ # my_int_array: [1, 2, 3],
115
+ # my_float_range: 1.0..3.5
116
+ # }
117
+ #
118
+ # Passing options to the type constructor
119
+ #
120
+ # # app/models/my_model.rb
121
+ # class MyModel < ActiveRecord::Base
122
+ # attribute :small_int, :integer, limit: 2
123
+ # end
124
+ #
125
+ # MyModel.create(small_int: 65537)
126
+ # # => Error: 65537 is out of range for the limit of two bytes
127
+ #
128
+ # ==== Creating Custom Types
129
+ #
130
+ # Users may also define their own custom types, as long as they respond
131
+ # to the methods defined on the value type. The method +deserialize+ or
132
+ # +cast+ will be called on your type object, with raw input from the
133
+ # database or from your controllers. See ActiveModel::Type::Value for the
134
+ # expected API. It is recommended that your type objects inherit from an
135
+ # existing type, or from ActiveRecord::Type::Value
62
136
  #
63
137
  # class MoneyType < ActiveRecord::Type::Integer
64
- # def type_cast(value)
65
- # if value.include?('$')
138
+ # def cast(value)
139
+ # if !value.kind_of?(Numeric) && value.include?('$')
66
140
  # price_in_dollars = value.gsub(/\$/, '').to_f
67
- # price_in_dollars * 100
141
+ # super(price_in_dollars * 100)
68
142
  # else
69
- # value.to_i
143
+ # super
70
144
  # end
71
145
  # end
72
146
  # end
73
147
  #
148
+ # # config/initializers/types.rb
149
+ # ActiveRecord::Type.register(:money, MoneyType)
150
+ #
151
+ # # app/models/store_listing.rb
74
152
  # class StoreListing < ActiveRecord::Base
75
- # attribute :price_in_cents, MoneyType.new
153
+ # attribute :price_in_cents, :money
76
154
  # end
77
155
  #
78
156
  # store_listing = StoreListing.new(price_in_cents: '$10.00')
79
157
  # store_listing.price_in_cents # => 1000
80
- def attribute(name, cast_type, options = {})
158
+ #
159
+ # For more details on creating custom types, see the documentation for
160
+ # ActiveModel::Type::Value. For more details on registering your types
161
+ # to be referenced by a symbol, see ActiveRecord::Type.register. You can
162
+ # also pass a type object directly, in place of a symbol.
163
+ #
164
+ # ==== \Querying
165
+ #
166
+ # When {ActiveRecord::Base.where}[rdoc-ref:QueryMethods#where] is called, it will
167
+ # use the type defined by the model class to convert the value to SQL,
168
+ # calling +serialize+ on your type object. For example:
169
+ #
170
+ # class Money < Struct.new(:amount, :currency)
171
+ # end
172
+ #
173
+ # class MoneyType < Type::Value
174
+ # def initialize(currency_converter:)
175
+ # @currency_converter = currency_converter
176
+ # end
177
+ #
178
+ # # value will be the result of +deserialize+ or
179
+ # # +cast+. Assumed to be an instance of +Money+ in
180
+ # # this case.
181
+ # def serialize(value)
182
+ # value_in_bitcoins = @currency_converter.convert_to_bitcoins(value)
183
+ # value_in_bitcoins.amount
184
+ # end
185
+ # end
186
+ #
187
+ # # config/initializers/types.rb
188
+ # ActiveRecord::Type.register(:money, MoneyType)
189
+ #
190
+ # # app/models/product.rb
191
+ # class Product < ActiveRecord::Base
192
+ # currency_converter = ConversionRatesFromTheInternet.new
193
+ # attribute :price_in_bitcoins, :money, currency_converter: currency_converter
194
+ # end
195
+ #
196
+ # Product.where(price_in_bitcoins: Money.new(5, "USD"))
197
+ # # => SELECT * FROM products WHERE price_in_bitcoins = 0.02230
198
+ #
199
+ # Product.where(price_in_bitcoins: Money.new(5, "GBP"))
200
+ # # => SELECT * FROM products WHERE price_in_bitcoins = 0.03412
201
+ #
202
+ # ==== Dirty Tracking
203
+ #
204
+ # The type of an attribute is given the opportunity to change how dirty
205
+ # tracking is performed. The methods +changed?+ and +changed_in_place?+
206
+ # will be called from ActiveModel::Dirty. See the documentation for those
207
+ # methods in ActiveModel::Type::Value for more details.
208
+ def attribute(name, cast_type = Type::Value.new, **options)
81
209
  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
210
+ reload_schema_from_cache
90
211
 
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))
212
+ self.attributes_to_define_after_schema_loads =
213
+ attributes_to_define_after_schema_loads.merge(
214
+ name => [cast_type, options]
215
+ )
94
216
  end
95
217
 
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
218
+ # This is the low level API which sits beneath +attribute+. It only
219
+ # accepts type objects, and will do its work immediately instead of
220
+ # waiting for the schema to load. Automatic schema detection and
221
+ # ClassMethods#attribute both call this under the hood. While this method
222
+ # is provided so it can be used by plugin authors, application code
223
+ # should probably use ClassMethods#attribute.
224
+ #
225
+ # +name+ The name of the attribute being defined. Expected to be a +String+.
226
+ #
227
+ # +cast_type+ The type object to use for this attribute.
228
+ #
229
+ # +default+ The default value to use when no value is provided. If this option
230
+ # is not passed, the previous default value (if any) will be used.
231
+ # Otherwise, the default will be +nil+. A proc can also be passed, and
232
+ # will be called once each time a new value is needed.
233
+ #
234
+ # +user_provided_default+ Whether the default value should be cast using
235
+ # +cast+ or +deserialize+.
236
+ def define_attribute(
237
+ name,
238
+ cast_type,
239
+ default: NO_DEFAULT_PROVIDED,
240
+ user_provided_default: true
241
+ )
242
+ attribute_types[name] = cast_type
243
+ define_default_attribute(name, default, cast_type, from_user: user_provided_default)
103
244
  end
104
245
 
105
- def reset_column_information # :nodoc:
246
+ def load_schema! # :nodoc:
106
247
  super
107
- clear_caches_calculated_from_columns
248
+ attributes_to_define_after_schema_loads.each do |name, (type, options)|
249
+ if type.is_a?(Symbol)
250
+ type = ActiveRecord::Type.lookup(type, **options.except(:default))
251
+ end
252
+
253
+ define_attribute(name, type, **options.slice(:default))
254
+ end
108
255
  end
109
256
 
110
257
  private
258
+ NO_DEFAULT_PROVIDED = Object.new # :nodoc:
259
+ private_constant :NO_DEFAULT_PROVIDED
111
260
 
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)
261
+ def define_default_attribute(name, value, type, from_user:)
262
+ if value == NO_DEFAULT_PROVIDED
263
+ default_attribute = _default_attributes[name].with_type(type)
264
+ elsif from_user
265
+ default_attribute = ActiveModel::Attribute::UserProvidedDefault.new(
266
+ name,
267
+ value,
268
+ type,
269
+ _default_attributes.fetch(name.to_s) { nil },
270
+ )
117
271
  else
118
- column
272
+ default_attribute = ActiveModel::Attribute.from_database(name, value, type)
119
273
  end
274
+ _default_attributes[name] = default_attribute
120
275
  end
121
-
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
126
-
127
- existing_columns + new_columns
128
- end
129
-
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
141
-
142
- def raw_default_values
143
- super.merge(user_provided_defaults)
144
- end
145
276
  end
146
277
  end
147
278
  end