activerecord 3.2.22.5 → 5.2.8

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 (275) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +657 -621
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +41 -46
  5. data/examples/performance.rb +55 -42
  6. data/examples/simple.rb +6 -5
  7. data/lib/active_record/aggregations.rb +264 -236
  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 +127 -75
  11. data/lib/active_record/associations/association_scope.rb +126 -92
  12. data/lib/active_record/associations/belongs_to_association.rb +78 -27
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +9 -4
  14. data/lib/active_record/associations/builder/association.rb +117 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +135 -60
  16. data/lib/active_record/associations/builder/collection_association.rb +61 -54
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +120 -42
  18. data/lib/active_record/associations/builder/has_many.rb +10 -64
  19. data/lib/active_record/associations/builder/has_one.rb +19 -51
  20. data/lib/active_record/associations/builder/singular_association.rb +28 -18
  21. data/lib/active_record/associations/collection_association.rb +226 -293
  22. data/lib/active_record/associations/collection_proxy.rb +1067 -69
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +83 -47
  25. data/lib/active_record/associations/has_many_through_association.rb +98 -65
  26. data/lib/active_record/associations/has_one_association.rb +57 -20
  27. data/lib/active_record/associations/has_one_through_association.rb +18 -9
  28. data/lib/active_record/associations/join_dependency/join_association.rb +48 -126
  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 +212 -164
  32. data/lib/active_record/associations/preloader/association.rb +95 -89
  33. data/lib/active_record/associations/preloader/through_association.rb +84 -44
  34. data/lib/active_record/associations/preloader.rb +123 -111
  35. data/lib/active_record/associations/singular_association.rb +33 -24
  36. data/lib/active_record/associations/through_association.rb +60 -26
  37. data/lib/active_record/associations.rb +1759 -1506
  38. data/lib/active_record/attribute_assignment.rb +60 -193
  39. data/lib/active_record/attribute_decorators.rb +90 -0
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +55 -8
  41. data/lib/active_record/attribute_methods/dirty.rb +113 -74
  42. data/lib/active_record/attribute_methods/primary_key.rb +106 -77
  43. data/lib/active_record/attribute_methods/query.rb +8 -5
  44. data/lib/active_record/attribute_methods/read.rb +63 -114
  45. data/lib/active_record/attribute_methods/serialization.rb +60 -90
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -43
  47. data/lib/active_record/attribute_methods/write.rb +43 -45
  48. data/lib/active_record/attribute_methods.rb +366 -149
  49. data/lib/active_record/attributes.rb +266 -0
  50. data/lib/active_record/autosave_association.rb +312 -225
  51. data/lib/active_record/base.rb +114 -505
  52. data/lib/active_record/callbacks.rb +145 -67
  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/collection_cache_key.rb +53 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +883 -284
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +16 -2
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +350 -200
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -27
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +150 -65
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +146 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +477 -284
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +95 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1100 -310
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +283 -0
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +450 -118
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +657 -446
  69. data/lib/active_record/connection_adapters/column.rb +50 -255
  70. data/lib/active_record/connection_adapters/connection_specification.rb +287 -0
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +59 -210
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +163 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +56 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +111 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +168 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +206 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +774 -0
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +620 -1080
  117. data/lib/active_record/connection_adapters/schema_cache.rb +85 -36
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -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 +67 -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 +106 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +545 -27
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +145 -0
  128. data/lib/active_record/core.rb +559 -0
  129. data/lib/active_record/counter_cache.rb +200 -105
  130. data/lib/active_record/define_callbacks.rb +22 -0
  131. data/lib/active_record/dynamic_matchers.rb +107 -69
  132. data/lib/active_record/enum.rb +244 -0
  133. data/lib/active_record/errors.rb +245 -60
  134. data/lib/active_record/explain.rb +35 -71
  135. data/lib/active_record/explain_registry.rb +32 -0
  136. data/lib/active_record/explain_subscriber.rb +18 -9
  137. data/lib/active_record/fixture_set/file.rb +82 -0
  138. data/lib/active_record/fixtures.rb +418 -275
  139. data/lib/active_record/gem_version.rb +17 -0
  140. data/lib/active_record/inheritance.rb +209 -100
  141. data/lib/active_record/integration.rb +116 -21
  142. data/lib/active_record/internal_metadata.rb +45 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  144. data/lib/active_record/locale/en.yml +9 -1
  145. data/lib/active_record/locking/optimistic.rb +107 -94
  146. data/lib/active_record/locking/pessimistic.rb +20 -8
  147. data/lib/active_record/log_subscriber.rb +99 -34
  148. data/lib/active_record/migration/command_recorder.rb +199 -64
  149. data/lib/active_record/migration/compatibility.rb +217 -0
  150. data/lib/active_record/migration/join_table.rb +17 -0
  151. data/lib/active_record/migration.rb +893 -296
  152. data/lib/active_record/model_schema.rb +328 -175
  153. data/lib/active_record/nested_attributes.rb +338 -242
  154. data/lib/active_record/no_touching.rb +58 -0
  155. data/lib/active_record/null_relation.rb +68 -0
  156. data/lib/active_record/persistence.rb +557 -170
  157. data/lib/active_record/query_cache.rb +14 -43
  158. data/lib/active_record/querying.rb +36 -24
  159. data/lib/active_record/railtie.rb +147 -52
  160. data/lib/active_record/railties/console_sandbox.rb +5 -4
  161. data/lib/active_record/railties/controller_runtime.rb +13 -6
  162. data/lib/active_record/railties/databases.rake +206 -488
  163. data/lib/active_record/readonly_attributes.rb +4 -6
  164. data/lib/active_record/reflection.rb +734 -228
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  166. data/lib/active_record/relation/batches.rb +249 -52
  167. data/lib/active_record/relation/calculations.rb +330 -284
  168. data/lib/active_record/relation/delegation.rb +135 -37
  169. data/lib/active_record/relation/finder_methods.rb +450 -287
  170. data/lib/active_record/relation/from_clause.rb +26 -0
  171. data/lib/active_record/relation/merger.rb +193 -0
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  174. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  179. data/lib/active_record/relation/predicate_builder.rb +132 -43
  180. data/lib/active_record/relation/query_attribute.rb +45 -0
  181. data/lib/active_record/relation/query_methods.rb +1037 -221
  182. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  183. data/lib/active_record/relation/spawn_methods.rb +48 -151
  184. data/lib/active_record/relation/where_clause.rb +186 -0
  185. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  186. data/lib/active_record/relation.rb +451 -359
  187. data/lib/active_record/result.rb +129 -20
  188. data/lib/active_record/runtime_registry.rb +24 -0
  189. data/lib/active_record/sanitization.rb +164 -136
  190. data/lib/active_record/schema.rb +31 -19
  191. data/lib/active_record/schema_dumper.rb +154 -107
  192. data/lib/active_record/schema_migration.rb +56 -0
  193. data/lib/active_record/scoping/default.rb +108 -98
  194. data/lib/active_record/scoping/named.rb +125 -112
  195. data/lib/active_record/scoping.rb +77 -123
  196. data/lib/active_record/secure_token.rb +40 -0
  197. data/lib/active_record/serialization.rb +10 -6
  198. data/lib/active_record/statement_cache.rb +121 -0
  199. data/lib/active_record/store.rb +175 -16
  200. data/lib/active_record/suppressor.rb +61 -0
  201. data/lib/active_record/table_metadata.rb +82 -0
  202. data/lib/active_record/tasks/database_tasks.rb +337 -0
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +143 -0
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +83 -0
  206. data/lib/active_record/timestamp.rb +80 -41
  207. data/lib/active_record/touch_later.rb +64 -0
  208. data/lib/active_record/transactions.rb +240 -119
  209. data/lib/active_record/translation.rb +2 -0
  210. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  211. data/lib/active_record/type/date.rb +9 -0
  212. data/lib/active_record/type/date_time.rb +9 -0
  213. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  214. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  215. data/lib/active_record/type/internal/timezone.rb +17 -0
  216. data/lib/active_record/type/json.rb +30 -0
  217. data/lib/active_record/type/serialized.rb +71 -0
  218. data/lib/active_record/type/text.rb +11 -0
  219. data/lib/active_record/type/time.rb +21 -0
  220. data/lib/active_record/type/type_map.rb +62 -0
  221. data/lib/active_record/type/unsigned_integer.rb +17 -0
  222. data/lib/active_record/type.rb +79 -0
  223. data/lib/active_record/type_caster/connection.rb +33 -0
  224. data/lib/active_record/type_caster/map.rb +23 -0
  225. data/lib/active_record/type_caster.rb +9 -0
  226. data/lib/active_record/validations/absence.rb +25 -0
  227. data/lib/active_record/validations/associated.rb +35 -18
  228. data/lib/active_record/validations/length.rb +26 -0
  229. data/lib/active_record/validations/presence.rb +68 -0
  230. data/lib/active_record/validations/uniqueness.rb +133 -75
  231. data/lib/active_record/validations.rb +53 -43
  232. data/lib/active_record/version.rb +7 -7
  233. data/lib/active_record.rb +89 -57
  234. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  235. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  236. data/lib/rails/generators/active_record/migration/migration_generator.rb +61 -8
  237. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  238. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +46 -0
  239. data/lib/rails/generators/active_record/migration.rb +28 -8
  240. data/lib/rails/generators/active_record/model/model_generator.rb +23 -22
  241. data/lib/rails/generators/active_record/model/templates/model.rb.tt +13 -0
  242. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +1 -1
  243. data/lib/rails/generators/active_record.rb +10 -16
  244. metadata +141 -62
  245. data/examples/associations.png +0 -0
  246. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  247. data/lib/active_record/associations/join_helper.rb +0 -55
  248. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  249. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  250. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  251. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  252. data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
  253. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  254. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  255. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  256. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  257. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  258. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -441
  259. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  260. data/lib/active_record/dynamic_finder_match.rb +0 -68
  261. data/lib/active_record/dynamic_scope_match.rb +0 -23
  262. data/lib/active_record/fixtures/file.rb +0 -65
  263. data/lib/active_record/identity_map.rb +0 -162
  264. data/lib/active_record/observer.rb +0 -121
  265. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  266. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  267. data/lib/active_record/session_store.rb +0 -360
  268. data/lib/active_record/test_case.rb +0 -73
  269. data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
  270. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  271. data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
  272. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  273. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  274. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  275. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class Migration
3
5
  # <tt>ActiveRecord::Migration::CommandRecorder</tt> records commands done during
@@ -5,101 +7,234 @@ module ActiveRecord
5
7
  # knows how to invert the following commands:
6
8
  #
7
9
  # * add_column
10
+ # * add_foreign_key
8
11
  # * add_index
12
+ # * add_reference
9
13
  # * add_timestamps
14
+ # * change_column
15
+ # * change_column_default (must supply a :from and :to option)
16
+ # * change_column_null
17
+ # * create_join_table
10
18
  # * create_table
19
+ # * disable_extension
20
+ # * drop_join_table
21
+ # * drop_table (must supply a block)
22
+ # * enable_extension
23
+ # * remove_column (must supply a type)
24
+ # * remove_columns (must specify at least one column name or more)
25
+ # * remove_foreign_key (must supply a second table)
26
+ # * remove_index
27
+ # * remove_reference
11
28
  # * remove_timestamps
12
29
  # * rename_column
13
30
  # * rename_index
14
31
  # * rename_table
15
32
  class CommandRecorder
16
- attr_accessor :commands, :delegate
33
+ ReversibleAndIrreversibleMethods = [:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
34
+ :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
35
+ :change_column_default, :add_reference, :remove_reference, :transaction,
36
+ :drop_join_table, :drop_table, :execute_block, :enable_extension, :disable_extension,
37
+ :change_column, :execute, :remove_columns, :change_column_null,
38
+ :add_foreign_key, :remove_foreign_key
39
+ ]
40
+ include JoinTable
41
+
42
+ attr_accessor :commands, :delegate, :reverting
17
43
 
18
44
  def initialize(delegate = nil)
19
45
  @commands = []
20
46
  @delegate = delegate
47
+ @reverting = false
48
+ end
49
+
50
+ # While executing the given block, the recorded will be in reverting mode.
51
+ # All commands recorded will end up being recorded reverted
52
+ # and in reverse order.
53
+ # For example:
54
+ #
55
+ # recorder.revert{ recorder.record(:rename_table, [:old, :new]) }
56
+ # # same effect as recorder.record(:rename_table, [:new, :old])
57
+ def revert
58
+ @reverting = !@reverting
59
+ previous = @commands
60
+ @commands = []
61
+ yield
62
+ ensure
63
+ @commands = previous.concat(@commands.reverse)
64
+ @reverting = !@reverting
21
65
  end
22
66
 
23
- # record +command+. +command+ should be a method name and arguments.
67
+ # Record +command+. +command+ should be a method name and arguments.
24
68
  # For example:
25
69
  #
26
70
  # recorder.record(:method_name, [:arg1, :arg2])
27
- def record(*command)
28
- @commands << command
71
+ def record(*command, &block)
72
+ if @reverting
73
+ @commands << inverse_of(*command, &block)
74
+ else
75
+ @commands << (command << block)
76
+ end
29
77
  end
30
78
 
31
- # Returns a list that represents commands that are the inverse of the
32
- # commands stored in +commands+. For example:
79
+ # Returns the inverse of the given command. For example:
33
80
  #
34
- # recorder.record(:rename_table, [:old, :new])
35
- # recorder.inverse # => [:rename_table, [:new, :old]]
81
+ # recorder.inverse_of(:rename_table, [:old, :new])
82
+ # # => [:rename_table, [:new, :old]]
36
83
  #
37
84
  # This method will raise an +IrreversibleMigration+ exception if it cannot
38
- # invert the +commands+.
39
- def inverse
40
- @commands.reverse.map { |name, args|
41
- method = :"invert_#{name}"
42
- raise IrreversibleMigration unless respond_to?(method, true)
43
- send(method, args)
44
- }
85
+ # invert the +command+.
86
+ def inverse_of(command, args, &block)
87
+ method = :"invert_#{command}"
88
+ raise IrreversibleMigration, <<-MSG.strip_heredoc unless respond_to?(method, true)
89
+ This migration uses #{command}, which is not automatically reversible.
90
+ To make the migration reversible you can either:
91
+ 1. Define #up and #down methods in place of the #change method.
92
+ 2. Use the #reversible method to define reversible behavior.
93
+ MSG
94
+ send(method, args, &block)
45
95
  end
46
96
 
47
- def respond_to?(*args) # :nodoc:
48
- super || delegate.respond_to?(*args)
49
- end
50
-
51
- [:create_table, :change_table, :rename_table, :add_column, :remove_column, :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps, :change_column, :change_column_default].each do |method|
97
+ ReversibleAndIrreversibleMethods.each do |method|
52
98
  class_eval <<-EOV, __FILE__, __LINE__ + 1
53
- def #{method}(*args) # def create_table(*args)
54
- record(:"#{method}", args) # record(:create_table, args)
55
- end # end
99
+ def #{method}(*args, &block) # def create_table(*args, &block)
100
+ record(:"#{method}", args, &block) # record(:create_table, args, &block)
101
+ end # end
56
102
  EOV
57
103
  end
104
+ alias :add_belongs_to :add_reference
105
+ alias :remove_belongs_to :remove_reference
58
106
 
59
- private
60
-
61
- def invert_create_table(args)
62
- [:drop_table, [args.first]]
107
+ def change_table(table_name, options = {}) # :nodoc:
108
+ yield delegate.update_table_definition(table_name, self)
63
109
  end
64
110
 
65
- def invert_rename_table(args)
66
- [:rename_table, args.reverse]
67
- end
68
-
69
- def invert_add_column(args)
70
- [:remove_column, args.first(2)]
71
- end
72
-
73
- def invert_rename_index(args)
74
- [:rename_index, [args.first] + args.last(2).reverse]
75
- end
76
-
77
- def invert_rename_column(args)
78
- [:rename_column, [args.first] + args.last(2).reverse]
79
- end
80
-
81
- def invert_add_index(args)
82
- table, columns, options = *args
83
- index_name = options.try(:[], :name)
84
- options_hash = index_name ? {:name => index_name} : {:column => columns}
85
- [:remove_index, [table, options_hash]]
86
- end
87
-
88
- def invert_remove_timestamps(args)
89
- [:add_timestamps, args]
90
- end
91
-
92
- def invert_add_timestamps(args)
93
- [:remove_timestamps, args]
94
- end
95
-
96
- # Forwards any missing method call to the \target.
97
- def method_missing(method, *args, &block)
98
- @delegate.send(method, *args, &block)
99
- rescue NoMethodError => e
100
- raise e, e.message.sub(/ for #<.*$/, " via proxy for #{@delegate}")
101
- end
111
+ private
102
112
 
113
+ module StraightReversions # :nodoc:
114
+ private
115
+ { transaction: :transaction,
116
+ execute_block: :execute_block,
117
+ create_table: :drop_table,
118
+ create_join_table: :drop_join_table,
119
+ add_column: :remove_column,
120
+ add_timestamps: :remove_timestamps,
121
+ add_reference: :remove_reference,
122
+ enable_extension: :disable_extension
123
+ }.each do |cmd, inv|
124
+ [[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
125
+ class_eval <<-EOV, __FILE__, __LINE__ + 1
126
+ def invert_#{method}(args, &block) # def invert_create_table(args, &block)
127
+ [:#{inverse}, args, block] # [:drop_table, args, block]
128
+ end # end
129
+ EOV
130
+ end
131
+ end
132
+ end
133
+
134
+ include StraightReversions
135
+
136
+ def invert_drop_table(args, &block)
137
+ if args.size == 1 && block == nil
138
+ raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
139
+ end
140
+ super
141
+ end
142
+
143
+ def invert_rename_table(args)
144
+ [:rename_table, args.reverse]
145
+ end
146
+
147
+ def invert_remove_column(args)
148
+ raise ActiveRecord::IrreversibleMigration, "remove_column is only reversible if given a type." if args.size <= 2
149
+ super
150
+ end
151
+
152
+ def invert_rename_index(args)
153
+ [:rename_index, [args.first] + args.last(2).reverse]
154
+ end
155
+
156
+ def invert_rename_column(args)
157
+ [:rename_column, [args.first] + args.last(2).reverse]
158
+ end
159
+
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]
166
+
167
+ [:remove_index, [table, options_hash]]
168
+ end
169
+
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]]
180
+ end
181
+ end
182
+
183
+ alias :invert_add_belongs_to :invert_add_reference
184
+ alias :invert_remove_belongs_to :invert_remove_reference
185
+
186
+ def invert_change_column_default(args)
187
+ table, column, options = *args
188
+
189
+ unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
190
+ raise ActiveRecord::IrreversibleMigration, "change_column_default is only reversible if given a :from and :to option."
191
+ end
192
+
193
+ [:change_column_default, [table, column, from: options[:to], to: options[:from]]]
194
+ end
195
+
196
+ def invert_change_column_null(args)
197
+ args[2] = !args[2]
198
+ [:change_column_null, args]
199
+ end
200
+
201
+ def invert_add_foreign_key(args)
202
+ from_table, to_table, add_options = args
203
+ add_options ||= {}
204
+
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
211
+ end
212
+
213
+ [:remove_foreign_key, [from_table, options]]
214
+ end
215
+
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)
219
+
220
+ reversed_args = [from_table, to_table]
221
+ reversed_args << remove_options if remove_options
222
+
223
+ [:add_foreign_key, reversed_args]
224
+ end
225
+
226
+ def respond_to_missing?(method, _)
227
+ super || delegate.respond_to?(method)
228
+ end
229
+
230
+ # Forwards any missing method call to the \target.
231
+ def method_missing(method, *args, &block)
232
+ if delegate.respond_to?(method)
233
+ delegate.public_send(method, *args, &block)
234
+ else
235
+ super
236
+ end
237
+ end
103
238
  end
104
239
  end
105
240
  end
@@ -0,0 +1,217 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class Migration
5
+ module Compatibility # :nodoc: all
6
+ def self.find(version)
7
+ version = version.to_s
8
+ name = "V#{version.tr('.', '_')}"
9
+ unless const_defined?(name)
10
+ versions = constants.grep(/\AV[0-9_]+\z/).map { |s| s.to_s.delete("V").tr("_", ".").inspect }
11
+ raise ArgumentError, "Unknown migration version #{version.inspect}; expected one of #{versions.sort.join(', ')}"
12
+ end
13
+ const_get(name)
14
+ end
15
+
16
+ V5_2 = Current
17
+
18
+ class V5_1 < V5_2
19
+ def change_column(table_name, column_name, type, options = {})
20
+ if connection.adapter_name == "PostgreSQL"
21
+ super(table_name, column_name, type, options.except(:default, :null, :comment))
22
+ connection.change_column_default(table_name, column_name, options[:default]) if options.key?(:default)
23
+ connection.change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
24
+ connection.change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
25
+ else
26
+ super
27
+ end
28
+ end
29
+
30
+ def create_table(table_name, options = {})
31
+ if connection.adapter_name == "Mysql2"
32
+ super(table_name, options: "ENGINE=InnoDB", **options)
33
+ else
34
+ super
35
+ end
36
+ end
37
+ end
38
+
39
+ class V5_0 < V5_1
40
+ module TableDefinition
41
+ def primary_key(name, type = :primary_key, **options)
42
+ type = :integer if type == :primary_key
43
+ super
44
+ end
45
+
46
+ def references(*args, **options)
47
+ super(*args, type: :integer, **options)
48
+ end
49
+ alias :belongs_to :references
50
+ end
51
+
52
+ def create_table(table_name, options = {})
53
+ if connection.adapter_name == "PostgreSQL"
54
+ if options[:id] == :uuid && !options.key?(:default)
55
+ options[:default] = "uuid_generate_v4()"
56
+ end
57
+ end
58
+
59
+ unless connection.adapter_name == "Mysql2" && options[:id] == :bigint
60
+ if [:integer, :bigint].include?(options[:id]) && !options.key?(:default)
61
+ options[:default] = nil
62
+ end
63
+ end
64
+
65
+ # Since 5.1 PostgreSQL adapter uses bigserial type for primary
66
+ # keys by default and MySQL uses bigint. This compat layer makes old migrations utilize
67
+ # serial/int type instead -- the way it used to work before 5.1.
68
+ unless options.key?(:id)
69
+ options[:id] = :integer
70
+ end
71
+
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
89
+ end
90
+
91
+ def create_join_table(table_1, table_2, column_options: {}, **options)
92
+ 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
101
+ end
102
+
103
+ def add_column(table_name, column_name, type, options = {})
104
+ if type == :primary_key
105
+ type = :integer
106
+ options[:primary_key] = true
107
+ end
108
+ super
109
+ end
110
+
111
+ def add_reference(table_name, ref_name, **options)
112
+ super(table_name, ref_name, type: :integer, **options)
113
+ end
114
+ alias :add_belongs_to :add_reference
115
+
116
+ private
117
+ def compatible_table_definition(t)
118
+ class << t
119
+ prepend TableDefinition
120
+ end
121
+ t
122
+ end
123
+ end
124
+
125
+ class V4_2 < V5_0
126
+ module TableDefinition
127
+ def references(*, **options)
128
+ options[:index] ||= false
129
+ super
130
+ end
131
+ alias :belongs_to :references
132
+
133
+ def timestamps(**options)
134
+ options[:null] = true if options[:null].nil?
135
+ super
136
+ end
137
+ end
138
+
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)
160
+ options[:index] ||= false
161
+ super
162
+ end
163
+ alias :add_belongs_to :add_reference
164
+
165
+ def add_timestamps(_, **options)
166
+ options[:null] = true if options[:null].nil?
167
+ super
168
+ end
169
+
170
+ def index_exists?(table_name, column_name, options = {})
171
+ column_names = Array(column_name).map(&:to_s)
172
+ options[:name] =
173
+ if options[:name].present?
174
+ options[:name].to_s
175
+ else
176
+ connection.index_name(table_name, column: column_names)
177
+ end
178
+ super
179
+ end
180
+
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)
185
+ end
186
+
187
+ private
188
+ def compatible_table_definition(t)
189
+ class << t
190
+ prepend TableDefinition
191
+ end
192
+ super
193
+ end
194
+
195
+ def index_name_for_remove(table_name, options = {})
196
+ index_name = connection.index_name(table_name, options)
197
+
198
+ 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
202
+ index_name_without_column = connection.index_name(table_name, options_without_column)
203
+
204
+ if connection.index_name_exists?(table_name, index_name_without_column)
205
+ return index_name_without_column
206
+ end
207
+ end
208
+
209
+ raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
210
+ end
211
+
212
+ index_name
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class Migration
5
+ module JoinTable #:nodoc:
6
+ private
7
+
8
+ def find_join_table_name(table_1, table_2, options = {})
9
+ options.delete(:table_name) || join_table_name(table_1, table_2)
10
+ end
11
+
12
+ def join_table_name(table_1, table_2)
13
+ ModelSchema.derive_join_table_name(table_1, table_2).to_sym
14
+ end
15
+ end
16
+ end
17
+ end