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,31 +1,91 @@
1
- require 'date'
2
- require 'set'
3
- require 'bigdecimal'
4
- require 'bigdecimal/util'
1
+ # frozen_string_literal: true
5
2
 
6
3
  module ActiveRecord
7
4
  module ConnectionAdapters #:nodoc:
8
5
  # Abstract representation of an index definition on a table. Instances of
9
6
  # this type are typically created and returned by methods in database
10
- # adapters. e.g. ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#indexes
11
- class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using) #:nodoc:
7
+ # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes
8
+ class IndexDefinition # :nodoc:
9
+ attr_reader :table, :name, :unique, :columns, :lengths, :orders, :opclasses, :where, :type, :using, :comment
10
+
11
+ def initialize(
12
+ table, name,
13
+ unique = false,
14
+ columns = [],
15
+ lengths: {},
16
+ orders: {},
17
+ opclasses: {},
18
+ where: nil,
19
+ type: nil,
20
+ using: nil,
21
+ comment: nil
22
+ )
23
+ @table = table
24
+ @name = name
25
+ @unique = unique
26
+ @columns = columns
27
+ @lengths = concise_options(lengths)
28
+ @orders = concise_options(orders)
29
+ @opclasses = concise_options(opclasses)
30
+ @where = where
31
+ @type = type
32
+ @using = using
33
+ @comment = comment
34
+ end
35
+
36
+ def column_options
37
+ {
38
+ length: lengths,
39
+ order: orders,
40
+ opclass: opclasses,
41
+ }
42
+ end
43
+
44
+ private
45
+ def concise_options(options)
46
+ if columns.size == options.size && options.values.uniq.size == 1
47
+ options.values.first
48
+ else
49
+ options
50
+ end
51
+ end
12
52
  end
13
53
 
14
54
  # Abstract representation of a column definition. Instances of this type
15
55
  # are typically created by methods in TableDefinition, and added to the
16
56
  # +columns+ attribute of said TableDefinition object, in order to be used
17
57
  # for generating a number of table creation or table changing SQL statements.
18
- class ColumnDefinition < Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :primary_key, :sql_type, :cast_type) #:nodoc:
19
-
58
+ ColumnDefinition = Struct.new(:name, :type, :options, :sql_type) do # :nodoc:
20
59
  def primary_key?
21
- primary_key || type.to_sym == :primary_key
60
+ options[:primary_key]
22
61
  end
23
- end
24
62
 
25
- class ChangeColumnDefinition < Struct.new(:column, :type, :options) #:nodoc:
63
+ [:limit, :precision, :scale, :default, :null, :collation, :comment].each do |option_name|
64
+ module_eval <<-CODE, __FILE__, __LINE__ + 1
65
+ def #{option_name}
66
+ options[:#{option_name}]
67
+ end
68
+
69
+ def #{option_name}=(value)
70
+ options[:#{option_name}] = value
71
+ end
72
+ CODE
73
+ end
74
+
75
+ def aliased_types(name, fallback)
76
+ "timestamp" == name ? :datetime : fallback
77
+ end
26
78
  end
27
79
 
28
- class ForeignKeyDefinition < Struct.new(:from_table, :to_table, :options) #:nodoc:
80
+ AddColumnDefinition = Struct.new(:column) # :nodoc:
81
+
82
+ ChangeColumnDefinition = Struct.new(:column, :name) #:nodoc:
83
+
84
+ CreateIndexDefinition = Struct.new(:index, :algorithm, :if_not_exists) # :nodoc:
85
+
86
+ PrimaryKeyDefinition = Struct.new(:name) # :nodoc:
87
+
88
+ ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do #:nodoc:
29
89
  def name
30
90
  options[:name]
31
91
  end
@@ -50,31 +110,174 @@ module ActiveRecord
50
110
  options[:primary_key] != default_primary_key
51
111
  end
52
112
 
113
+ def validate?
114
+ options.fetch(:validate, true)
115
+ end
116
+ alias validated? validate?
117
+
118
+ def export_name_on_schema_dump?
119
+ !ActiveRecord::SchemaDumper.fk_ignore_pattern.match?(name) if name
120
+ end
121
+
122
+ def defined_for?(to_table: nil, validate: nil, **options)
123
+ (to_table.nil? || to_table.to_s == self.to_table) &&
124
+ (validate.nil? || validate == options.fetch(:validate, validate)) &&
125
+ options.all? { |k, v| self.options[k].to_s == v.to_s }
126
+ end
127
+
53
128
  private
54
- def default_primary_key
55
- "id"
129
+ def default_primary_key
130
+ "id"
131
+ end
132
+ end
133
+
134
+ CheckConstraintDefinition = Struct.new(:table_name, :expression, :options) do
135
+ def name
136
+ options[:name]
137
+ end
138
+
139
+ def validate?
140
+ options.fetch(:validate, true)
141
+ end
142
+ alias validated? validate?
143
+
144
+ def export_name_on_schema_dump?
145
+ !ActiveRecord::SchemaDumper.chk_ignore_pattern.match?(name) if name
146
+ end
147
+ end
148
+
149
+ class ReferenceDefinition # :nodoc:
150
+ def initialize(
151
+ name,
152
+ polymorphic: false,
153
+ index: true,
154
+ foreign_key: false,
155
+ type: :bigint,
156
+ **options
157
+ )
158
+ @name = name
159
+ @polymorphic = polymorphic
160
+ @index = index
161
+ @foreign_key = foreign_key
162
+ @type = type
163
+ @options = options
164
+
165
+ if polymorphic && foreign_key
166
+ raise ArgumentError, "Cannot add a foreign key to a polymorphic relation"
167
+ end
168
+ end
169
+
170
+ def add_to(table)
171
+ columns.each do |name, type, options|
172
+ table.column(name, type, **options)
173
+ end
174
+
175
+ if index
176
+ table.index(column_names, **index_options(table.name))
177
+ end
178
+
179
+ if foreign_key
180
+ table.foreign_key(foreign_table_name, **foreign_key_options)
181
+ end
56
182
  end
183
+
184
+ private
185
+ attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
186
+
187
+ def as_options(value)
188
+ value.is_a?(Hash) ? value : {}
189
+ end
190
+
191
+ def polymorphic_options
192
+ as_options(polymorphic).merge(options.slice(:null, :first, :after))
193
+ end
194
+
195
+ def polymorphic_index_name(table_name)
196
+ "index_#{table_name}_on_#{name}"
197
+ end
198
+
199
+ def index_options(table_name)
200
+ index_options = as_options(index)
201
+ index_options[:name] ||= polymorphic_index_name(table_name) if polymorphic
202
+ index_options
203
+ end
204
+
205
+ def foreign_key_options
206
+ as_options(foreign_key).merge(column: column_name)
207
+ end
208
+
209
+ def columns
210
+ result = [[column_name, type, options]]
211
+ if polymorphic
212
+ result.unshift(["#{name}_type", :string, polymorphic_options])
213
+ end
214
+ result
215
+ end
216
+
217
+ def column_name
218
+ "#{name}_id"
219
+ end
220
+
221
+ def column_names
222
+ columns.map(&:first)
223
+ end
224
+
225
+ def foreign_table_name
226
+ foreign_key_options.fetch(:to_table) do
227
+ Base.pluralize_table_names ? name.to_s.pluralize : name
228
+ end
229
+ end
57
230
  end
58
231
 
59
- module TimestampDefaultDeprecation # :nodoc:
60
- def emit_warning_if_null_unspecified(sym, options)
61
- return if options.key?(:null)
232
+ module ColumnMethods
233
+ extend ActiveSupport::Concern
62
234
 
63
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
64
- `##{sym}` was called without specifying an option for `null`. In Rails 5,
65
- this behavior will change to `null: false`. You should manually specify
66
- `null: true` to prevent the behavior of your existing migrations from changing.
67
- MSG
235
+ # Appends a primary key definition to the table definition.
236
+ # Can be called multiple times, but this is probably not a good idea.
237
+ def primary_key(name, type = :primary_key, **options)
238
+ column(name, type, **options.merge(primary_key: true))
239
+ end
240
+
241
+ ##
242
+ # :method: column
243
+ # :call-seq: column(name, type, **options)
244
+ #
245
+ # Appends a column or columns of a specified type.
246
+ #
247
+ # t.string(:goat)
248
+ # t.string(:goat, :sheep)
249
+ #
250
+ # See TableDefinition#column
251
+
252
+ included do
253
+ define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
254
+ :float, :integer, :json, :string, :text, :time, :timestamp, :virtual
255
+
256
+ alias :numeric :decimal
257
+ end
258
+
259
+ class_methods do
260
+ def define_column_methods(*column_types) # :nodoc:
261
+ column_types.each do |column_type|
262
+ module_eval <<-RUBY, __FILE__, __LINE__ + 1
263
+ def #{column_type}(*names, **options)
264
+ raise ArgumentError, "Missing column name(s) for #{column_type}" if names.empty?
265
+ names.each { |name| column(name, :#{column_type}, **options) }
266
+ end
267
+ RUBY
268
+ end
269
+ end
270
+ private :define_column_methods
68
271
  end
69
272
  end
70
273
 
71
274
  # Represents the schema of an SQL table in an abstract way. This class
72
275
  # provides methods for manipulating the schema representation.
73
276
  #
74
- # Inside migration files, the +t+ object in +create_table+
277
+ # Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
75
278
  # is actually of this type:
76
279
  #
77
- # class SomeMigration < ActiveRecord::Migration
280
+ # class SomeMigration < ActiveRecord::Migration[6.0]
78
281
  # def up
79
282
  # create_table :foo do |t|
80
283
  # puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
@@ -86,125 +289,66 @@ module ActiveRecord
86
289
  # end
87
290
  # end
88
291
  #
89
- # The table definitions
90
- # The Columns are stored as a ColumnDefinition in the +columns+ attribute.
91
292
  class TableDefinition
92
- include TimestampDefaultDeprecation
93
-
94
- # An array of ColumnDefinition objects, representing the column changes
95
- # that have been defined.
96
- attr_accessor :indexes
97
- attr_reader :name, :temporary, :options, :as, :foreign_keys
98
-
99
- def initialize(types, name, temporary, options, as = nil)
293
+ include ColumnMethods
294
+
295
+ attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys, :check_constraints
296
+
297
+ def initialize(
298
+ conn,
299
+ name,
300
+ temporary: false,
301
+ if_not_exists: false,
302
+ options: nil,
303
+ as: nil,
304
+ comment: nil,
305
+ **
306
+ )
307
+ @conn = conn
100
308
  @columns_hash = {}
101
- @indexes = {}
309
+ @indexes = []
102
310
  @foreign_keys = []
103
- @native = types
311
+ @primary_keys = nil
312
+ @check_constraints = []
104
313
  @temporary = temporary
314
+ @if_not_exists = if_not_exists
105
315
  @options = options
106
316
  @as = as
107
317
  @name = name
318
+ @comment = comment
108
319
  end
109
320
 
110
- def columns; @columns_hash.values; end
111
-
112
- # Appends a primary key definition to the table definition.
113
- # Can be called multiple times, but this is probably not a good idea.
114
- def primary_key(name, type = :primary_key, options = {})
115
- column(name, type, options.merge(:primary_key => true))
321
+ def primary_keys(name = nil) # :nodoc:
322
+ @primary_keys = PrimaryKeyDefinition.new(name) if name
323
+ @primary_keys
116
324
  end
117
325
 
326
+ # Returns an array of ColumnDefinition objects for the columns of the table.
327
+ def columns; @columns_hash.values; end
328
+
118
329
  # Returns a ColumnDefinition for the column with name +name+.
119
330
  def [](name)
120
331
  @columns_hash[name.to_s]
121
332
  end
122
333
 
123
334
  # Instantiates a new column for the table.
124
- # The +type+ parameter is normally one of the migrations native types,
125
- # which is one of the following:
126
- # <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
127
- # <tt>:integer</tt>, <tt>:float</tt>, <tt>:decimal</tt>,
128
- # <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
129
- # <tt>:binary</tt>, <tt>:boolean</tt>.
130
- #
131
- # You may use a type not in this list as long as it is supported by your
132
- # database (for example, "polygon" in MySQL), but this will not be database
133
- # agnostic and should usually be avoided.
134
- #
135
- # Available options are (none of these exists by default):
136
- # * <tt>:limit</tt> -
137
- # Requests a maximum column length. This is number of characters for <tt>:string</tt> and
138
- # <tt>:text</tt> columns and number of bytes for <tt>:binary</tt> and <tt>:integer</tt> columns.
139
- # * <tt>:default</tt> -
140
- # The column's default value. Use nil for NULL.
141
- # * <tt>:null</tt> -
142
- # Allows or disallows +NULL+ values in the column. This option could
143
- # have been named <tt>:null_allowed</tt>.
144
- # * <tt>:precision</tt> -
145
- # Specifies the precision for a <tt>:decimal</tt> column.
146
- # * <tt>:scale</tt> -
147
- # Specifies the scale for a <tt>:decimal</tt> column.
335
+ # See {connection.add_column}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_column]
336
+ # for available options.
337
+ #
338
+ # Additional options are:
148
339
  # * <tt>:index</tt> -
149
340
  # Create an index for the column. Can be either <tt>true</tt> or an options hash.
150
341
  #
151
- # Note: The precision is the total number of significant digits
152
- # and the scale is the number of digits that can be stored following
153
- # the decimal point. For example, the number 123.45 has a precision of 5
154
- # and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
155
- # range from -999.99 to 999.99.
156
- #
157
- # Please be aware of different RDBMS implementations behavior with
158
- # <tt>:decimal</tt> columns:
159
- # * The SQL standard says the default scale should be 0, <tt>:scale</tt> <=
160
- # <tt>:precision</tt>, and makes no comments about the requirements of
161
- # <tt>:precision</tt>.
162
- # * MySQL: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..30].
163
- # Default is (10,0).
164
- # * PostgreSQL: <tt>:precision</tt> [1..infinity],
165
- # <tt>:scale</tt> [0..infinity]. No default.
166
- # * SQLite2: Any <tt>:precision</tt> and <tt>:scale</tt> may be used.
167
- # Internal storage as strings. No default.
168
- # * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
169
- # but the maximum supported <tt>:precision</tt> is 16. No default.
170
- # * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
171
- # Default is (38,0).
172
- # * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
173
- # Default unknown.
174
- # * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
175
- # Default (38,0).
176
- #
177
342
  # This method returns <tt>self</tt>.
178
343
  #
179
344
  # == Examples
180
- # # Assuming +td+ is an instance of TableDefinition
181
- # td.column(:granted, :boolean)
182
- # # granted BOOLEAN
183
345
  #
184
- # td.column(:picture, :binary, limit: 2.megabytes)
185
- # # => picture BLOB(2097152)
186
- #
187
- # td.column(:sales_stage, :string, limit: 20, default: 'new', null: false)
188
- # # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
189
- #
190
- # td.column(:bill_gates_money, :decimal, precision: 15, scale: 2)
191
- # # => bill_gates_money DECIMAL(15,2)
192
- #
193
- # td.column(:sensor_reading, :decimal, precision: 30, scale: 20)
194
- # # => sensor_reading DECIMAL(30,20)
195
- #
196
- # # While <tt>:scale</tt> defaults to zero on most databases, it
197
- # # probably wouldn't hurt to include it.
198
- # td.column(:huge_integer, :decimal, precision: 30)
199
- # # => huge_integer DECIMAL(30)
200
- #
201
- # # Defines a column with a database-specific type.
202
- # td.column(:foo, 'polygon')
203
- # # => foo polygon
346
+ # # Assuming +td+ is an instance of TableDefinition
347
+ # td.column(:granted, :boolean, index: true)
204
348
  #
205
349
  # == Short-hand examples
206
350
  #
207
- # Instead of calling +column+ directly, you can also work with the short-hand definitions for the default types.
351
+ # Instead of calling #column directly, you can also work with the short-hand definitions for the default types.
208
352
  # They use the type as the method name instead of as a parameter and allow for multiple columns to be defined
209
353
  # in a single statement.
210
354
  #
@@ -236,7 +380,8 @@ module ActiveRecord
236
380
  # TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
237
381
  # column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of
238
382
  # options, these will be used when creating the <tt>_type</tt> column. The <tt>:index</tt> option
239
- # will also create an index, similar to calling <tt>add_index</tt>. So what can be written like this:
383
+ # will also create an index, similar to calling {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index].
384
+ # So what can be written like this:
240
385
  #
241
386
  # create_table :taggings do |t|
242
387
  # t.integer :tag_id, :tagger_id, :taggable_id
@@ -250,130 +395,122 @@ module ActiveRecord
250
395
  #
251
396
  # create_table :taggings do |t|
252
397
  # t.references :tag, index: { name: 'index_taggings_on_tag_id' }
253
- # t.references :tagger, polymorphic: true, index: true
254
- # t.references :taggable, polymorphic: { default: 'Photo' }
398
+ # t.references :tagger, polymorphic: true
399
+ # t.references :taggable, polymorphic: { default: 'Photo' }, index: false
255
400
  # end
256
- def column(name, type, options = {})
401
+ def column(name, type, index: nil, **options)
257
402
  name = name.to_s
258
- type = type.to_sym
259
- options = options.dup
403
+ type = type.to_sym if type
404
+
405
+ if @columns_hash[name]
406
+ if @columns_hash[name].primary_key?
407
+ raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
408
+ else
409
+ raise ArgumentError, "you can't define an already defined column '#{name}'."
410
+ end
411
+ end
412
+
413
+ @columns_hash[name] = new_column_definition(name, type, **options)
260
414
 
261
- if @columns_hash[name] && @columns_hash[name].primary_key?
262
- raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
415
+ if index
416
+ index_options = index.is_a?(Hash) ? index : {}
417
+ index(name, **index_options)
263
418
  end
264
419
 
265
- index_options = options.delete(:index)
266
- index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
267
- @columns_hash[name] = new_column_definition(name, type, options)
268
420
  self
269
421
  end
270
422
 
423
+ # remove the column +name+ from the table.
424
+ # remove_column(:account_id)
271
425
  def remove_column(name)
272
426
  @columns_hash.delete name.to_s
273
427
  end
274
428
 
275
- [:string, :text, :integer, :bigint, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
276
- define_method column_type do |*args|
277
- options = args.extract_options!
278
- column_names = args
279
- column_names.each { |name| column(name, column_type, options) }
280
- end
281
- end
282
-
283
429
  # Adds index options to the indexes hash, keyed by column name
284
430
  # This is primarily used to track indexes that need to be created after the table
285
431
  #
286
432
  # index(:account_id, name: 'index_projects_on_account_id')
287
- def index(column_name, options = {})
288
- indexes[column_name] = options
433
+ def index(column_name, **options)
434
+ indexes << [column_name, options]
289
435
  end
290
436
 
291
- def foreign_key(table_name, options = {}) # :nodoc:
292
- foreign_keys.push([table_name, options])
437
+ def foreign_key(table_name, **options) # :nodoc:
438
+ foreign_keys << [table_name, options]
439
+ end
440
+
441
+ def check_constraint(expression, **options)
442
+ check_constraints << [expression, options]
293
443
  end
294
444
 
295
445
  # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
296
- # <tt>:updated_at</tt> to the table. See SchemaStatements#add_timestamps
446
+ # <tt>:updated_at</tt> to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
297
447
  #
298
448
  # t.timestamps null: false
299
- def timestamps(*args)
300
- options = args.extract_options!
301
- emit_warning_if_null_unspecified(:timestamps, options)
302
- column(:created_at, :datetime, options)
303
- column(:updated_at, :datetime, options)
449
+ def timestamps(**options)
450
+ options[:null] = false if options[:null].nil?
451
+
452
+ if !options.key?(:precision) && @conn.supports_datetime_with_precision?
453
+ options[:precision] = 6
454
+ end
455
+
456
+ column(:created_at, :datetime, **options)
457
+ column(:updated_at, :datetime, **options)
304
458
  end
305
459
 
306
460
  # Adds a reference.
307
461
  #
308
462
  # t.references(:user)
309
463
  # t.belongs_to(:supplier, foreign_key: true)
464
+ # t.belongs_to(:supplier, foreign_key: true, type: :integer)
310
465
  #
311
- # See SchemaStatements#add_reference for details of the options you can use.
312
- def references(*args)
313
- options = args.extract_options!
314
- polymorphic = options.delete(:polymorphic)
315
- index_options = options.delete(:index)
316
- foreign_key_options = options.delete(:foreign_key)
317
- type = options.delete(:type) || :integer
318
-
319
- if polymorphic && foreign_key_options
320
- raise ArgumentError, "Cannot add a foreign key on a polymorphic relation"
321
- end
322
-
323
- args.each do |col|
324
- column("#{col}_id", type, options)
325
- column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
326
- index(polymorphic ? %w(type id).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
327
- if foreign_key_options
328
- to_table = Base.pluralize_table_names ? col.to_s.pluralize : col.to_s
329
- foreign_key(to_table, foreign_key_options.is_a?(Hash) ? foreign_key_options : {})
330
- end
466
+ # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
467
+ def references(*args, **options)
468
+ args.each do |ref_name|
469
+ ReferenceDefinition.new(ref_name, **options).add_to(self)
331
470
  end
332
471
  end
333
472
  alias :belongs_to :references
334
473
 
335
- def new_column_definition(name, type, options) # :nodoc:
336
- type = aliased_types(type.to_s, type)
337
- column = create_column_definition name, type
338
- limit = options.fetch(:limit) do
339
- native[type][:limit] if native[type].is_a?(Hash)
474
+ def new_column_definition(name, type, **options) # :nodoc:
475
+ if integer_like_primary_key?(type, options)
476
+ type = integer_like_primary_key_type(type, options)
340
477
  end
341
-
342
- column.limit = limit
343
- column.precision = options[:precision]
344
- column.scale = options[:scale]
345
- column.default = options[:default]
346
- column.null = options[:null]
347
- column.first = options[:first]
348
- column.after = options[:after]
349
- column.primary_key = type == :primary_key || options[:primary_key]
350
- column
478
+ type = aliased_types(type.to_s, type)
479
+ options[:primary_key] ||= type == :primary_key
480
+ options[:null] = false if options[:primary_key]
481
+ create_column_definition(name, type, options)
351
482
  end
352
483
 
353
484
  private
354
- def create_column_definition(name, type)
355
- ColumnDefinition.new name, type
356
- end
485
+ def create_column_definition(name, type, options)
486
+ ColumnDefinition.new(name, type, options)
487
+ end
357
488
 
358
- def native
359
- @native
360
- end
489
+ def aliased_types(name, fallback)
490
+ "timestamp" == name ? :datetime : fallback
491
+ end
361
492
 
362
- def aliased_types(name, fallback)
363
- 'timestamp' == name ? :datetime : fallback
364
- end
493
+ def integer_like_primary_key?(type, options)
494
+ options[:primary_key] && [:integer, :bigint].include?(type) && !options.key?(:default)
495
+ end
496
+
497
+ def integer_like_primary_key_type(type, options)
498
+ type
499
+ end
365
500
  end
366
501
 
367
502
  class AlterTable # :nodoc:
368
503
  attr_reader :adds
369
- attr_reader :foreign_key_adds
370
- attr_reader :foreign_key_drops
504
+ attr_reader :foreign_key_adds, :foreign_key_drops
505
+ attr_reader :check_constraint_adds, :check_constraint_drops
371
506
 
372
507
  def initialize(td)
373
508
  @td = td
374
509
  @adds = []
375
510
  @foreign_key_adds = []
376
511
  @foreign_key_drops = []
512
+ @check_constraint_adds = []
513
+ @check_constraint_drops = []
377
514
  end
378
515
 
379
516
  def name; @td.name; end
@@ -386,47 +523,67 @@ module ActiveRecord
386
523
  @foreign_key_drops << name
387
524
  end
388
525
 
389
- def add_column(name, type, options)
526
+ def add_check_constraint(expression, options)
527
+ @check_constraint_adds << CheckConstraintDefinition.new(name, expression, options)
528
+ end
529
+
530
+ def drop_check_constraint(constraint_name)
531
+ @check_constraint_drops << constraint_name
532
+ end
533
+
534
+ def add_column(name, type, **options)
390
535
  name = name.to_s
391
536
  type = type.to_sym
392
- @adds << @td.new_column_definition(name, type, options)
537
+ @adds << AddColumnDefinition.new(@td.new_column_definition(name, type, **options))
393
538
  end
394
539
  end
395
540
 
396
541
  # Represents an SQL table in an abstract way for updating a table.
397
- # Also see TableDefinition and SchemaStatements#create_table
542
+ # Also see TableDefinition and {connection.create_table}[rdoc-ref:SchemaStatements#create_table]
398
543
  #
399
544
  # Available transformations are:
400
545
  #
401
546
  # change_table :table do |t|
547
+ # t.primary_key
402
548
  # t.column
403
549
  # t.index
404
550
  # t.rename_index
405
551
  # t.timestamps
406
552
  # t.change
407
553
  # t.change_default
554
+ # t.change_null
408
555
  # t.rename
409
556
  # t.references
410
557
  # t.belongs_to
558
+ # t.check_constraint
411
559
  # t.string
412
560
  # t.text
413
561
  # t.integer
562
+ # t.bigint
414
563
  # t.float
415
564
  # t.decimal
565
+ # t.numeric
416
566
  # t.datetime
417
567
  # t.timestamp
418
568
  # t.time
419
569
  # t.date
420
570
  # t.binary
421
571
  # t.boolean
572
+ # t.foreign_key
573
+ # t.json
574
+ # t.virtual
422
575
  # t.remove
576
+ # t.remove_foreign_key
423
577
  # t.remove_references
424
578
  # t.remove_belongs_to
425
579
  # t.remove_index
580
+ # t.remove_check_constraint
426
581
  # t.remove_timestamps
427
582
  # end
428
583
  #
429
584
  class Table
585
+ include ColumnMethods
586
+
430
587
  attr_reader :name
431
588
 
432
589
  def initialize(table_name, base)
@@ -435,33 +592,46 @@ module ActiveRecord
435
592
  end
436
593
 
437
594
  # Adds a new column to the named table.
438
- # See TableDefinition#column for details of the options you can use.
439
595
  #
440
- # ====== Creating a simple column
441
596
  # t.column(:name, :string)
442
- def column(column_name, type, options = {})
443
- @base.add_column(name, column_name, type, options)
597
+ #
598
+ # See TableDefinition#column for details of the options you can use.
599
+ def column(column_name, type, index: nil, **options)
600
+ @base.add_column(name, column_name, type, **options)
601
+ if index
602
+ index_options = index.is_a?(Hash) ? index : {}
603
+ index(column_name, **index_options)
604
+ end
444
605
  end
445
606
 
446
- # Checks to see if a column exists. See SchemaStatements#column_exists?
447
- def column_exists?(column_name, type = nil, options = {})
448
- @base.column_exists?(name, column_name, type, options)
607
+ # Checks to see if a column exists.
608
+ #
609
+ # t.string(:name) unless t.column_exists?(:name, :string)
610
+ #
611
+ # See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
612
+ def column_exists?(column_name, type = nil, **options)
613
+ @base.column_exists?(name, column_name, type, **options)
449
614
  end
450
615
 
451
616
  # Adds a new index to the table. +column_name+ can be a single Symbol, or
452
- # an Array of Symbols. See SchemaStatements#add_index
617
+ # an Array of Symbols.
453
618
  #
454
- # ====== Creating a simple index
455
619
  # t.index(:name)
456
- # ====== Creating a unique index
457
620
  # t.index([:branch_id, :party_id], unique: true)
458
- # ====== Creating a named index
459
621
  # t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
460
- def index(column_name, options = {})
461
- @base.add_index(name, column_name, options)
622
+ #
623
+ # See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
624
+ def index(column_name, **options)
625
+ @base.add_index(name, column_name, **options)
462
626
  end
463
627
 
464
- # Checks to see if an index exists. See SchemaStatements#index_exists?
628
+ # Checks to see if an index exists.
629
+ #
630
+ # unless t.index_exists?(:branch_id)
631
+ # t.index(:branch_id)
632
+ # end
633
+ #
634
+ # See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?]
465
635
  def index_exists?(column_name, options = {})
466
636
  @base.index_exists?(name, column_name, options)
467
637
  end
@@ -469,66 +639,88 @@ module ActiveRecord
469
639
  # Renames the given index on the table.
470
640
  #
471
641
  # t.rename_index(:user_id, :account_id)
642
+ #
643
+ # See {connection.rename_index}[rdoc-ref:SchemaStatements#rename_index]
472
644
  def rename_index(index_name, new_index_name)
473
645
  @base.rename_index(name, index_name, new_index_name)
474
646
  end
475
647
 
476
- # Adds timestamps (+created_at+ and +updated_at+) columns to the table. See SchemaStatements#add_timestamps
648
+ # Adds timestamps (+created_at+ and +updated_at+) columns to the table.
649
+ #
650
+ # t.timestamps(null: false)
477
651
  #
478
- # t.timestamps null: false
479
- def timestamps(options = {})
480
- @base.add_timestamps(name, options)
652
+ # See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
653
+ def timestamps(**options)
654
+ @base.add_timestamps(name, **options)
481
655
  end
482
656
 
483
657
  # Changes the column's definition according to the new options.
484
- # See TableDefinition#column for details of the options you can use.
485
658
  #
486
659
  # t.change(:name, :string, limit: 80)
487
660
  # t.change(:description, :text)
488
- def change(column_name, type, options = {})
489
- @base.change_column(name, column_name, type, options)
661
+ #
662
+ # See TableDefinition#column for details of the options you can use.
663
+ def change(column_name, type, **options)
664
+ @base.change_column(name, column_name, type, **options)
490
665
  end
491
666
 
492
- # Sets a new default value for a column. See SchemaStatements#change_column_default
667
+ # Sets a new default value for a column.
493
668
  #
494
669
  # t.change_default(:qualification, 'new')
495
670
  # t.change_default(:authorized, 1)
496
- def change_default(column_name, default)
497
- @base.change_column_default(name, column_name, default)
671
+ # t.change_default(:status, from: nil, to: "draft")
672
+ #
673
+ # See {connection.change_column_default}[rdoc-ref:SchemaStatements#change_column_default]
674
+ def change_default(column_name, default_or_changes)
675
+ @base.change_column_default(name, column_name, default_or_changes)
676
+ end
677
+
678
+ # Sets or removes a NOT NULL constraint on a column.
679
+ #
680
+ # t.change_null(:qualification, true)
681
+ # t.change_null(:qualification, false, 0)
682
+ #
683
+ # See {connection.change_column_null}[rdoc-ref:SchemaStatements#change_column_null]
684
+ def change_null(column_name, null, default = nil)
685
+ @base.change_column_null(name, column_name, null, default)
498
686
  end
499
687
 
500
688
  # Removes the column(s) from the table definition.
501
689
  #
502
690
  # t.remove(:qualification)
503
691
  # t.remove(:qualification, :experience)
504
- def remove(*column_names)
505
- @base.remove_columns(name, *column_names)
692
+ #
693
+ # See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
694
+ def remove(*column_names, **options)
695
+ @base.remove_columns(name, *column_names, **options)
506
696
  end
507
697
 
508
698
  # Removes the given index from the table.
509
699
  #
510
- # ====== Remove the index_table_name_on_column in the table_name table
511
- # t.remove_index :column
512
- # ====== Remove the index named index_table_name_on_branch_id in the table_name table
513
- # t.remove_index column: :branch_id
514
- # ====== Remove the index named index_table_name_on_branch_id_and_party_id in the table_name table
515
- # t.remove_index column: [:branch_id, :party_id]
516
- # ====== Remove the index named by_branch_party in the table_name table
517
- # t.remove_index name: :by_branch_party
518
- def remove_index(options = {})
519
- @base.remove_index(name, options)
700
+ # t.remove_index(:branch_id)
701
+ # t.remove_index(column: [:branch_id, :party_id])
702
+ # t.remove_index(name: :by_branch_party)
703
+ # t.remove_index(:branch_id, name: :by_branch_party)
704
+ #
705
+ # See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
706
+ def remove_index(column_name = nil, **options)
707
+ @base.remove_index(name, column_name, **options)
520
708
  end
521
709
 
522
710
  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
523
711
  #
524
712
  # t.remove_timestamps
525
- def remove_timestamps(options = {})
526
- @base.remove_timestamps(name, options)
713
+ #
714
+ # See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
715
+ def remove_timestamps(**options)
716
+ @base.remove_timestamps(name, **options)
527
717
  end
528
718
 
529
719
  # Renames a column.
530
720
  #
531
721
  # t.rename(:description, :name)
722
+ #
723
+ # See {connection.rename_column}[rdoc-ref:SchemaStatements#rename_column]
532
724
  def rename(column_name, new_column_name)
533
725
  @base.rename_column(name, column_name, new_column_name)
534
726
  end
@@ -538,47 +730,73 @@ module ActiveRecord
538
730
  # t.references(:user)
539
731
  # t.belongs_to(:supplier, foreign_key: true)
540
732
  #
541
- # See SchemaStatements#add_reference for details of the options you can use.
542
- def references(*args)
543
- options = args.extract_options!
733
+ # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
734
+ def references(*args, **options)
544
735
  args.each do |ref_name|
545
- @base.add_reference(name, ref_name, options)
736
+ @base.add_reference(name, ref_name, **options)
546
737
  end
547
738
  end
548
739
  alias :belongs_to :references
549
740
 
550
741
  # Removes a reference. Optionally removes a +type+ column.
551
- # <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
552
742
  #
553
743
  # t.remove_references(:user)
554
744
  # t.remove_belongs_to(:supplier, polymorphic: true)
555
745
  #
556
- # See SchemaStatements#remove_reference
557
- def remove_references(*args)
558
- options = args.extract_options!
746
+ # See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
747
+ def remove_references(*args, **options)
559
748
  args.each do |ref_name|
560
- @base.remove_reference(name, ref_name, options)
749
+ @base.remove_reference(name, ref_name, **options)
561
750
  end
562
751
  end
563
752
  alias :remove_belongs_to :remove_references
564
753
 
565
- # Adds a column or columns of a specified type
754
+ # Adds a foreign key to the table using a supplied table name.
566
755
  #
567
- # t.string(:goat)
568
- # t.string(:goat, :sheep)
569
- [:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
570
- define_method column_type do |*args|
571
- options = args.extract_options!
572
- args.each do |column_name|
573
- @base.add_column(name, column_name, column_type, options)
574
- end
575
- end
756
+ # t.foreign_key(:authors)
757
+ # t.foreign_key(:authors, column: :author_id, primary_key: "id")
758
+ #
759
+ # See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
760
+ def foreign_key(*args, **options)
761
+ @base.add_foreign_key(name, *args, **options)
576
762
  end
577
763
 
578
- private
579
- def native
580
- @base.native_database_types
581
- end
764
+ # Removes the given foreign key from the table.
765
+ #
766
+ # t.remove_foreign_key(:authors)
767
+ # t.remove_foreign_key(column: :author_id)
768
+ #
769
+ # See {connection.remove_foreign_key}[rdoc-ref:SchemaStatements#remove_foreign_key]
770
+ def remove_foreign_key(*args, **options)
771
+ @base.remove_foreign_key(name, *args, **options)
772
+ end
773
+
774
+ # Checks to see if a foreign key exists.
775
+ #
776
+ # t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
777
+ #
778
+ # See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
779
+ def foreign_key_exists?(*args, **options)
780
+ @base.foreign_key_exists?(name, *args, **options)
781
+ end
782
+
783
+ # Adds a check constraint.
784
+ #
785
+ # t.check_constraint("price > 0", name: "price_check")
786
+ #
787
+ # See {connection.add_check_constraint}[rdoc-ref:SchemaStatements#add_check_constraint]
788
+ def check_constraint(*args)
789
+ @base.add_check_constraint(name, *args)
790
+ end
791
+
792
+ # Removes the given check constraint from the table.
793
+ #
794
+ # t.remove_check_constraint(name: "price_check")
795
+ #
796
+ # See {connection.remove_check_constraint}[rdoc-ref:SchemaStatements#remove_check_constraint]
797
+ def remove_check_constraint(*args)
798
+ @base.remove_check_constraint(name, *args)
799
+ end
582
800
  end
583
801
  end
584
802
  end