activerecord 3.2.6 → 6.0.0

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

Potentially problematic release.


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

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