activerecord 4.2.11.2 → 6.0.0

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

Potentially problematic release.


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

Files changed (372) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +613 -1638
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +13 -12
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record.rb +41 -22
  8. data/lib/active_record/aggregations.rb +267 -251
  9. data/lib/active_record/association_relation.rb +11 -6
  10. data/lib/active_record/associations.rb +1737 -1597
  11. data/lib/active_record/associations/alias_tracker.rb +29 -35
  12. data/lib/active_record/associations/association.rb +125 -58
  13. data/lib/active_record/associations/association_scope.rb +103 -132
  14. data/lib/active_record/associations/belongs_to_association.rb +65 -60
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  16. data/lib/active_record/associations/builder/association.rb +27 -40
  17. data/lib/active_record/associations/builder/belongs_to.rb +69 -55
  18. data/lib/active_record/associations/builder/collection_association.rb +10 -33
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +52 -66
  20. data/lib/active_record/associations/builder/has_many.rb +8 -4
  21. data/lib/active_record/associations/builder/has_one.rb +46 -5
  22. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  23. data/lib/active_record/associations/collection_association.rb +131 -287
  24. data/lib/active_record/associations/collection_proxy.rb +241 -146
  25. data/lib/active_record/associations/foreign_association.rb +10 -1
  26. data/lib/active_record/associations/has_many_association.rb +34 -97
  27. data/lib/active_record/associations/has_many_through_association.rb +60 -87
  28. data/lib/active_record/associations/has_one_association.rb +61 -49
  29. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  30. data/lib/active_record/associations/join_dependency.rb +137 -167
  31. data/lib/active_record/associations/join_dependency/join_association.rb +38 -86
  32. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  33. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  34. data/lib/active_record/associations/preloader.rb +90 -92
  35. data/lib/active_record/associations/preloader/association.rb +90 -123
  36. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  37. data/lib/active_record/associations/singular_association.rb +18 -39
  38. data/lib/active_record/associations/through_association.rb +38 -18
  39. data/lib/active_record/attribute_assignment.rb +56 -183
  40. data/lib/active_record/attribute_decorators.rb +39 -15
  41. data/lib/active_record/attribute_methods.rb +120 -135
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -8
  43. data/lib/active_record/attribute_methods/dirty.rb +174 -144
  44. data/lib/active_record/attribute_methods/primary_key.rb +91 -83
  45. data/lib/active_record/attribute_methods/query.rb +6 -5
  46. data/lib/active_record/attribute_methods/read.rb +20 -76
  47. data/lib/active_record/attribute_methods/serialization.rb +40 -20
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
  49. data/lib/active_record/attribute_methods/write.rb +32 -54
  50. data/lib/active_record/attributes.rb +214 -82
  51. data/lib/active_record/autosave_association.rb +91 -37
  52. data/lib/active_record/base.rb +57 -45
  53. data/lib/active_record/callbacks.rb +100 -74
  54. data/lib/active_record/coders/json.rb +3 -1
  55. data/lib/active_record/coders/yaml_column.rb +24 -12
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +796 -296
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -115
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -23
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +170 -53
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -46
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +356 -227
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +664 -243
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +191 -83
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +460 -204
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +510 -635
  69. data/lib/active_record/connection_adapters/column.rb +56 -43
  70. data/lib/active_record/connection_adapters/connection_specification.rb +174 -152
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +58 -180
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -114
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
  96. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  100. data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
  102. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
  103. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +10 -5
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +470 -290
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +551 -356
  117. data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -345
  127. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  128. data/lib/active_record/connection_handling.rb +176 -41
  129. data/lib/active_record/core.rb +251 -231
  130. data/lib/active_record/counter_cache.rb +67 -49
  131. data/lib/active_record/database_configurations.rb +233 -0
  132. data/lib/active_record/database_configurations/database_config.rb +37 -0
  133. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  134. data/lib/active_record/database_configurations/url_config.rb +79 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +87 -105
  137. data/lib/active_record/enum.rb +163 -86
  138. data/lib/active_record/errors.rb +188 -53
  139. data/lib/active_record/explain.rb +23 -11
  140. data/lib/active_record/explain_registry.rb +4 -2
  141. data/lib/active_record/explain_subscriber.rb +10 -5
  142. data/lib/active_record/fixture_set/file.rb +35 -9
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +153 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  147. data/lib/active_record/fixtures.rb +228 -499
  148. data/lib/active_record/gem_version.rb +6 -4
  149. data/lib/active_record/inheritance.rb +158 -112
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +123 -29
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +21 -3
  154. data/lib/active_record/locale/en.yml +3 -2
  155. data/lib/active_record/locking/optimistic.rb +87 -96
  156. data/lib/active_record/locking/pessimistic.rb +18 -6
  157. data/lib/active_record/log_subscriber.rb +76 -33
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +621 -303
  162. data/lib/active_record/migration/command_recorder.rb +177 -90
  163. data/lib/active_record/migration/compatibility.rb +244 -0
  164. data/lib/active_record/migration/join_table.rb +8 -6
  165. data/lib/active_record/model_schema.rb +312 -112
  166. data/lib/active_record/nested_attributes.rb +264 -222
  167. data/lib/active_record/no_touching.rb +14 -1
  168. data/lib/active_record/null_relation.rb +24 -37
  169. data/lib/active_record/persistence.rb +557 -125
  170. data/lib/active_record/query_cache.rb +19 -23
  171. data/lib/active_record/querying.rb +43 -29
  172. data/lib/active_record/railtie.rb +143 -44
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +2 -0
  175. data/lib/active_record/railties/controller_runtime.rb +34 -33
  176. data/lib/active_record/railties/databases.rake +328 -185
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +428 -279
  179. data/lib/active_record/relation.rb +518 -341
  180. data/lib/active_record/relation/batches.rb +207 -55
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  182. data/lib/active_record/relation/calculations.rb +267 -253
  183. data/lib/active_record/relation/delegation.rb +70 -80
  184. data/lib/active_record/relation/finder_methods.rb +277 -241
  185. data/lib/active_record/relation/from_clause.rb +26 -0
  186. data/lib/active_record/relation/merger.rb +78 -87
  187. data/lib/active_record/relation/predicate_builder.rb +114 -119
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -26
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  195. data/lib/active_record/relation/query_attribute.rb +50 -0
  196. data/lib/active_record/relation/query_methods.rb +575 -394
  197. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  198. data/lib/active_record/relation/spawn_methods.rb +11 -13
  199. data/lib/active_record/relation/where_clause.rb +190 -0
  200. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  201. data/lib/active_record/result.rb +79 -42
  202. data/lib/active_record/runtime_registry.rb +6 -4
  203. data/lib/active_record/sanitization.rb +144 -121
  204. data/lib/active_record/schema.rb +21 -24
  205. data/lib/active_record/schema_dumper.rb +112 -93
  206. data/lib/active_record/schema_migration.rb +24 -17
  207. data/lib/active_record/scoping.rb +45 -26
  208. data/lib/active_record/scoping/default.rb +101 -85
  209. data/lib/active_record/scoping/named.rb +86 -33
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +5 -5
  212. data/lib/active_record/statement_cache.rb +73 -36
  213. data/lib/active_record/store.rb +127 -42
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +75 -0
  216. data/lib/active_record/tasks/database_tasks.rb +307 -100
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +55 -99
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -41
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +38 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +224 -0
  222. data/lib/active_record/timestamp.rb +86 -40
  223. data/lib/active_record/touch_later.rb +66 -0
  224. data/lib/active_record/transactions.rb +216 -150
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type.rb +78 -23
  227. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  228. data/lib/active_record/type/date.rb +4 -45
  229. data/lib/active_record/type/date_time.rb +4 -49
  230. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  231. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  232. data/lib/active_record/type/internal/timezone.rb +17 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +24 -15
  235. data/lib/active_record/type/text.rb +2 -2
  236. data/lib/active_record/type/time.rb +11 -16
  237. data/lib/active_record/type/type_map.rb +15 -17
  238. data/lib/active_record/type/unsigned_integer.rb +9 -7
  239. data/lib/active_record/type_caster.rb +9 -0
  240. data/lib/active_record/type_caster/connection.rb +34 -0
  241. data/lib/active_record/type_caster/map.rb +20 -0
  242. data/lib/active_record/validations.rb +39 -35
  243. data/lib/active_record/validations/absence.rb +25 -0
  244. data/lib/active_record/validations/associated.rb +13 -4
  245. data/lib/active_record/validations/length.rb +26 -0
  246. data/lib/active_record/validations/presence.rb +14 -13
  247. data/lib/active_record/validations/uniqueness.rb +42 -55
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/arel.rb +51 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +257 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +204 -0
  317. data/lib/arel/visitors/dot.rb +297 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +157 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +159 -0
  323. data/lib/arel/visitors/oracle12.rb +66 -0
  324. data/lib/arel/visitors/postgresql.rb +110 -0
  325. data/lib/arel/visitors/sqlite.rb +39 -0
  326. data/lib/arel/visitors/to_sql.rb +889 -0
  327. data/lib/arel/visitors/visitor.rb +46 -0
  328. data/lib/arel/visitors/where_sql.rb +23 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +7 -5
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration.rb +31 -1
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
  335. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  336. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -2
  337. data/lib/rails/generators/active_record/model/model_generator.rb +19 -22
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  340. metadata +164 -59
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  343. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  344. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  345. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  348. data/lib/active_record/attribute.rb +0 -163
  349. data/lib/active_record/attribute_set.rb +0 -81
  350. data/lib/active_record/attribute_set/builder.rb +0 -106
  351. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  352. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  353. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  354. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  355. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  356. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  357. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  358. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  359. data/lib/active_record/type/big_integer.rb +0 -13
  360. data/lib/active_record/type/binary.rb +0 -50
  361. data/lib/active_record/type/boolean.rb +0 -31
  362. data/lib/active_record/type/decimal.rb +0 -64
  363. data/lib/active_record/type/decorator.rb +0 -14
  364. data/lib/active_record/type/float.rb +0 -19
  365. data/lib/active_record/type/integer.rb +0 -59
  366. data/lib/active_record/type/mutable.rb +0 -16
  367. data/lib/active_record/type/numeric.rb +0 -36
  368. data/lib/active_record/type/string.rb +0 -40
  369. data/lib/active_record/type/time_value.rb +0 -38
  370. data/lib/active_record/type/value.rb +0 -110
  371. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
  372. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,11 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
- # = Active Record Through Association
3
4
  module Associations
5
+ # = Active Record Through Association
4
6
  module ThroughAssociation #:nodoc:
7
+ delegate :source_reflection, to: :reflection
8
+
9
+ private
10
+ def through_reflection
11
+ @through_reflection ||= begin
12
+ refl = reflection.through_reflection
5
13
 
6
- delegate :source_reflection, :through_reflection, :to => :reflection
14
+ while refl.through_reflection?
15
+ refl = refl.through_reflection
16
+ end
17
+
18
+ refl
19
+ end
20
+ end
7
21
 
8
- protected
22
+ def through_association
23
+ @through_association ||= owner.association(through_reflection.name)
24
+ end
9
25
 
10
26
  # We merge in these scopes for two reasons:
11
27
  #
@@ -14,7 +30,7 @@ module ActiveRecord
14
30
  def target_scope
15
31
  scope = super
16
32
  reflection.chain.drop(1).each do |reflection|
17
- relation = reflection.klass.all
33
+ relation = reflection.klass.scope_for_association
18
34
  scope.merge!(
19
35
  relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load)
20
36
  )
@@ -22,12 +38,10 @@ module ActiveRecord
22
38
  scope
23
39
  end
24
40
 
25
- private
26
-
27
41
  # Construct attributes for :through pointing to owner and associate. This is used by the
28
42
  # methods which create and delete records on the association.
29
43
  #
30
- # We only support indirectly modifying through associations which has a belongs_to source.
44
+ # We only support indirectly modifying through associations which have a belongs_to source.
31
45
  # This is the "has_many :tags, through: :taggings" situation, where the join model
32
46
  # typically has a belongs_to on both side. In other words, associations which could also
33
47
  # be represented as has_and_belongs_to_many associations.
@@ -39,24 +53,22 @@ module ActiveRecord
39
53
  def construct_join_attributes(*records)
40
54
  ensure_mutable
41
55
 
42
- if source_reflection.association_primary_key(reflection.klass) == reflection.klass.primary_key
56
+ association_primary_key = source_reflection.association_primary_key(reflection.klass)
57
+
58
+ if association_primary_key == reflection.klass.primary_key && !options[:source_type]
43
59
  join_attributes = { source_reflection.name => records }
44
60
  else
45
61
  join_attributes = {
46
- source_reflection.foreign_key =>
47
- records.map { |record|
48
- record.send(source_reflection.association_primary_key(reflection.klass))
49
- }
62
+ source_reflection.foreign_key => records.map(&association_primary_key.to_sym)
50
63
  }
51
64
  end
52
65
 
53
66
  if options[:source_type]
54
- join_attributes[source_reflection.foreign_type] =
55
- records.map { |record| record.class.base_class.name }
67
+ join_attributes[source_reflection.foreign_type] = [ options[:source_type] ]
56
68
  end
57
69
 
58
70
  if records.count == 1
59
- Hash[join_attributes.map { |k, v| [k, v.first] }]
71
+ join_attributes.transform_values!(&:first)
60
72
  else
61
73
  join_attributes
62
74
  end
@@ -76,13 +88,21 @@ module ActiveRecord
76
88
 
77
89
  def ensure_mutable
78
90
  unless source_reflection.belongs_to?
79
- raise HasManyThroughCantAssociateThroughHasOneOrManyReflection.new(owner, reflection)
91
+ if reflection.has_one?
92
+ raise HasOneThroughCantAssociateThroughHasOneOrManyReflection.new(owner, reflection)
93
+ else
94
+ raise HasManyThroughCantAssociateThroughHasOneOrManyReflection.new(owner, reflection)
95
+ end
80
96
  end
81
97
  end
82
98
 
83
99
  def ensure_not_nested
84
100
  if reflection.nested?
85
- raise HasManyThroughNestedAssociationsAreReadonly.new(owner, reflection)
101
+ if reflection.has_one?
102
+ raise HasOneThroughNestedAssociationsAreReadonly.new(owner, reflection)
103
+ else
104
+ raise HasManyThroughNestedAssociationsAreReadonly.new(owner, reflection)
105
+ end
86
106
  end
87
107
  end
88
108
 
@@ -94,7 +114,7 @@ module ActiveRecord
94
114
  attributes[inverse.foreign_key] = target.id
95
115
  end
96
116
 
97
- super(attributes)
117
+ super
98
118
  end
99
119
  end
100
120
  end
@@ -1,212 +1,85 @@
1
- require 'active_model/forbidden_attributes_protection'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_model/forbidden_attributes_protection"
2
4
 
3
5
  module ActiveRecord
4
6
  module AttributeAssignment
5
- extend ActiveSupport::Concern
6
- include ActiveModel::ForbiddenAttributesProtection
7
-
8
- # Allows you to set all the attributes by passing in a hash of attributes with
9
- # keys matching the attribute names (which again matches the column names).
10
- #
11
- # If the passed hash responds to <tt>permitted?</tt> method and the return value
12
- # of this method is +false+ an <tt>ActiveModel::ForbiddenAttributesError</tt>
13
- # exception is raised.
14
- #
15
- # cat = Cat.new(name: "Gorby", status: "yawning")
16
- # cat.attributes # => { "name" => "Gorby", "status" => "yawning", "created_at" => nil, "updated_at" => nil}
17
- # cat.assign_attributes(status: "sleeping")
18
- # cat.attributes # => { "name" => "Gorby", "status" => "sleeping", "created_at" => nil, "updated_at" => nil }
19
- #
20
- # New attributes will be persisted in the database when the object is saved.
21
- #
22
- # Aliased to <tt>attributes=</tt>.
23
- def assign_attributes(new_attributes)
24
- if !new_attributes.respond_to?(:stringify_keys)
25
- raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
26
- end
27
- return if new_attributes.blank?
28
-
29
- attributes = new_attributes.stringify_keys
30
- multi_parameter_attributes = []
31
- nested_parameter_attributes = []
32
-
33
- attributes = sanitize_for_mass_assignment(attributes)
34
-
35
- attributes.each do |k, v|
36
- if k.include?("(")
37
- multi_parameter_attributes << [ k, v ]
38
- elsif v.is_a?(Hash)
39
- nested_parameter_attributes << [ k, v ]
40
- else
41
- _assign_attribute(k, v)
42
- end
43
- end
44
-
45
- assign_nested_parameter_attributes(nested_parameter_attributes) unless nested_parameter_attributes.empty?
46
- assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty?
47
- end
48
-
49
- alias attributes= assign_attributes
7
+ include ActiveModel::AttributeAssignment
50
8
 
51
9
  private
52
10
 
53
- def _assign_attribute(k, v)
54
- public_send("#{k}=", v)
55
- rescue NoMethodError, NameError
56
- if respond_to?("#{k}=")
57
- raise
58
- else
59
- raise UnknownAttributeError.new(self, k)
60
- end
61
- end
11
+ def _assign_attributes(attributes)
12
+ multi_parameter_attributes = {}
13
+ nested_parameter_attributes = {}
62
14
 
63
- # Assign any deferred nested attributes after the base attributes have been set.
64
- def assign_nested_parameter_attributes(pairs)
65
- pairs.each { |k, v| _assign_attribute(k, v) }
66
- end
67
-
68
- # Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
69
- # by calling new on the column type or aggregation type (through composed_of) object with these parameters.
70
- # So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
71
- # written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
72
- # parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and
73
- # f for Float. If all the values for a given attribute are empty, the attribute will be set to +nil+.
74
- def assign_multiparameter_attributes(pairs)
75
- execute_callstack_for_multiparameter_attributes(
76
- extract_callstack_for_multiparameter_attributes(pairs)
77
- )
78
- end
79
-
80
- def execute_callstack_for_multiparameter_attributes(callstack)
81
- errors = []
82
- callstack.each do |name, values_with_empty_parameters|
83
- begin
84
- send("#{name}=", MultiparameterAttribute.new(self, name, values_with_empty_parameters).read_value)
85
- rescue => ex
86
- errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name} (#{ex.message})", ex, name)
15
+ attributes.each do |k, v|
16
+ if k.include?("(")
17
+ multi_parameter_attributes[k] = attributes.delete(k)
18
+ elsif v.is_a?(Hash)
19
+ nested_parameter_attributes[k] = attributes.delete(k)
20
+ end
87
21
  end
88
- end
89
- unless errors.empty?
90
- error_descriptions = errors.map { |ex| ex.message }.join(",")
91
- raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes [#{error_descriptions}]"
92
- end
93
- end
94
-
95
- def extract_callstack_for_multiparameter_attributes(pairs)
96
- attributes = {}
22
+ super(attributes)
97
23
 
98
- pairs.each do |(multiparameter_name, value)|
99
- attribute_name = multiparameter_name.split("(").first
100
- attributes[attribute_name] ||= {}
101
-
102
- parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
103
- attributes[attribute_name][find_parameter_position(multiparameter_name)] ||= parameter_value
24
+ assign_nested_parameter_attributes(nested_parameter_attributes) unless nested_parameter_attributes.empty?
25
+ assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty?
104
26
  end
105
27
 
106
- attributes
107
- end
108
-
109
- def type_cast_attribute_value(multiparameter_name, value)
110
- multiparameter_name =~ /\([0-9]*([if])\)/ ? value.send("to_" + $1) : value
111
- end
112
-
113
- def find_parameter_position(multiparameter_name)
114
- multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i
115
- end
116
-
117
- class MultiparameterAttribute #:nodoc:
118
- attr_reader :object, :name, :values, :cast_type
119
-
120
- def initialize(object, name, values)
121
- @object = object
122
- @name = name
123
- @values = values
124
- end
125
-
126
- def read_value
127
- return if values.values.compact.empty?
128
-
129
- @cast_type = object.type_for_attribute(name)
130
- klass = cast_type.klass
131
-
132
- if klass == Time
133
- read_time
134
- elsif klass == Date
135
- read_date
136
- else
137
- read_other
138
- end
28
+ # Assign any deferred nested attributes after the base attributes have been set.
29
+ def assign_nested_parameter_attributes(pairs)
30
+ pairs.each { |k, v| _assign_attribute(k, v) }
139
31
  end
140
32
 
141
- private
142
-
143
- def instantiate_time_object(set_values)
144
- if object.class.send(:create_time_zone_conversion_attribute?, name, cast_type)
145
- Time.zone.local(*set_values)
146
- else
147
- Time.send(object.class.default_timezone, *set_values)
148
- end
33
+ # Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
34
+ # by calling new on the column type or aggregation type (through composed_of) object with these parameters.
35
+ # So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
36
+ # written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
37
+ # parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and
38
+ # f for Float. If all the values for a given attribute are empty, the attribute will be set to +nil+.
39
+ def assign_multiparameter_attributes(pairs)
40
+ execute_callstack_for_multiparameter_attributes(
41
+ extract_callstack_for_multiparameter_attributes(pairs)
42
+ )
149
43
  end
150
44
 
151
- def read_time
152
- # If column is a :time (and not :date or :datetime) there is no need to validate if
153
- # there are year/month/day fields
154
- if cast_type.type == :time
155
- # if the column is a time set the values to their defaults as January 1, 1970, but only if they're nil
156
- { 1 => 1970, 2 => 1, 3 => 1 }.each do |key,value|
157
- values[key] ||= value
45
+ def execute_callstack_for_multiparameter_attributes(callstack)
46
+ errors = []
47
+ callstack.each do |name, values_with_empty_parameters|
48
+ if values_with_empty_parameters.each_value.all?(&:nil?)
49
+ values = nil
50
+ else
51
+ values = values_with_empty_parameters
158
52
  end
159
- else
160
- # else column is a timestamp, so if Date bits were not provided, error
161
- validate_required_parameters!([1,2,3])
162
-
163
- # If Date bits were provided but blank, then return nil
164
- return if blank_date_parameter?
53
+ send("#{name}=", values)
54
+ rescue => ex
55
+ errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name} (#{ex.message})", ex, name)
165
56
  end
166
-
167
- max_position = extract_max_param(6)
168
- set_values = values.values_at(*(1..max_position))
169
- # If Time bits are not there, then default to 0
170
- (3..5).each { |i| set_values[i] = set_values[i].presence || 0 }
171
- instantiate_time_object(set_values)
172
- end
173
-
174
- def read_date
175
- return if blank_date_parameter?
176
- set_values = values.values_at(1,2,3)
177
- begin
178
- Date.new(*set_values)
179
- rescue ArgumentError # if Date.new raises an exception on an invalid date
180
- instantiate_time_object(set_values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
57
+ unless errors.empty?
58
+ error_descriptions = errors.map(&:message).join(",")
59
+ raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes [#{error_descriptions}]"
181
60
  end
182
61
  end
183
62
 
184
- def read_other
185
- max_position = extract_max_param
186
- positions = (1..max_position)
187
- validate_required_parameters!(positions)
63
+ def extract_callstack_for_multiparameter_attributes(pairs)
64
+ attributes = {}
188
65
 
189
- values.slice(*positions)
190
- end
66
+ pairs.each do |(multiparameter_name, value)|
67
+ attribute_name = multiparameter_name.split("(").first
68
+ attributes[attribute_name] ||= {}
191
69
 
192
- # Checks whether some blank date parameter exists. Note that this is different
193
- # than the validate_required_parameters! method, since it just checks for blank
194
- # positions instead of missing ones, and does not raise in case one blank position
195
- # exists. The caller is responsible to handle the case of this returning true.
196
- def blank_date_parameter?
197
- (1..3).any? { |position| values[position].blank? }
70
+ parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
71
+ attributes[attribute_name][find_parameter_position(multiparameter_name)] ||= parameter_value
72
+ end
73
+
74
+ attributes
198
75
  end
199
76
 
200
- # If some position is not provided, it errors out a missing parameter exception.
201
- def validate_required_parameters!(positions)
202
- if missing_parameter = positions.detect { |position| !values.key?(position) }
203
- raise ArgumentError.new("Missing Parameter - #{name}(#{missing_parameter})")
204
- end
77
+ def type_cast_attribute_value(multiparameter_name, value)
78
+ multiparameter_name =~ /\([0-9]*([if])\)/ ? value.send("to_" + $1) : value
205
79
  end
206
80
 
207
- def extract_max_param(upper_cap = 100)
208
- [values.keys.max, upper_cap].min
81
+ def find_parameter_position(multiparameter_name)
82
+ multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i
209
83
  end
210
- end
211
84
  end
212
85
  end
@@ -1,21 +1,44 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module AttributeDecorators # :nodoc:
3
5
  extend ActiveSupport::Concern
4
6
 
5
7
  included do
6
- class_attribute :attribute_type_decorations, instance_accessor: false # :internal:
7
- self.attribute_type_decorations = TypeDecorator.new
8
+ class_attribute :attribute_type_decorations, instance_accessor: false, default: TypeDecorator.new # :internal:
8
9
  end
9
10
 
10
11
  module ClassMethods # :nodoc:
12
+ # This method is an internal API used to create class macros such as
13
+ # +serialize+, and features like time zone aware attributes.
14
+ #
15
+ # Used to wrap the type of an attribute in a new type.
16
+ # When the schema for a model is loaded, attributes with the same name as
17
+ # +column_name+ will have their type yielded to the given block. The
18
+ # return value of that block will be used instead.
19
+ #
20
+ # Subsequent calls where +column_name+ and +decorator_name+ are the same
21
+ # will override the previous decorator, not decorate twice. This can be
22
+ # used to create idempotent class macros like +serialize+
11
23
  def decorate_attribute_type(column_name, decorator_name, &block)
12
24
  matcher = ->(name, _) { name == column_name.to_s }
13
25
  key = "_#{column_name}_#{decorator_name}"
14
26
  decorate_matching_attribute_types(matcher, key, &block)
15
27
  end
16
28
 
29
+ # This method is an internal API used to create higher level features like
30
+ # time zone aware attributes.
31
+ #
32
+ # When the schema for a model is loaded, +matcher+ will be called for each
33
+ # attribute with its name and type. If the matcher returns a truthy value,
34
+ # the type will then be yielded to the given block, and the return value
35
+ # of that block will replace the type.
36
+ #
37
+ # Subsequent calls to this method with the same value for +decorator_name+
38
+ # will replace the previous decorator, not decorate twice. This can be
39
+ # used to ensure that class macros are idempotent.
17
40
  def decorate_matching_attribute_types(matcher, decorator_name, &block)
18
- clear_caches_calculated_from_columns
41
+ reload_schema_from_cache
19
42
  decorator_name = decorator_name.to_s
20
43
 
21
44
  # Create new hashes so we don't modify parent classes
@@ -24,12 +47,13 @@ module ActiveRecord
24
47
 
25
48
  private
26
49
 
27
- def add_user_provided_columns(*)
28
- super.map do |column|
29
- decorated_type = attribute_type_decorations.apply(column.name, column.cast_type)
30
- column.with_type(decorated_type)
50
+ def load_schema!
51
+ super
52
+ attribute_types.each do |name, type|
53
+ decorated_type = attribute_type_decorations.apply(name, type)
54
+ define_attribute(name, decorated_type)
55
+ end
31
56
  end
32
- end
33
57
  end
34
58
 
35
59
  class TypeDecorator # :nodoc:
@@ -52,15 +76,15 @@ module ActiveRecord
52
76
 
53
77
  private
54
78
 
55
- def decorators_for(name, type)
56
- matching(name, type).map(&:last)
57
- end
79
+ def decorators_for(name, type)
80
+ matching(name, type).map(&:last)
81
+ end
58
82
 
59
- def matching(name, type)
60
- @decorations.values.select do |(matcher, _)|
61
- matcher.call(name, type)
83
+ def matching(name, type)
84
+ @decorations.values.select do |(matcher, _)|
85
+ matcher.call(name, type)
86
+ end
62
87
  end
63
- end
64
88
  end
65
89
  end
66
90
  end