activerecord 4.2.0 → 6.0.5.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 (373) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +852 -801
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +14 -13
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/advisory_lock_base.rb +18 -0
  8. data/lib/active_record/aggregations.rb +267 -249
  9. data/lib/active_record/association_relation.rb +26 -6
  10. data/lib/active_record/associations/alias_tracker.rb +29 -36
  11. data/lib/active_record/associations/association.rb +137 -55
  12. data/lib/active_record/associations/association_scope.rb +110 -132
  13. data/lib/active_record/associations/belongs_to_association.rb +67 -54
  14. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  15. data/lib/active_record/associations/builder/association.rb +27 -40
  16. data/lib/active_record/associations/builder/belongs_to.rb +69 -55
  17. data/lib/active_record/associations/builder/collection_association.rb +10 -29
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +58 -70
  19. data/lib/active_record/associations/builder/has_many.rb +8 -4
  20. data/lib/active_record/associations/builder/has_one.rb +46 -5
  21. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  22. data/lib/active_record/associations/collection_association.rb +150 -275
  23. data/lib/active_record/associations/collection_proxy.rb +253 -152
  24. data/lib/active_record/associations/foreign_association.rb +20 -0
  25. data/lib/active_record/associations/has_many_association.rb +35 -84
  26. data/lib/active_record/associations/has_many_through_association.rb +62 -80
  27. data/lib/active_record/associations/has_one_association.rb +62 -49
  28. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  29. data/lib/active_record/associations/join_dependency/join_association.rb +43 -78
  30. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  31. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  32. data/lib/active_record/associations/join_dependency.rb +159 -162
  33. data/lib/active_record/associations/preloader/association.rb +102 -113
  34. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  35. data/lib/active_record/associations/preloader.rb +96 -95
  36. data/lib/active_record/associations/singular_association.rb +18 -45
  37. data/lib/active_record/associations/through_association.rb +49 -24
  38. data/lib/active_record/associations.rb +1737 -1596
  39. data/lib/active_record/attribute_assignment.rb +57 -185
  40. data/lib/active_record/attribute_decorators.rb +39 -17
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +14 -5
  42. data/lib/active_record/attribute_methods/dirty.rb +174 -134
  43. data/lib/active_record/attribute_methods/primary_key.rb +90 -84
  44. data/lib/active_record/attribute_methods/query.rb +6 -5
  45. data/lib/active_record/attribute_methods/read.rb +20 -77
  46. data/lib/active_record/attribute_methods/serialization.rb +40 -21
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -37
  48. data/lib/active_record/attribute_methods/write.rb +33 -56
  49. data/lib/active_record/attribute_methods.rb +124 -143
  50. data/lib/active_record/attributes.rb +213 -74
  51. data/lib/active_record/autosave_association.rb +125 -54
  52. data/lib/active_record/base.rb +60 -49
  53. data/lib/active_record/callbacks.rb +101 -76
  54. data/lib/active_record/coders/json.rb +3 -1
  55. data/lib/active_record/coders/yaml_column.rb +36 -13
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +810 -291
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +253 -108
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +83 -24
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +171 -53
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -47
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +383 -239
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +736 -235
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +190 -87
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +487 -192
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +536 -600
  69. data/lib/active_record/connection_adapters/column.rb +56 -43
  70. data/lib/active_record/connection_adapters/connection_specification.rb +174 -153
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +71 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +59 -196
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +71 -115
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  99. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +9 -5
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +465 -291
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +565 -363
  117. data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +299 -364
  127. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  128. data/lib/active_record/connection_handling.rb +167 -41
  129. data/lib/active_record/core.rb +277 -233
  130. data/lib/active_record/counter_cache.rb +71 -50
  131. data/lib/active_record/database_configurations/database_config.rb +37 -0
  132. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  133. data/lib/active_record/database_configurations/url_config.rb +78 -0
  134. data/lib/active_record/database_configurations.rb +233 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +87 -106
  137. data/lib/active_record/enum.rb +172 -89
  138. data/lib/active_record/errors.rb +189 -53
  139. data/lib/active_record/explain.rb +22 -11
  140. data/lib/active_record/explain_registry.rb +4 -2
  141. data/lib/active_record/explain_subscriber.rb +11 -6
  142. data/lib/active_record/fixture_set/file.rb +35 -9
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +152 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  147. data/lib/active_record/fixtures.rb +225 -497
  148. data/lib/active_record/gem_version.rb +6 -4
  149. data/lib/active_record/inheritance.rb +158 -115
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +123 -29
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  154. data/lib/active_record/locale/en.yml +3 -2
  155. data/lib/active_record/locking/optimistic.rb +99 -98
  156. data/lib/active_record/locking/pessimistic.rb +18 -6
  157. data/lib/active_record/log_subscriber.rb +76 -33
  158. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  160. data/lib/active_record/middleware/database_selector.rb +74 -0
  161. data/lib/active_record/migration/command_recorder.rb +166 -91
  162. data/lib/active_record/migration/compatibility.rb +244 -0
  163. data/lib/active_record/migration/join_table.rb +8 -7
  164. data/lib/active_record/migration.rb +636 -290
  165. data/lib/active_record/model_schema.rb +344 -112
  166. data/lib/active_record/nested_attributes.rb +265 -215
  167. data/lib/active_record/no_touching.rb +15 -2
  168. data/lib/active_record/null_relation.rb +24 -38
  169. data/lib/active_record/persistence.rb +559 -125
  170. data/lib/active_record/query_cache.rb +19 -23
  171. data/lib/active_record/querying.rb +44 -30
  172. data/lib/active_record/railtie.rb +166 -47
  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 +341 -202
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +461 -302
  179. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  180. data/lib/active_record/relation/batches.rb +206 -55
  181. data/lib/active_record/relation/calculations.rb +270 -249
  182. data/lib/active_record/relation/delegation.rb +76 -84
  183. data/lib/active_record/relation/finder_methods.rb +287 -255
  184. data/lib/active_record/relation/from_clause.rb +30 -0
  185. data/lib/active_record/relation/merger.rb +86 -68
  186. data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -25
  187. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  188. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  189. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  190. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  191. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  192. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  193. data/lib/active_record/relation/predicate_builder.rb +112 -92
  194. data/lib/active_record/relation/query_attribute.rb +50 -0
  195. data/lib/active_record/relation/query_methods.rb +612 -392
  196. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  197. data/lib/active_record/relation/spawn_methods.rb +18 -17
  198. data/lib/active_record/relation/where_clause.rb +189 -0
  199. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  200. data/lib/active_record/relation.rb +533 -340
  201. data/lib/active_record/result.rb +79 -43
  202. data/lib/active_record/runtime_registry.rb +6 -4
  203. data/lib/active_record/sanitization.rb +144 -121
  204. data/lib/active_record/schema.rb +21 -24
  205. data/lib/active_record/schema_dumper.rb +112 -93
  206. data/lib/active_record/schema_migration.rb +24 -20
  207. data/lib/active_record/scoping/default.rb +98 -82
  208. data/lib/active_record/scoping/named.rb +91 -33
  209. data/lib/active_record/scoping.rb +45 -27
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +5 -5
  212. data/lib/active_record/statement_cache.rb +73 -36
  213. data/lib/active_record/store.rb +127 -42
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +90 -0
  216. data/lib/active_record/tasks/database_tasks.rb +309 -99
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +58 -89
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -31
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +37 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +243 -0
  222. data/lib/active_record/timestamp.rb +86 -41
  223. data/lib/active_record/touch_later.rb +65 -0
  224. data/lib/active_record/transactions.rb +222 -146
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  227. data/lib/active_record/type/date.rb +4 -41
  228. data/lib/active_record/type/date_time.rb +4 -38
  229. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  230. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  231. data/lib/active_record/type/internal/timezone.rb +17 -0
  232. data/lib/active_record/type/json.rb +30 -0
  233. data/lib/active_record/type/serialized.rb +29 -15
  234. data/lib/active_record/type/text.rb +2 -2
  235. data/lib/active_record/type/time.rb +21 -16
  236. data/lib/active_record/type/type_map.rb +16 -19
  237. data/lib/active_record/type/unsigned_integer.rb +9 -8
  238. data/lib/active_record/type.rb +77 -23
  239. data/lib/active_record/type_caster/connection.rb +34 -0
  240. data/lib/active_record/type_caster/map.rb +20 -0
  241. data/lib/active_record/type_caster.rb +9 -0
  242. data/lib/active_record/validations/absence.rb +25 -0
  243. data/lib/active_record/validations/associated.rb +12 -4
  244. data/lib/active_record/validations/length.rb +26 -0
  245. data/lib/active_record/validations/presence.rb +14 -13
  246. data/lib/active_record/validations/uniqueness.rb +43 -46
  247. data/lib/active_record/validations.rb +38 -35
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/active_record.rb +44 -21
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes/attribute.rb +37 -0
  252. data/lib/arel/attributes.rb +22 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes/and.rb +32 -0
  266. data/lib/arel/nodes/ascending.rb +23 -0
  267. data/lib/arel/nodes/binary.rb +52 -0
  268. data/lib/arel/nodes/bind_param.rb +36 -0
  269. data/lib/arel/nodes/case.rb +55 -0
  270. data/lib/arel/nodes/casted.rb +50 -0
  271. data/lib/arel/nodes/comment.rb +29 -0
  272. data/lib/arel/nodes/count.rb +12 -0
  273. data/lib/arel/nodes/delete_statement.rb +45 -0
  274. data/lib/arel/nodes/descending.rb +23 -0
  275. data/lib/arel/nodes/equality.rb +18 -0
  276. data/lib/arel/nodes/extract.rb +24 -0
  277. data/lib/arel/nodes/false.rb +16 -0
  278. data/lib/arel/nodes/full_outer_join.rb +8 -0
  279. data/lib/arel/nodes/function.rb +44 -0
  280. data/lib/arel/nodes/grouping.rb +8 -0
  281. data/lib/arel/nodes/in.rb +8 -0
  282. data/lib/arel/nodes/infix_operation.rb +80 -0
  283. data/lib/arel/nodes/inner_join.rb +8 -0
  284. data/lib/arel/nodes/insert_statement.rb +37 -0
  285. data/lib/arel/nodes/join_source.rb +20 -0
  286. data/lib/arel/nodes/matches.rb +18 -0
  287. data/lib/arel/nodes/named_function.rb +23 -0
  288. data/lib/arel/nodes/node.rb +50 -0
  289. data/lib/arel/nodes/node_expression.rb +13 -0
  290. data/lib/arel/nodes/outer_join.rb +8 -0
  291. data/lib/arel/nodes/over.rb +15 -0
  292. data/lib/arel/nodes/regexp.rb +16 -0
  293. data/lib/arel/nodes/right_outer_join.rb +8 -0
  294. data/lib/arel/nodes/select_core.rb +67 -0
  295. data/lib/arel/nodes/select_statement.rb +41 -0
  296. data/lib/arel/nodes/sql_literal.rb +16 -0
  297. data/lib/arel/nodes/string_join.rb +11 -0
  298. data/lib/arel/nodes/table_alias.rb +27 -0
  299. data/lib/arel/nodes/terminal.rb +16 -0
  300. data/lib/arel/nodes/true.rb +16 -0
  301. data/lib/arel/nodes/unary.rb +45 -0
  302. data/lib/arel/nodes/unary_operation.rb +20 -0
  303. data/lib/arel/nodes/unqualified_column.rb +22 -0
  304. data/lib/arel/nodes/update_statement.rb +41 -0
  305. data/lib/arel/nodes/values_list.rb +9 -0
  306. data/lib/arel/nodes/window.rb +126 -0
  307. data/lib/arel/nodes/with.rb +11 -0
  308. data/lib/arel/nodes.rb +68 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +256 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors/depth_first.rb +203 -0
  316. data/lib/arel/visitors/dot.rb +296 -0
  317. data/lib/arel/visitors/ibm_db.rb +34 -0
  318. data/lib/arel/visitors/informix.rb +62 -0
  319. data/lib/arel/visitors/mssql.rb +156 -0
  320. data/lib/arel/visitors/mysql.rb +83 -0
  321. data/lib/arel/visitors/oracle.rb +158 -0
  322. data/lib/arel/visitors/oracle12.rb +65 -0
  323. data/lib/arel/visitors/postgresql.rb +109 -0
  324. data/lib/arel/visitors/sqlite.rb +38 -0
  325. data/lib/arel/visitors/to_sql.rb +888 -0
  326. data/lib/arel/visitors/visitor.rb +45 -0
  327. data/lib/arel/visitors/where_sql.rb +22 -0
  328. data/lib/arel/visitors.rb +20 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/arel.rb +62 -0
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
  334. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  335. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -8
  336. data/lib/rails/generators/active_record/migration.rb +30 -1
  337. data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record.rb +7 -5
  340. metadata +174 -63
  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 -149
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  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/integer.rb +0 -11
  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 -30
  362. data/lib/active_record/type/decimal.rb +0 -40
  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 -55
  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 -36
  369. data/lib/active_record/type/time_value.rb +0 -38
  370. data/lib/active_record/type/value.rb +0 -101
  371. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  372. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  373. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,31 +1,81 @@
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
+ private
37
+ def concise_options(options)
38
+ if columns.size == options.size && options.values.uniq.size == 1
39
+ options.values.first
40
+ else
41
+ options
42
+ end
43
+ end
12
44
  end
13
45
 
14
46
  # Abstract representation of a column definition. Instances of this type
15
47
  # are typically created by methods in TableDefinition, and added to the
16
48
  # +columns+ attribute of said TableDefinition object, in order to be used
17
49
  # 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
-
50
+ ColumnDefinition = Struct.new(:name, :type, :options, :sql_type) do # :nodoc:
20
51
  def primary_key?
21
- primary_key || type.to_sym == :primary_key
52
+ options[:primary_key]
22
53
  end
23
- end
24
54
 
25
- class ChangeColumnDefinition < Struct.new(:column, :type, :options) #:nodoc:
55
+ [:limit, :precision, :scale, :default, :null, :collation, :comment].each do |option_name|
56
+ module_eval <<-CODE, __FILE__, __LINE__ + 1
57
+ def #{option_name}
58
+ options[:#{option_name}]
59
+ end
60
+
61
+ def #{option_name}=(value)
62
+ options[:#{option_name}] = value
63
+ end
64
+ CODE
65
+ end
66
+
67
+ def aliased_types(name, fallback)
68
+ "timestamp" == name ? :datetime : fallback
69
+ end
26
70
  end
27
71
 
28
- class ForeignKeyDefinition < Struct.new(:from_table, :to_table, :options) #:nodoc:
72
+ AddColumnDefinition = Struct.new(:column) # :nodoc:
73
+
74
+ ChangeColumnDefinition = Struct.new(:column, :name) #:nodoc:
75
+
76
+ PrimaryKeyDefinition = Struct.new(:name) # :nodoc:
77
+
78
+ ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do #:nodoc:
29
79
  def name
30
80
  options[:name]
31
81
  end
@@ -50,31 +100,153 @@ module ActiveRecord
50
100
  options[:primary_key] != default_primary_key
51
101
  end
52
102
 
103
+ def validate?
104
+ options.fetch(:validate, true)
105
+ end
106
+ alias validated? validate?
107
+
108
+ def export_name_on_schema_dump?
109
+ !ActiveRecord::SchemaDumper.fk_ignore_pattern.match?(name) if name
110
+ end
111
+
112
+ def defined_for?(to_table: nil, validate: nil, **options)
113
+ (to_table.nil? || to_table.to_s == self.to_table) &&
114
+ (validate.nil? || validate == options.fetch(:validate, validate)) &&
115
+ options.all? { |k, v| self.options[k].to_s == v.to_s }
116
+ end
117
+
53
118
  private
54
- def default_primary_key
55
- "id"
119
+ def default_primary_key
120
+ "id"
121
+ end
122
+ end
123
+
124
+ class ReferenceDefinition # :nodoc:
125
+ def initialize(
126
+ name,
127
+ polymorphic: false,
128
+ index: true,
129
+ foreign_key: false,
130
+ type: :bigint,
131
+ **options
132
+ )
133
+ @name = name
134
+ @polymorphic = polymorphic
135
+ @index = index
136
+ @foreign_key = foreign_key
137
+ @type = type
138
+ @options = options
139
+
140
+ if polymorphic && foreign_key
141
+ raise ArgumentError, "Cannot add a foreign key to a polymorphic relation"
142
+ end
143
+ end
144
+
145
+ def add_to(table)
146
+ columns.each do |column_options|
147
+ kwargs = column_options.extract_options!
148
+ table.column(*column_options, **kwargs)
149
+ end
150
+
151
+ if index
152
+ table.index(column_names, index_options)
153
+ end
154
+
155
+ if foreign_key
156
+ table.foreign_key(foreign_table_name, **foreign_key_options)
157
+ end
56
158
  end
159
+
160
+ private
161
+ attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
162
+
163
+ def as_options(value)
164
+ value.is_a?(Hash) ? value : {}
165
+ end
166
+
167
+ def polymorphic_options
168
+ as_options(polymorphic).merge(options.slice(:null, :first, :after))
169
+ end
170
+
171
+ def index_options
172
+ as_options(index)
173
+ end
174
+
175
+ def foreign_key_options
176
+ as_options(foreign_key).merge(column: column_name)
177
+ end
178
+
179
+ def columns
180
+ result = [[column_name, type, options]]
181
+ if polymorphic
182
+ result.unshift(["#{name}_type", :string, polymorphic_options])
183
+ end
184
+ result
185
+ end
186
+
187
+ def column_name
188
+ "#{name}_id"
189
+ end
190
+
191
+ def column_names
192
+ columns.map(&:first)
193
+ end
194
+
195
+ def foreign_table_name
196
+ foreign_key_options.fetch(:to_table) do
197
+ Base.pluralize_table_names ? name.to_s.pluralize : name
198
+ end
199
+ end
57
200
  end
58
201
 
59
- module TimestampDefaultDeprecation # :nodoc:
60
- def emit_warning_if_null_unspecified(options)
61
- return if options.key?(:null)
202
+ module ColumnMethods
203
+ extend ActiveSupport::Concern
204
+
205
+ # Appends a primary key definition to the table definition.
206
+ # Can be called multiple times, but this is probably not a good idea.
207
+ def primary_key(name, type = :primary_key, **options)
208
+ column(name, type, **options.merge(primary_key: true))
209
+ end
210
+
211
+ ##
212
+ # :method: column
213
+ # :call-seq: column(name, type, **options)
214
+ #
215
+ # Appends a column or columns of a specified type.
216
+ #
217
+ # t.string(:goat)
218
+ # t.string(:goat, :sheep)
219
+ #
220
+ # See TableDefinition#column
221
+
222
+ included do
223
+ define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
224
+ :float, :integer, :json, :string, :text, :time, :timestamp, :virtual
62
225
 
63
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
64
- `#timestamp` 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
226
+ alias :numeric :decimal
227
+ end
228
+
229
+ class_methods do
230
+ private def define_column_methods(*column_types) # :nodoc:
231
+ column_types.each do |column_type|
232
+ module_eval <<-RUBY, __FILE__, __LINE__ + 1
233
+ def #{column_type}(*names, **options)
234
+ raise ArgumentError, "Missing column name(s) for #{column_type}" if names.empty?
235
+ names.each { |name| column(name, :#{column_type}, **options) }
236
+ end
237
+ RUBY
238
+ end
239
+ end
68
240
  end
69
241
  end
70
242
 
71
243
  # Represents the schema of an SQL table in an abstract way. This class
72
244
  # provides methods for manipulating the schema representation.
73
245
  #
74
- # Inside migration files, the +t+ object in +create_table+
246
+ # Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
75
247
  # is actually of this type:
76
248
  #
77
- # class SomeMigration < ActiveRecord::Migration
249
+ # class SomeMigration < ActiveRecord::Migration[5.0]
78
250
  # def up
79
251
  # create_table :foo do |t|
80
252
  # puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
@@ -86,124 +258,65 @@ module ActiveRecord
86
258
  # end
87
259
  # end
88
260
  #
89
- # The table definitions
90
- # The Columns are stored as a ColumnDefinition in the +columns+ attribute.
91
261
  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
98
-
99
- def initialize(types, name, temporary, options, as = nil)
262
+ include ColumnMethods
263
+
264
+ attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys
265
+
266
+ def initialize(
267
+ conn,
268
+ name,
269
+ temporary: false,
270
+ if_not_exists: false,
271
+ options: nil,
272
+ as: nil,
273
+ comment: nil,
274
+ **
275
+ )
276
+ @conn = conn
100
277
  @columns_hash = {}
101
- @indexes = {}
102
- @native = types
278
+ @indexes = []
279
+ @foreign_keys = []
280
+ @primary_keys = nil
103
281
  @temporary = temporary
282
+ @if_not_exists = if_not_exists
104
283
  @options = options
105
284
  @as = as
106
285
  @name = name
286
+ @comment = comment
107
287
  end
108
288
 
109
- def columns; @columns_hash.values; end
110
-
111
- # Appends a primary key definition to the table definition.
112
- # Can be called multiple times, but this is probably not a good idea.
113
- def primary_key(name, type = :primary_key, options = {})
114
- column(name, type, options.merge(:primary_key => true))
289
+ def primary_keys(name = nil) # :nodoc:
290
+ @primary_keys = PrimaryKeyDefinition.new(name) if name
291
+ @primary_keys
115
292
  end
116
293
 
294
+ # Returns an array of ColumnDefinition objects for the columns of the table.
295
+ def columns; @columns_hash.values; end
296
+
117
297
  # Returns a ColumnDefinition for the column with name +name+.
118
298
  def [](name)
119
299
  @columns_hash[name.to_s]
120
300
  end
121
301
 
122
302
  # Instantiates a new column for the table.
123
- # The +type+ parameter is normally one of the migrations native types,
124
- # which is one of the following:
125
- # <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
126
- # <tt>:integer</tt>, <tt>:float</tt>, <tt>:decimal</tt>,
127
- # <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
128
- # <tt>:binary</tt>, <tt>:boolean</tt>.
129
- #
130
- # You may use a type not in this list as long as it is supported by your
131
- # database (for example, "polygon" in MySQL), but this will not be database
132
- # agnostic and should usually be avoided.
133
- #
134
- # Available options are (none of these exists by default):
135
- # * <tt>:limit</tt> -
136
- # Requests a maximum column length. This is number of characters for <tt>:string</tt> and
137
- # <tt>:text</tt> columns and number of bytes for <tt>:binary</tt> and <tt>:integer</tt> columns.
138
- # * <tt>:default</tt> -
139
- # The column's default value. Use nil for NULL.
140
- # * <tt>:null</tt> -
141
- # Allows or disallows +NULL+ values in the column. This option could
142
- # have been named <tt>:null_allowed</tt>.
143
- # * <tt>:precision</tt> -
144
- # Specifies the precision for a <tt>:decimal</tt> column.
145
- # * <tt>:scale</tt> -
146
- # Specifies the scale for a <tt>:decimal</tt> column.
303
+ # See {connection.add_column}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_column]
304
+ # for available options.
305
+ #
306
+ # Additional options are:
147
307
  # * <tt>:index</tt> -
148
308
  # Create an index for the column. Can be either <tt>true</tt> or an options hash.
149
309
  #
150
- # Note: The precision is the total number of significant digits
151
- # and the scale is the number of digits that can be stored following
152
- # the decimal point. For example, the number 123.45 has a precision of 5
153
- # and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
154
- # range from -999.99 to 999.99.
155
- #
156
- # Please be aware of different RDBMS implementations behavior with
157
- # <tt>:decimal</tt> columns:
158
- # * The SQL standard says the default scale should be 0, <tt>:scale</tt> <=
159
- # <tt>:precision</tt>, and makes no comments about the requirements of
160
- # <tt>:precision</tt>.
161
- # * MySQL: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..30].
162
- # Default is (10,0).
163
- # * PostgreSQL: <tt>:precision</tt> [1..infinity],
164
- # <tt>:scale</tt> [0..infinity]. No default.
165
- # * SQLite2: Any <tt>:precision</tt> and <tt>:scale</tt> may be used.
166
- # Internal storage as strings. No default.
167
- # * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
168
- # but the maximum supported <tt>:precision</tt> is 16. No default.
169
- # * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
170
- # Default is (38,0).
171
- # * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
172
- # Default unknown.
173
- # * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
174
- # Default (38,0).
175
- #
176
310
  # This method returns <tt>self</tt>.
177
311
  #
178
312
  # == Examples
179
- # # Assuming +td+ is an instance of TableDefinition
180
- # td.column(:granted, :boolean)
181
- # # granted BOOLEAN
182
313
  #
183
- # td.column(:picture, :binary, limit: 2.megabytes)
184
- # # => picture BLOB(2097152)
185
- #
186
- # td.column(:sales_stage, :string, limit: 20, default: 'new', null: false)
187
- # # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
188
- #
189
- # td.column(:bill_gates_money, :decimal, precision: 15, scale: 2)
190
- # # => bill_gates_money DECIMAL(15,2)
191
- #
192
- # td.column(:sensor_reading, :decimal, precision: 30, scale: 20)
193
- # # => sensor_reading DECIMAL(30,20)
194
- #
195
- # # While <tt>:scale</tt> defaults to zero on most databases, it
196
- # # probably wouldn't hurt to include it.
197
- # td.column(:huge_integer, :decimal, precision: 30)
198
- # # => huge_integer DECIMAL(30)
199
- #
200
- # # Defines a column with a database-specific type.
201
- # td.column(:foo, 'polygon')
202
- # # => foo polygon
314
+ # # Assuming +td+ is an instance of TableDefinition
315
+ # td.column(:granted, :boolean, index: true)
203
316
  #
204
317
  # == Short-hand examples
205
318
  #
206
- # Instead of calling +column+ directly, you can also work with the short-hand definitions for the default types.
319
+ # Instead of calling #column directly, you can also work with the short-hand definitions for the default types.
207
320
  # They use the type as the method name instead of as a parameter and allow for multiple columns to be defined
208
321
  # in a single statement.
209
322
  #
@@ -235,7 +348,8 @@ module ActiveRecord
235
348
  # TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
236
349
  # column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of
237
350
  # options, these will be used when creating the <tt>_type</tt> column. The <tt>:index</tt> option
238
- # will also create an index, similar to calling <tt>add_index</tt>. So what can be written like this:
351
+ # will also create an index, similar to calling {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index].
352
+ # So what can be written like this:
239
353
  #
240
354
  # create_table :taggings do |t|
241
355
  # t.integer :tag_id, :tagger_id, :taggable_id
@@ -249,106 +363,100 @@ module ActiveRecord
249
363
  #
250
364
  # create_table :taggings do |t|
251
365
  # t.references :tag, index: { name: 'index_taggings_on_tag_id' }
252
- # t.references :tagger, polymorphic: true, index: true
253
- # t.references :taggable, polymorphic: { default: 'Photo' }
366
+ # t.references :tagger, polymorphic: true
367
+ # t.references :taggable, polymorphic: { default: 'Photo' }, index: false
254
368
  # end
255
- def column(name, type, options = {})
369
+ def column(name, type, **options)
256
370
  name = name.to_s
257
- type = type.to_sym
371
+ type = type.to_sym if type
258
372
 
259
- if @columns_hash[name] && @columns_hash[name].primary_key?
260
- raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
373
+ if @columns_hash[name]
374
+ if @columns_hash[name].primary_key?
375
+ raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
376
+ else
377
+ raise ArgumentError, "you can't define an already defined column '#{name}'."
378
+ end
261
379
  end
262
380
 
263
381
  index_options = options.delete(:index)
264
382
  index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
265
- @columns_hash[name] = new_column_definition(name, type, options)
383
+ @columns_hash[name] = new_column_definition(name, type, **options)
266
384
  self
267
385
  end
268
386
 
387
+ # remove the column +name+ from the table.
388
+ # remove_column(:account_id)
269
389
  def remove_column(name)
270
390
  @columns_hash.delete name.to_s
271
391
  end
272
392
 
273
- [:string, :text, :integer, :bigint, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
274
- define_method column_type do |*args|
275
- options = args.extract_options!
276
- column_names = args
277
- column_names.each { |name| column(name, column_type, options) }
278
- end
279
- end
280
-
281
393
  # Adds index options to the indexes hash, keyed by column name
282
394
  # This is primarily used to track indexes that need to be created after the table
283
395
  #
284
396
  # index(:account_id, name: 'index_projects_on_account_id')
285
397
  def index(column_name, options = {})
286
- indexes[column_name] = options
398
+ indexes << [column_name, options]
399
+ end
400
+
401
+ def foreign_key(table_name, **options) # :nodoc:
402
+ foreign_keys << [table_name, options]
287
403
  end
288
404
 
289
405
  # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
290
- # <tt>:updated_at</tt> to the table. See SchemaStatements#add_timestamps
406
+ # <tt>:updated_at</tt> to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
291
407
  #
292
408
  # t.timestamps null: false
293
- def timestamps(*args)
294
- options = args.extract_options!
295
- emit_warning_if_null_unspecified(options)
296
- column(:created_at, :datetime, options)
297
- column(:updated_at, :datetime, options)
409
+ def timestamps(**options)
410
+ options[:null] = false if options[:null].nil?
411
+
412
+ if !options.key?(:precision) && @conn.supports_datetime_with_precision?
413
+ options[:precision] = 6
414
+ end
415
+
416
+ column(:created_at, :datetime, **options)
417
+ column(:updated_at, :datetime, **options)
298
418
  end
299
419
 
300
- # Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided.
301
- # <tt>references</tt> and <tt>belongs_to</tt> are acceptable. The reference column will be an +integer+
302
- # by default, the <tt>:type</tt> option can be used to specify a different type.
420
+ # Adds a reference.
303
421
  #
304
422
  # t.references(:user)
305
- # t.references(:user, type: "string")
306
- # t.belongs_to(:supplier, polymorphic: true)
423
+ # t.belongs_to(:supplier, foreign_key: true)
424
+ # t.belongs_to(:supplier, foreign_key: true, type: :integer)
307
425
  #
308
- # See SchemaStatements#add_reference
309
- def references(*args)
310
- options = args.extract_options!
311
- polymorphic = options.delete(:polymorphic)
312
- index_options = options.delete(:index)
313
- type = options.delete(:type) || :integer
314
- args.each do |col|
315
- column("#{col}_id", type, options)
316
- column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
317
- index(polymorphic ? %w(type id).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
426
+ # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
427
+ def references(*args, **options)
428
+ args.each do |ref_name|
429
+ ReferenceDefinition.new(ref_name, **options).add_to(self)
318
430
  end
319
431
  end
320
432
  alias :belongs_to :references
321
433
 
322
- def new_column_definition(name, type, options) # :nodoc:
323
- type = aliased_types(type.to_s, type)
324
- column = create_column_definition name, type
325
- limit = options.fetch(:limit) do
326
- native[type][:limit] if native[type].is_a?(Hash)
434
+ def new_column_definition(name, type, **options) # :nodoc:
435
+ if integer_like_primary_key?(type, options)
436
+ type = integer_like_primary_key_type(type, options)
327
437
  end
328
-
329
- column.limit = limit
330
- column.precision = options[:precision]
331
- column.scale = options[:scale]
332
- column.default = options[:default]
333
- column.null = options[:null]
334
- column.first = options[:first]
335
- column.after = options[:after]
336
- column.primary_key = type == :primary_key || options[:primary_key]
337
- column
438
+ type = aliased_types(type.to_s, type)
439
+ options[:primary_key] ||= type == :primary_key
440
+ options[:null] = false if options[:primary_key]
441
+ create_column_definition(name, type, options)
338
442
  end
339
443
 
340
444
  private
341
- def create_column_definition(name, type)
342
- ColumnDefinition.new name, type
343
- end
445
+ def create_column_definition(name, type, options)
446
+ ColumnDefinition.new(name, type, options)
447
+ end
344
448
 
345
- def native
346
- @native
347
- end
449
+ def aliased_types(name, fallback)
450
+ "timestamp" == name ? :datetime : fallback
451
+ end
348
452
 
349
- def aliased_types(name, fallback)
350
- 'timestamp' == name ? :datetime : fallback
351
- end
453
+ def integer_like_primary_key?(type, options)
454
+ options[:primary_key] && [:integer, :bigint].include?(type) && !options.key?(:default)
455
+ end
456
+
457
+ def integer_like_primary_key_type(type, options)
458
+ type
459
+ end
352
460
  end
353
461
 
354
462
  class AlterTable # :nodoc:
@@ -373,19 +481,20 @@ module ActiveRecord
373
481
  @foreign_key_drops << name
374
482
  end
375
483
 
376
- def add_column(name, type, options)
484
+ def add_column(name, type, **options)
377
485
  name = name.to_s
378
486
  type = type.to_sym
379
- @adds << @td.new_column_definition(name, type, options)
487
+ @adds << AddColumnDefinition.new(@td.new_column_definition(name, type, **options))
380
488
  end
381
489
  end
382
490
 
383
491
  # Represents an SQL table in an abstract way for updating a table.
384
- # Also see TableDefinition and SchemaStatements#create_table
492
+ # Also see TableDefinition and {connection.create_table}[rdoc-ref:SchemaStatements#create_table]
385
493
  #
386
494
  # Available transformations are:
387
495
  #
388
496
  # change_table :table do |t|
497
+ # t.primary_key
389
498
  # t.column
390
499
  # t.index
391
500
  # t.rename_index
@@ -398,15 +507,21 @@ module ActiveRecord
398
507
  # t.string
399
508
  # t.text
400
509
  # t.integer
510
+ # t.bigint
401
511
  # t.float
402
512
  # t.decimal
513
+ # t.numeric
403
514
  # t.datetime
404
515
  # t.timestamp
405
516
  # t.time
406
517
  # t.date
407
518
  # t.binary
408
519
  # t.boolean
520
+ # t.foreign_key
521
+ # t.json
522
+ # t.virtual
409
523
  # t.remove
524
+ # t.remove_foreign_key
410
525
  # t.remove_references
411
526
  # t.remove_belongs_to
412
527
  # t.remove_index
@@ -414,6 +529,8 @@ module ActiveRecord
414
529
  # end
415
530
  #
416
531
  class Table
532
+ include ColumnMethods
533
+
417
534
  attr_reader :name
418
535
 
419
536
  def initialize(table_name, base)
@@ -422,33 +539,44 @@ module ActiveRecord
422
539
  end
423
540
 
424
541
  # Adds a new column to the named table.
425
- # See TableDefinition#column for details of the options you can use.
426
542
  #
427
- # ====== Creating a simple column
428
543
  # t.column(:name, :string)
429
- def column(column_name, type, options = {})
430
- @base.add_column(name, column_name, type, options)
544
+ #
545
+ # See TableDefinition#column for details of the options you can use.
546
+ def column(column_name, type, **options)
547
+ index_options = options.delete(:index)
548
+ @base.add_column(name, column_name, type, **options)
549
+ index(column_name, index_options.is_a?(Hash) ? index_options : {}) if index_options
431
550
  end
432
551
 
433
- # Checks to see if a column exists. See SchemaStatements#column_exists?
434
- def column_exists?(column_name, type = nil, options = {})
435
- @base.column_exists?(name, column_name, type, options)
552
+ # Checks to see if a column exists.
553
+ #
554
+ # t.string(:name) unless t.column_exists?(:name, :string)
555
+ #
556
+ # See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
557
+ def column_exists?(column_name, type = nil, **options)
558
+ @base.column_exists?(name, column_name, type, **options)
436
559
  end
437
560
 
438
561
  # Adds a new index to the table. +column_name+ can be a single Symbol, or
439
- # an Array of Symbols. See SchemaStatements#add_index
562
+ # an Array of Symbols.
440
563
  #
441
- # ====== Creating a simple index
442
564
  # t.index(:name)
443
- # ====== Creating a unique index
444
565
  # t.index([:branch_id, :party_id], unique: true)
445
- # ====== Creating a named index
446
566
  # t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
567
+ #
568
+ # See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
447
569
  def index(column_name, options = {})
448
570
  @base.add_index(name, column_name, options)
449
571
  end
450
572
 
451
- # Checks to see if an index exists. See SchemaStatements#index_exists?
573
+ # Checks to see if an index exists.
574
+ #
575
+ # unless t.index_exists?(:branch_id)
576
+ # t.index(:branch_id)
577
+ # end
578
+ #
579
+ # See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?]
452
580
  def index_exists?(column_name, options = {})
453
581
  @base.index_exists?(name, column_name, options)
454
582
  end
@@ -456,52 +584,59 @@ module ActiveRecord
456
584
  # Renames the given index on the table.
457
585
  #
458
586
  # t.rename_index(:user_id, :account_id)
587
+ #
588
+ # See {connection.rename_index}[rdoc-ref:SchemaStatements#rename_index]
459
589
  def rename_index(index_name, new_index_name)
460
590
  @base.rename_index(name, index_name, new_index_name)
461
591
  end
462
592
 
463
- # Adds timestamps (+created_at+ and +updated_at+) columns to the table. See SchemaStatements#add_timestamps
593
+ # Adds timestamps (+created_at+ and +updated_at+) columns to the table.
594
+ #
595
+ # t.timestamps(null: false)
464
596
  #
465
- # t.timestamps null: false
466
- def timestamps(options = {})
467
- @base.add_timestamps(name, options)
597
+ # See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
598
+ def timestamps(**options)
599
+ @base.add_timestamps(name, **options)
468
600
  end
469
601
 
470
602
  # Changes the column's definition according to the new options.
471
- # See TableDefinition#column for details of the options you can use.
472
603
  #
473
604
  # t.change(:name, :string, limit: 80)
474
605
  # t.change(:description, :text)
606
+ #
607
+ # See TableDefinition#column for details of the options you can use.
475
608
  def change(column_name, type, options = {})
476
609
  @base.change_column(name, column_name, type, options)
477
610
  end
478
611
 
479
- # Sets a new default value for a column. See SchemaStatements#change_column_default
612
+ # Sets a new default value for a column.
480
613
  #
481
614
  # t.change_default(:qualification, 'new')
482
615
  # t.change_default(:authorized, 1)
483
- def change_default(column_name, default)
484
- @base.change_column_default(name, column_name, default)
616
+ # t.change_default(:status, from: nil, to: "draft")
617
+ #
618
+ # See {connection.change_column_default}[rdoc-ref:SchemaStatements#change_column_default]
619
+ def change_default(column_name, default_or_changes)
620
+ @base.change_column_default(name, column_name, default_or_changes)
485
621
  end
486
622
 
487
623
  # Removes the column(s) from the table definition.
488
624
  #
489
625
  # t.remove(:qualification)
490
626
  # t.remove(:qualification, :experience)
627
+ #
628
+ # See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
491
629
  def remove(*column_names)
492
630
  @base.remove_columns(name, *column_names)
493
631
  end
494
632
 
495
633
  # Removes the given index from the table.
496
634
  #
497
- # ====== Remove the index_table_name_on_column in the table_name table
498
- # t.remove_index :column
499
- # ====== Remove the index named index_table_name_on_branch_id in the table_name table
500
- # t.remove_index column: :branch_id
501
- # ====== Remove the index named index_table_name_on_branch_id_and_party_id in the table_name table
502
- # t.remove_index column: [:branch_id, :party_id]
503
- # ====== Remove the index named by_branch_party in the table_name table
504
- # t.remove_index name: :by_branch_party
635
+ # t.remove_index(:branch_id)
636
+ # t.remove_index(column: [:branch_id, :party_id])
637
+ # t.remove_index(name: :by_branch_party)
638
+ #
639
+ # See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
505
640
  def remove_index(options = {})
506
641
  @base.remove_index(name, options)
507
642
  end
@@ -509,66 +644,75 @@ module ActiveRecord
509
644
  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
510
645
  #
511
646
  # t.remove_timestamps
512
- def remove_timestamps(options = {})
513
- @base.remove_timestamps(name, options)
647
+ #
648
+ # See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
649
+ def remove_timestamps(**options)
650
+ @base.remove_timestamps(name, **options)
514
651
  end
515
652
 
516
653
  # Renames a column.
517
654
  #
518
655
  # t.rename(:description, :name)
656
+ #
657
+ # See {connection.rename_column}[rdoc-ref:SchemaStatements#rename_column]
519
658
  def rename(column_name, new_column_name)
520
659
  @base.rename_column(name, column_name, new_column_name)
521
660
  end
522
661
 
523
- # Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided.
524
- # <tt>references</tt> and <tt>belongs_to</tt> are acceptable. The reference column will be an +integer+
525
- # by default, the <tt>:type</tt> option can be used to specify a different type.
662
+ # Adds a reference.
526
663
  #
527
664
  # t.references(:user)
528
- # t.references(:user, type: "string")
529
- # t.belongs_to(:supplier, polymorphic: true)
665
+ # t.belongs_to(:supplier, foreign_key: true)
530
666
  #
531
- # See SchemaStatements#add_reference
532
- def references(*args)
533
- options = args.extract_options!
667
+ # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
668
+ def references(*args, **options)
534
669
  args.each do |ref_name|
535
- @base.add_reference(name, ref_name, options)
670
+ @base.add_reference(name, ref_name, **options)
536
671
  end
537
672
  end
538
673
  alias :belongs_to :references
539
674
 
540
675
  # Removes a reference. Optionally removes a +type+ column.
541
- # <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
542
676
  #
543
677
  # t.remove_references(:user)
544
678
  # t.remove_belongs_to(:supplier, polymorphic: true)
545
679
  #
546
- # See SchemaStatements#remove_reference
547
- def remove_references(*args)
548
- options = args.extract_options!
680
+ # See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
681
+ def remove_references(*args, **options)
549
682
  args.each do |ref_name|
550
- @base.remove_reference(name, ref_name, options)
683
+ @base.remove_reference(name, ref_name, **options)
551
684
  end
552
685
  end
553
686
  alias :remove_belongs_to :remove_references
554
687
 
555
- # Adds a column or columns of a specified type
688
+ # Adds a foreign key to the table using a supplied table name.
556
689
  #
557
- # t.string(:goat)
558
- # t.string(:goat, :sheep)
559
- [:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
560
- define_method column_type do |*args|
561
- options = args.extract_options!
562
- args.each do |column_name|
563
- @base.add_column(name, column_name, column_type, options)
564
- end
565
- end
690
+ # t.foreign_key(:authors)
691
+ # t.foreign_key(:authors, column: :author_id, primary_key: "id")
692
+ #
693
+ # See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
694
+ def foreign_key(*args, **options)
695
+ @base.add_foreign_key(name, *args, **options)
566
696
  end
567
697
 
568
- private
569
- def native
570
- @base.native_database_types
571
- end
698
+ # Removes the given foreign key from the table.
699
+ #
700
+ # t.remove_foreign_key(:authors)
701
+ # t.remove_foreign_key(column: :author_id)
702
+ #
703
+ # See {connection.remove_foreign_key}[rdoc-ref:SchemaStatements#remove_foreign_key]
704
+ def remove_foreign_key(*args, **options)
705
+ @base.remove_foreign_key(name, *args, **options)
706
+ end
707
+
708
+ # Checks to see if a foreign key exists.
709
+ #
710
+ # t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
711
+ #
712
+ # See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
713
+ def foreign_key_exists?(*args, **options)
714
+ @base.foreign_key_exists?(name, *args, **options)
715
+ end
572
716
  end
573
717
  end
574
718
  end