activerecord 5.2.7.1 → 6.1.4.6

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 (316) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1145 -575
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +7 -5
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +9 -8
  7. data/lib/active_record/association_relation.rb +30 -10
  8. data/lib/active_record/associations/alias_tracker.rb +19 -16
  9. data/lib/active_record/associations/association.rb +100 -41
  10. data/lib/active_record/associations/association_scope.rb +23 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +55 -48
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
  13. data/lib/active_record/associations/builder/association.rb +45 -22
  14. data/lib/active_record/associations/builder/belongs_to.rb +29 -59
  15. data/lib/active_record/associations/builder/collection_association.rb +8 -17
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -2
  18. data/lib/active_record/associations/builder/has_one.rb +33 -2
  19. data/lib/active_record/associations/builder/singular_association.rb +3 -1
  20. data/lib/active_record/associations/collection_association.rb +31 -29
  21. data/lib/active_record/associations/collection_proxy.rb +25 -21
  22. data/lib/active_record/associations/foreign_association.rb +20 -0
  23. data/lib/active_record/associations/has_many_association.rb +26 -13
  24. data/lib/active_record/associations/has_many_through_association.rb +24 -18
  25. data/lib/active_record/associations/has_one_association.rb +43 -31
  26. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  27. data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
  28. data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
  29. data/lib/active_record/associations/join_dependency.rb +91 -60
  30. data/lib/active_record/associations/preloader/association.rb +71 -43
  31. data/lib/active_record/associations/preloader/through_association.rb +49 -40
  32. data/lib/active_record/associations/preloader.rb +47 -34
  33. data/lib/active_record/associations/singular_association.rb +3 -17
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/associations.rb +137 -25
  36. data/lib/active_record/attribute_assignment.rb +17 -19
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
  38. data/lib/active_record/attribute_methods/dirty.rb +101 -40
  39. data/lib/active_record/attribute_methods/primary_key.rb +20 -25
  40. data/lib/active_record/attribute_methods/query.rb +4 -8
  41. data/lib/active_record/attribute_methods/read.rb +14 -56
  42. data/lib/active_record/attribute_methods/serialization.rb +12 -7
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  44. data/lib/active_record/attribute_methods/write.rb +18 -34
  45. data/lib/active_record/attribute_methods.rb +81 -143
  46. data/lib/active_record/attributes.rb +46 -9
  47. data/lib/active_record/autosave_association.rb +57 -42
  48. data/lib/active_record/base.rb +4 -17
  49. data/lib/active_record/callbacks.rb +158 -43
  50. data/lib/active_record/coders/yaml_column.rb +12 -3
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +207 -90
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +167 -69
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -99
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
  64. data/lib/active_record/connection_adapters/column.rb +30 -12
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  67. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  68. data/lib/active_record/connection_adapters/mysql/database_statements.rb +86 -32
  69. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  70. data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
  71. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
  72. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
  73. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
  74. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
  75. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
  77. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  78. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  79. data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
  80. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +38 -54
  81. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
  93. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  94. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  96. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
  97. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
  99. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  100. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
  101. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  102. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  103. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
  104. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
  105. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  106. data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
  107. data/lib/active_record/connection_adapters/schema_cache.rb +135 -21
  108. data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
  109. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
  110. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  111. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  112. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
  113. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
  114. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  115. data/lib/active_record/connection_adapters.rb +52 -0
  116. data/lib/active_record/connection_handling.rb +293 -33
  117. data/lib/active_record/core.rb +334 -97
  118. data/lib/active_record/counter_cache.rb +8 -30
  119. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  120. data/lib/active_record/database_configurations/database_config.rb +80 -0
  121. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  122. data/lib/active_record/database_configurations/url_config.rb +53 -0
  123. data/lib/active_record/database_configurations.rb +272 -0
  124. data/lib/active_record/delegated_type.rb +209 -0
  125. data/lib/active_record/destroy_association_async_job.rb +36 -0
  126. data/lib/active_record/dynamic_matchers.rb +3 -4
  127. data/lib/active_record/enum.rb +108 -36
  128. data/lib/active_record/errors.rb +62 -19
  129. data/lib/active_record/explain.rb +10 -6
  130. data/lib/active_record/explain_subscriber.rb +1 -1
  131. data/lib/active_record/fixture_set/file.rb +10 -17
  132. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  133. data/lib/active_record/fixture_set/render_context.rb +17 -0
  134. data/lib/active_record/fixture_set/table_row.rb +152 -0
  135. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  136. data/lib/active_record/fixtures.rb +200 -481
  137. data/lib/active_record/gem_version.rb +4 -4
  138. data/lib/active_record/inheritance.rb +53 -24
  139. data/lib/active_record/insert_all.rb +212 -0
  140. data/lib/active_record/integration.rb +67 -17
  141. data/lib/active_record/internal_metadata.rb +26 -9
  142. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  143. data/lib/active_record/locking/optimistic.rb +37 -23
  144. data/lib/active_record/locking/pessimistic.rb +9 -5
  145. data/lib/active_record/log_subscriber.rb +35 -35
  146. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  147. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  148. data/lib/active_record/middleware/database_selector.rb +77 -0
  149. data/lib/active_record/migration/command_recorder.rb +96 -44
  150. data/lib/active_record/migration/compatibility.rb +142 -64
  151. data/lib/active_record/migration/join_table.rb +0 -1
  152. data/lib/active_record/migration.rb +206 -157
  153. data/lib/active_record/model_schema.rb +148 -22
  154. data/lib/active_record/nested_attributes.rb +4 -7
  155. data/lib/active_record/no_touching.rb +8 -1
  156. data/lib/active_record/null_relation.rb +0 -1
  157. data/lib/active_record/persistence.rb +267 -59
  158. data/lib/active_record/query_cache.rb +21 -4
  159. data/lib/active_record/querying.rb +40 -23
  160. data/lib/active_record/railtie.rb +115 -58
  161. data/lib/active_record/railties/console_sandbox.rb +2 -4
  162. data/lib/active_record/railties/controller_runtime.rb +30 -35
  163. data/lib/active_record/railties/databases.rake +411 -80
  164. data/lib/active_record/readonly_attributes.rb +4 -0
  165. data/lib/active_record/reflection.rb +109 -93
  166. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  167. data/lib/active_record/relation/batches.rb +44 -35
  168. data/lib/active_record/relation/calculations.rb +157 -90
  169. data/lib/active_record/relation/delegation.rb +35 -50
  170. data/lib/active_record/relation/finder_methods.rb +64 -39
  171. data/lib/active_record/relation/from_clause.rb +5 -1
  172. data/lib/active_record/relation/merger.rb +32 -40
  173. data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
  174. data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  179. data/lib/active_record/relation/predicate_builder.rb +62 -45
  180. data/lib/active_record/relation/query_attribute.rb +13 -8
  181. data/lib/active_record/relation/query_methods.rb +476 -187
  182. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  183. data/lib/active_record/relation/spawn_methods.rb +9 -9
  184. data/lib/active_record/relation/where_clause.rb +115 -62
  185. data/lib/active_record/relation.rb +379 -115
  186. data/lib/active_record/result.rb +64 -38
  187. data/lib/active_record/runtime_registry.rb +2 -2
  188. data/lib/active_record/sanitization.rb +22 -41
  189. data/lib/active_record/schema.rb +2 -11
  190. data/lib/active_record/schema_dumper.rb +54 -9
  191. data/lib/active_record/schema_migration.rb +7 -9
  192. data/lib/active_record/scoping/default.rb +4 -8
  193. data/lib/active_record/scoping/named.rb +17 -24
  194. data/lib/active_record/scoping.rb +8 -9
  195. data/lib/active_record/secure_token.rb +16 -8
  196. data/lib/active_record/serialization.rb +5 -3
  197. data/lib/active_record/signed_id.rb +116 -0
  198. data/lib/active_record/statement_cache.rb +49 -6
  199. data/lib/active_record/store.rb +88 -9
  200. data/lib/active_record/suppressor.rb +2 -2
  201. data/lib/active_record/table_metadata.rb +42 -43
  202. data/lib/active_record/tasks/database_tasks.rb +277 -81
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
  206. data/lib/active_record/test_databases.rb +24 -0
  207. data/lib/active_record/test_fixtures.rb +287 -0
  208. data/lib/active_record/timestamp.rb +43 -32
  209. data/lib/active_record/touch_later.rb +23 -22
  210. data/lib/active_record/transactions.rb +62 -118
  211. data/lib/active_record/translation.rb +1 -1
  212. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  213. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  214. data/lib/active_record/type/serialized.rb +6 -3
  215. data/lib/active_record/type/time.rb +10 -0
  216. data/lib/active_record/type/type_map.rb +0 -1
  217. data/lib/active_record/type/unsigned_integer.rb +0 -1
  218. data/lib/active_record/type.rb +10 -5
  219. data/lib/active_record/type_caster/connection.rb +15 -15
  220. data/lib/active_record/type_caster/map.rb +8 -8
  221. data/lib/active_record/validations/associated.rb +1 -2
  222. data/lib/active_record/validations/numericality.rb +35 -0
  223. data/lib/active_record/validations/uniqueness.rb +38 -30
  224. data/lib/active_record/validations.rb +4 -3
  225. data/lib/active_record.rb +13 -12
  226. data/lib/arel/alias_predication.rb +9 -0
  227. data/lib/arel/attributes/attribute.rb +41 -0
  228. data/lib/arel/collectors/bind.rb +29 -0
  229. data/lib/arel/collectors/composite.rb +39 -0
  230. data/lib/arel/collectors/plain_string.rb +20 -0
  231. data/lib/arel/collectors/sql_string.rb +27 -0
  232. data/lib/arel/collectors/substitute_binds.rb +35 -0
  233. data/lib/arel/crud.rb +42 -0
  234. data/lib/arel/delete_manager.rb +18 -0
  235. data/lib/arel/errors.rb +9 -0
  236. data/lib/arel/expressions.rb +29 -0
  237. data/lib/arel/factory_methods.rb +49 -0
  238. data/lib/arel/insert_manager.rb +49 -0
  239. data/lib/arel/math.rb +45 -0
  240. data/lib/arel/nodes/and.rb +32 -0
  241. data/lib/arel/nodes/ascending.rb +23 -0
  242. data/lib/arel/nodes/binary.rb +126 -0
  243. data/lib/arel/nodes/bind_param.rb +44 -0
  244. data/lib/arel/nodes/case.rb +55 -0
  245. data/lib/arel/nodes/casted.rb +62 -0
  246. data/lib/arel/nodes/comment.rb +29 -0
  247. data/lib/arel/nodes/count.rb +12 -0
  248. data/lib/arel/nodes/delete_statement.rb +45 -0
  249. data/lib/arel/nodes/descending.rb +23 -0
  250. data/lib/arel/nodes/equality.rb +15 -0
  251. data/lib/arel/nodes/extract.rb +24 -0
  252. data/lib/arel/nodes/false.rb +16 -0
  253. data/lib/arel/nodes/full_outer_join.rb +8 -0
  254. data/lib/arel/nodes/function.rb +44 -0
  255. data/lib/arel/nodes/grouping.rb +11 -0
  256. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  257. data/lib/arel/nodes/in.rb +15 -0
  258. data/lib/arel/nodes/infix_operation.rb +92 -0
  259. data/lib/arel/nodes/inner_join.rb +8 -0
  260. data/lib/arel/nodes/insert_statement.rb +37 -0
  261. data/lib/arel/nodes/join_source.rb +20 -0
  262. data/lib/arel/nodes/matches.rb +18 -0
  263. data/lib/arel/nodes/named_function.rb +23 -0
  264. data/lib/arel/nodes/node.rb +51 -0
  265. data/lib/arel/nodes/node_expression.rb +13 -0
  266. data/lib/arel/nodes/ordering.rb +27 -0
  267. data/lib/arel/nodes/outer_join.rb +8 -0
  268. data/lib/arel/nodes/over.rb +15 -0
  269. data/lib/arel/nodes/regexp.rb +16 -0
  270. data/lib/arel/nodes/right_outer_join.rb +8 -0
  271. data/lib/arel/nodes/select_core.rb +67 -0
  272. data/lib/arel/nodes/select_statement.rb +41 -0
  273. data/lib/arel/nodes/sql_literal.rb +19 -0
  274. data/lib/arel/nodes/string_join.rb +11 -0
  275. data/lib/arel/nodes/table_alias.rb +31 -0
  276. data/lib/arel/nodes/terminal.rb +16 -0
  277. data/lib/arel/nodes/true.rb +16 -0
  278. data/lib/arel/nodes/unary.rb +44 -0
  279. data/lib/arel/nodes/unary_operation.rb +20 -0
  280. data/lib/arel/nodes/unqualified_column.rb +22 -0
  281. data/lib/arel/nodes/update_statement.rb +41 -0
  282. data/lib/arel/nodes/values_list.rb +9 -0
  283. data/lib/arel/nodes/window.rb +126 -0
  284. data/lib/arel/nodes/with.rb +11 -0
  285. data/lib/arel/nodes.rb +70 -0
  286. data/lib/arel/order_predications.rb +13 -0
  287. data/lib/arel/predications.rb +250 -0
  288. data/lib/arel/select_manager.rb +270 -0
  289. data/lib/arel/table.rb +118 -0
  290. data/lib/arel/tree_manager.rb +72 -0
  291. data/lib/arel/update_manager.rb +34 -0
  292. data/lib/arel/visitors/dot.rb +308 -0
  293. data/lib/arel/visitors/mysql.rb +93 -0
  294. data/lib/arel/visitors/postgresql.rb +120 -0
  295. data/lib/arel/visitors/sqlite.rb +38 -0
  296. data/lib/arel/visitors/to_sql.rb +899 -0
  297. data/lib/arel/visitors/visitor.rb +45 -0
  298. data/lib/arel/visitors.rb +13 -0
  299. data/lib/arel/window_predications.rb +9 -0
  300. data/lib/arel.rb +54 -0
  301. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  302. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
  303. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
  304. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
  305. data/lib/rails/generators/active_record/migration.rb +19 -2
  306. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  307. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  308. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  309. metadata +117 -32
  310. data/lib/active_record/attribute_decorators.rb +0 -90
  311. data/lib/active_record/collection_cache_key.rb +0 -53
  312. data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
  313. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
  314. data/lib/active_record/define_callbacks.rb +0 -22
  315. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
  316. data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -8,12 +8,15 @@ module ActiveRecord
8
8
  #
9
9
  # * add_column
10
10
  # * add_foreign_key
11
+ # * add_check_constraint
11
12
  # * add_index
12
13
  # * add_reference
13
14
  # * add_timestamps
14
15
  # * change_column
15
16
  # * change_column_default (must supply a :from and :to option)
16
17
  # * change_column_null
18
+ # * change_column_comment (must supply a :from and :to option)
19
+ # * change_table_comment (must supply a :from and :to option)
17
20
  # * create_join_table
18
21
  # * create_table
19
22
  # * disable_extension
@@ -23,6 +26,7 @@ module ActiveRecord
23
26
  # * remove_column (must supply a type)
24
27
  # * remove_columns (must specify at least one column name or more)
25
28
  # * remove_foreign_key (must supply a second table)
29
+ # * remove_check_constraint
26
30
  # * remove_index
27
31
  # * remove_reference
28
32
  # * remove_timestamps
@@ -30,12 +34,15 @@ module ActiveRecord
30
34
  # * rename_index
31
35
  # * rename_table
32
36
  class CommandRecorder
33
- ReversibleAndIrreversibleMethods = [:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
37
+ ReversibleAndIrreversibleMethods = [
38
+ :create_table, :create_join_table, :rename_table, :add_column, :remove_column,
34
39
  :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
35
40
  :change_column_default, :add_reference, :remove_reference, :transaction,
36
41
  :drop_join_table, :drop_table, :execute_block, :enable_extension, :disable_extension,
37
42
  :change_column, :execute, :remove_columns, :change_column_null,
38
- :add_foreign_key, :remove_foreign_key
43
+ :add_foreign_key, :remove_foreign_key,
44
+ :change_column_comment, :change_table_comment,
45
+ :add_check_constraint, :remove_check_constraint
39
46
  ]
40
47
  include JoinTable
41
48
 
@@ -81,11 +88,16 @@ module ActiveRecord
81
88
  # recorder.inverse_of(:rename_table, [:old, :new])
82
89
  # # => [:rename_table, [:new, :old]]
83
90
  #
91
+ # If the inverse of a command requires several commands, returns array of commands.
92
+ #
93
+ # recorder.inverse_of(:remove_columns, [:some_table, :foo, :bar, type: :string])
94
+ # # => [[:add_column, :some_table, :foo, :string], [:add_column, :some_table, :bar, :string]]
95
+ #
84
96
  # This method will raise an +IrreversibleMigration+ exception if it cannot
85
97
  # invert the +command+.
86
98
  def inverse_of(command, args, &block)
87
99
  method = :"invert_#{command}"
88
- raise IrreversibleMigration, <<-MSG.strip_heredoc unless respond_to?(method, true)
100
+ raise IrreversibleMigration, <<~MSG unless respond_to?(method, true)
89
101
  This migration uses #{command}, which is not automatically reversible.
90
102
  To make the migration reversible you can either:
91
103
  1. Define #up and #down methods in place of the #change method.
@@ -100,25 +112,34 @@ module ActiveRecord
100
112
  record(:"#{method}", args, &block) # record(:create_table, args, &block)
101
113
  end # end
102
114
  EOV
115
+ ruby2_keywords(method) if respond_to?(:ruby2_keywords, true)
103
116
  end
104
117
  alias :add_belongs_to :add_reference
105
118
  alias :remove_belongs_to :remove_reference
106
119
 
107
- def change_table(table_name, options = {}) # :nodoc:
120
+ def change_table(table_name, **options) # :nodoc:
108
121
  yield delegate.update_table_definition(table_name, self)
109
122
  end
110
123
 
111
- private
124
+ def replay(migration)
125
+ commands.each do |cmd, args, block|
126
+ migration.send(cmd, *args, &block)
127
+ end
128
+ end
112
129
 
130
+ private
113
131
  module StraightReversions # :nodoc:
114
132
  private
115
- { transaction: :transaction,
133
+ {
116
134
  execute_block: :execute_block,
117
135
  create_table: :drop_table,
118
136
  create_join_table: :drop_join_table,
119
137
  add_column: :remove_column,
138
+ add_index: :remove_index,
120
139
  add_timestamps: :remove_timestamps,
121
140
  add_reference: :remove_reference,
141
+ add_foreign_key: :remove_foreign_key,
142
+ add_check_constraint: :remove_check_constraint,
122
143
  enable_extension: :disable_extension
123
144
  }.each do |cmd, inv|
124
145
  [[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
@@ -133,6 +154,17 @@ module ActiveRecord
133
154
 
134
155
  include StraightReversions
135
156
 
157
+ def invert_transaction(args)
158
+ sub_recorder = CommandRecorder.new(delegate)
159
+ sub_recorder.revert { yield }
160
+
161
+ invertions_proc = proc {
162
+ sub_recorder.replay(self)
163
+ }
164
+
165
+ [:transaction, args, invertions_proc]
166
+ end
167
+
136
168
  def invert_drop_table(args, &block)
137
169
  if args.size == 1 && block == nil
138
170
  raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
@@ -149,44 +181,49 @@ module ActiveRecord
149
181
  super
150
182
  end
151
183
 
184
+ def invert_remove_columns(args)
185
+ unless args[-1].is_a?(Hash) && args[-1].has_key?(:type)
186
+ raise ActiveRecord::IrreversibleMigration, "remove_columns is only reversible if given a type."
187
+ end
188
+
189
+ [:add_columns, args]
190
+ end
191
+
152
192
  def invert_rename_index(args)
153
- [:rename_index, [args.first] + args.last(2).reverse]
193
+ table_name, old_name, new_name = args
194
+ [:rename_index, [table_name, new_name, old_name]]
154
195
  end
155
196
 
156
197
  def invert_rename_column(args)
157
- [:rename_column, [args.first] + args.last(2).reverse]
198
+ table_name, old_name, new_name = args
199
+ [:rename_column, [table_name, new_name, old_name]]
158
200
  end
159
201
 
160
- def invert_add_index(args)
161
- table, columns, options = *args
162
- options ||= {}
163
-
164
- options_hash = options.slice(:name, :algorithm)
165
- options_hash[:column] = columns if !options_hash[:name]
202
+ def invert_remove_index(args)
203
+ options = args.extract_options!
204
+ table, columns = args
166
205
 
167
- [:remove_index, [table, options_hash]]
168
- end
206
+ columns ||= options.delete(:column)
169
207
 
170
- def invert_remove_index(args)
171
- table, options_or_column = *args
172
- if (options = options_or_column).is_a?(Hash)
173
- unless options[:column]
174
- raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
175
- end
176
- options = options.dup
177
- [:add_index, [table, options.delete(:column), options]]
178
- elsif (column = options_or_column).present?
179
- [:add_index, [table, column]]
208
+ unless columns
209
+ raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
180
210
  end
211
+
212
+ options.delete(:if_exists)
213
+
214
+ args = [table, columns]
215
+ args << options unless options.empty?
216
+
217
+ [:add_index, args]
181
218
  end
182
219
 
183
220
  alias :invert_add_belongs_to :invert_add_reference
184
221
  alias :invert_remove_belongs_to :invert_remove_reference
185
222
 
186
223
  def invert_change_column_default(args)
187
- table, column, options = *args
224
+ table, column, options = args
188
225
 
189
- unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
226
+ unless options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
190
227
  raise ActiveRecord::IrreversibleMigration, "change_column_default is only reversible if given a :from and :to option."
191
228
  end
192
229
 
@@ -198,29 +235,43 @@ module ActiveRecord
198
235
  [:change_column_null, args]
199
236
  end
200
237
 
201
- def invert_add_foreign_key(args)
202
- from_table, to_table, add_options = args
203
- add_options ||= {}
238
+ def invert_remove_foreign_key(args)
239
+ options = args.extract_options!
240
+ from_table, to_table = args
204
241
 
205
- if add_options[:name]
206
- options = { name: add_options[:name] }
207
- elsif add_options[:column]
208
- options = { column: add_options[:column] }
209
- else
210
- options = to_table
242
+ to_table ||= options.delete(:to_table)
243
+
244
+ raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil?
245
+
246
+ reversed_args = [from_table, to_table]
247
+ reversed_args << options unless options.empty?
248
+
249
+ [:add_foreign_key, reversed_args]
250
+ end
251
+
252
+ def invert_change_column_comment(args)
253
+ table, column, options = args
254
+
255
+ unless options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
256
+ raise ActiveRecord::IrreversibleMigration, "change_column_comment is only reversible if given a :from and :to option."
211
257
  end
212
258
 
213
- [:remove_foreign_key, [from_table, options]]
259
+ [:change_column_comment, [table, column, from: options[:to], to: options[:from]]]
214
260
  end
215
261
 
216
- def invert_remove_foreign_key(args)
217
- from_table, to_table, remove_options = args
218
- raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil? || to_table.is_a?(Hash)
262
+ def invert_change_table_comment(args)
263
+ table, options = args
219
264
 
220
- reversed_args = [from_table, to_table]
221
- reversed_args << remove_options if remove_options
265
+ unless options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
266
+ raise ActiveRecord::IrreversibleMigration, "change_table_comment is only reversible if given a :from and :to option."
267
+ end
222
268
 
223
- [:add_foreign_key, reversed_args]
269
+ [:change_table_comment, [table, from: options[:to], to: options[:from]]]
270
+ end
271
+
272
+ def invert_remove_check_constraint(args)
273
+ raise ActiveRecord::IrreversibleMigration, "remove_check_constraint is only reversible if given an expression." if args.size < 2
274
+ super
224
275
  end
225
276
 
226
277
  def respond_to_missing?(method, _)
@@ -235,6 +286,7 @@ module ActiveRecord
235
286
  super
236
287
  end
237
288
  end
289
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
238
290
  end
239
291
  end
240
292
  end
@@ -13,12 +13,135 @@ module ActiveRecord
13
13
  const_get(name)
14
14
  end
15
15
 
16
- V5_2 = Current
16
+ V6_1 = Current
17
+
18
+ class V6_0 < V6_1
19
+ class ReferenceDefinition < ConnectionAdapters::ReferenceDefinition
20
+ def index_options(table_name)
21
+ as_options(index)
22
+ end
23
+ end
24
+
25
+ module TableDefinition
26
+ def references(*args, **options)
27
+ args.each do |ref_name|
28
+ ReferenceDefinition.new(ref_name, **options).add_to(self)
29
+ end
30
+ end
31
+ alias :belongs_to :references
32
+ end
33
+
34
+ def create_table(table_name, **options)
35
+ if block_given?
36
+ super { |t| yield compatible_table_definition(t) }
37
+ else
38
+ super
39
+ end
40
+ end
41
+
42
+ def change_table(table_name, **options)
43
+ if block_given?
44
+ super { |t| yield compatible_table_definition(t) }
45
+ else
46
+ super
47
+ end
48
+ end
49
+
50
+ def create_join_table(table_1, table_2, **options)
51
+ if block_given?
52
+ super { |t| yield compatible_table_definition(t) }
53
+ else
54
+ super
55
+ end
56
+ end
57
+
58
+ def add_reference(table_name, ref_name, **options)
59
+ ReferenceDefinition.new(ref_name, **options)
60
+ .add_to(connection.update_table_definition(table_name, self))
61
+ end
62
+ alias :add_belongs_to :add_reference
63
+
64
+ private
65
+ def compatible_table_definition(t)
66
+ class << t
67
+ prepend TableDefinition
68
+ end
69
+ t
70
+ end
71
+ end
72
+
73
+ class V5_2 < V6_0
74
+ module TableDefinition
75
+ def timestamps(**options)
76
+ options[:precision] ||= nil
77
+ super
78
+ end
79
+ end
80
+
81
+ module CommandRecorder
82
+ def invert_transaction(args, &block)
83
+ [:transaction, args, block]
84
+ end
85
+
86
+ def invert_change_column_comment(args)
87
+ [:change_column_comment, args]
88
+ end
89
+
90
+ def invert_change_table_comment(args)
91
+ [:change_table_comment, args]
92
+ end
93
+ end
94
+
95
+ def create_table(table_name, **options)
96
+ if block_given?
97
+ super { |t| yield compatible_table_definition(t) }
98
+ else
99
+ super
100
+ end
101
+ end
102
+
103
+ def change_table(table_name, **options)
104
+ if block_given?
105
+ super { |t| yield compatible_table_definition(t) }
106
+ else
107
+ super
108
+ end
109
+ end
110
+
111
+ def create_join_table(table_1, table_2, **options)
112
+ if block_given?
113
+ super { |t| yield compatible_table_definition(t) }
114
+ else
115
+ super
116
+ end
117
+ end
118
+
119
+ def add_timestamps(table_name, **options)
120
+ options[:precision] ||= nil
121
+ super
122
+ end
123
+
124
+ private
125
+ def compatible_table_definition(t)
126
+ class << t
127
+ prepend TableDefinition
128
+ end
129
+ t
130
+ end
131
+
132
+ def command_recorder
133
+ recorder = super
134
+ class << recorder
135
+ prepend CommandRecorder
136
+ end
137
+ recorder
138
+ end
139
+ end
17
140
 
18
141
  class V5_1 < V5_2
19
- def change_column(table_name, column_name, type, options = {})
142
+ def change_column(table_name, column_name, type, **options)
20
143
  if connection.adapter_name == "PostgreSQL"
21
- super(table_name, column_name, type, options.except(:default, :null, :comment))
144
+ super(table_name, column_name, type, **options.except(:default, :null, :comment))
22
145
  connection.change_column_default(table_name, column_name, options[:default]) if options.key?(:default)
23
146
  connection.change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
24
147
  connection.change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
@@ -27,7 +150,7 @@ module ActiveRecord
27
150
  end
28
151
  end
29
152
 
30
- def create_table(table_name, options = {})
153
+ def create_table(table_name, **options)
31
154
  if connection.adapter_name == "Mysql2"
32
155
  super(table_name, options: "ENGINE=InnoDB", **options)
33
156
  else
@@ -49,7 +172,7 @@ module ActiveRecord
49
172
  alias :belongs_to :references
50
173
  end
51
174
 
52
- def create_table(table_name, options = {})
175
+ def create_table(table_name, **options)
53
176
  if connection.adapter_name == "PostgreSQL"
54
177
  if options[:id] == :uuid && !options.key?(:default)
55
178
  options[:default] = "uuid_generate_v4()"
@@ -69,38 +192,15 @@ module ActiveRecord
69
192
  options[:id] = :integer
70
193
  end
71
194
 
72
- if block_given?
73
- super do |t|
74
- yield compatible_table_definition(t)
75
- end
76
- else
77
- super
78
- end
79
- end
80
-
81
- def change_table(table_name, options = {})
82
- if block_given?
83
- super do |t|
84
- yield compatible_table_definition(t)
85
- end
86
- else
87
- super
88
- end
195
+ super
89
196
  end
90
197
 
91
198
  def create_join_table(table_1, table_2, column_options: {}, **options)
92
199
  column_options.reverse_merge!(type: :integer)
93
-
94
- if block_given?
95
- super do |t|
96
- yield compatible_table_definition(t)
97
- end
98
- else
99
- super
100
- end
200
+ super
101
201
  end
102
202
 
103
- def add_column(table_name, column_name, type, options = {})
203
+ def add_column(table_name, column_name, type, **options)
104
204
  if type == :primary_key
105
205
  type = :integer
106
206
  options[:primary_key] = true
@@ -118,7 +218,7 @@ module ActiveRecord
118
218
  class << t
119
219
  prepend TableDefinition
120
220
  end
121
- t
221
+ super
122
222
  end
123
223
  end
124
224
 
@@ -136,38 +236,18 @@ module ActiveRecord
136
236
  end
137
237
  end
138
238
 
139
- def create_table(table_name, options = {})
140
- if block_given?
141
- super do |t|
142
- yield compatible_table_definition(t)
143
- end
144
- else
145
- super
146
- end
147
- end
148
-
149
- def change_table(table_name, options = {})
150
- if block_given?
151
- super do |t|
152
- yield compatible_table_definition(t)
153
- end
154
- else
155
- super
156
- end
157
- end
158
-
159
- def add_reference(*, **options)
239
+ def add_reference(table_name, ref_name, **options)
160
240
  options[:index] ||= false
161
241
  super
162
242
  end
163
243
  alias :add_belongs_to :add_reference
164
244
 
165
- def add_timestamps(_, **options)
245
+ def add_timestamps(table_name, **options)
166
246
  options[:null] = true if options[:null].nil?
167
247
  super
168
248
  end
169
249
 
170
- def index_exists?(table_name, column_name, options = {})
250
+ def index_exists?(table_name, column_name, **options)
171
251
  column_names = Array(column_name).map(&:to_s)
172
252
  options[:name] =
173
253
  if options[:name].present?
@@ -178,10 +258,9 @@ module ActiveRecord
178
258
  super
179
259
  end
180
260
 
181
- def remove_index(table_name, options = {})
182
- options = { column: options } unless options.is_a?(Hash)
183
- options[:name] = index_name_for_remove(table_name, options)
184
- super(table_name, options)
261
+ def remove_index(table_name, column_name = nil, **options)
262
+ options[:name] = index_name_for_remove(table_name, column_name, options)
263
+ super
185
264
  end
186
265
 
187
266
  private
@@ -192,13 +271,12 @@ module ActiveRecord
192
271
  super
193
272
  end
194
273
 
195
- def index_name_for_remove(table_name, options = {})
196
- index_name = connection.index_name(table_name, options)
274
+ def index_name_for_remove(table_name, column_name, options)
275
+ index_name = connection.index_name(table_name, column_name || options)
197
276
 
198
277
  unless connection.index_name_exists?(table_name, index_name)
199
- if options.is_a?(Hash) && options.has_key?(:name)
200
- options_without_column = options.dup
201
- options_without_column.delete :column
278
+ if options.key?(:name)
279
+ options_without_column = options.except(:column)
202
280
  index_name_without_column = connection.index_name(table_name, options_without_column)
203
281
 
204
282
  if connection.index_name_exists?(table_name, index_name_without_column)
@@ -4,7 +4,6 @@ module ActiveRecord
4
4
  class Migration
5
5
  module JoinTable #:nodoc:
6
6
  private
7
-
8
7
  def find_join_table_name(table_1, table_2, options = {})
9
8
  options.delete(:table_name) || join_table_name(table_1, table_2)
10
9
  end