activerecord 4.2.11.3 → 5.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 (246) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1281 -1204
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -8
  5. data/examples/performance.rb +2 -3
  6. data/examples/simple.rb +0 -1
  7. data/lib/active_record/aggregations.rb +35 -24
  8. data/lib/active_record/association_relation.rb +3 -3
  9. data/lib/active_record/associations/alias_tracker.rb +19 -16
  10. data/lib/active_record/associations/association.rb +11 -9
  11. data/lib/active_record/associations/association_scope.rb +73 -102
  12. data/lib/active_record/associations/belongs_to_association.rb +21 -32
  13. data/lib/active_record/associations/builder/association.rb +28 -34
  14. data/lib/active_record/associations/builder/belongs_to.rb +43 -18
  15. data/lib/active_record/associations/builder/collection_association.rb +7 -19
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
  17. data/lib/active_record/associations/builder/has_many.rb +4 -4
  18. data/lib/active_record/associations/builder/has_one.rb +11 -6
  19. data/lib/active_record/associations/builder/singular_association.rb +3 -10
  20. data/lib/active_record/associations/collection_association.rb +49 -41
  21. data/lib/active_record/associations/collection_proxy.rb +67 -27
  22. data/lib/active_record/associations/foreign_association.rb +1 -1
  23. data/lib/active_record/associations/has_many_association.rb +20 -71
  24. data/lib/active_record/associations/has_many_through_association.rb +8 -47
  25. data/lib/active_record/associations/has_one_association.rb +12 -5
  26. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  27. data/lib/active_record/associations/join_dependency.rb +29 -19
  28. data/lib/active_record/associations/preloader/association.rb +46 -52
  29. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  30. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  31. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  32. data/lib/active_record/associations/preloader/through_association.rb +27 -14
  33. data/lib/active_record/associations/preloader.rb +14 -4
  34. data/lib/active_record/associations/singular_association.rb +7 -1
  35. data/lib/active_record/associations/through_association.rb +11 -3
  36. data/lib/active_record/associations.rb +317 -209
  37. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  38. data/lib/active_record/attribute.rb +68 -18
  39. data/lib/active_record/attribute_assignment.rb +19 -140
  40. data/lib/active_record/attribute_decorators.rb +6 -5
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  42. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  43. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  44. data/lib/active_record/attribute_methods/query.rb +2 -2
  45. data/lib/active_record/attribute_methods/read.rb +31 -59
  46. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
  48. data/lib/active_record/attribute_methods/write.rb +13 -37
  49. data/lib/active_record/attribute_methods.rb +76 -47
  50. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  51. data/lib/active_record/attribute_set/builder.rb +6 -4
  52. data/lib/active_record/attribute_set.rb +30 -3
  53. data/lib/active_record/attributes.rb +199 -81
  54. data/lib/active_record/autosave_association.rb +49 -16
  55. data/lib/active_record/base.rb +32 -23
  56. data/lib/active_record/callbacks.rb +39 -43
  57. data/lib/active_record/coders/json.rb +1 -1
  58. data/lib/active_record/coders/yaml_column.rb +20 -8
  59. data/lib/active_record/collection_cache_key.rb +40 -0
  60. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
  61. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  62. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
  63. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
  64. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
  65. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  66. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  67. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
  68. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  69. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +380 -141
  70. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  71. data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
  72. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
  73. data/lib/active_record/connection_adapters/column.rb +28 -43
  74. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  75. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  76. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  77. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  78. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  79. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  81. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  82. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  83. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  84. data/lib/active_record/connection_adapters/mysql2_adapter.rb +29 -166
  85. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  86. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
  87. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -57
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  98. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  100. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  101. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  102. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  105. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  106. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  107. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  108. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  109. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
  110. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  111. data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
  112. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  113. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  114. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  115. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  116. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  117. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +149 -192
  118. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  119. data/lib/active_record/connection_handling.rb +37 -14
  120. data/lib/active_record/core.rb +89 -107
  121. data/lib/active_record/counter_cache.rb +13 -24
  122. data/lib/active_record/dynamic_matchers.rb +1 -20
  123. data/lib/active_record/enum.rb +113 -76
  124. data/lib/active_record/errors.rb +87 -48
  125. data/lib/active_record/explain_registry.rb +1 -1
  126. data/lib/active_record/explain_subscriber.rb +1 -1
  127. data/lib/active_record/fixture_set/file.rb +26 -5
  128. data/lib/active_record/fixtures.rb +76 -40
  129. data/lib/active_record/gem_version.rb +4 -4
  130. data/lib/active_record/inheritance.rb +32 -40
  131. data/lib/active_record/integration.rb +4 -4
  132. data/lib/active_record/internal_metadata.rb +56 -0
  133. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  134. data/lib/active_record/locale/en.yml +3 -2
  135. data/lib/active_record/locking/optimistic.rb +15 -15
  136. data/lib/active_record/locking/pessimistic.rb +1 -1
  137. data/lib/active_record/log_subscriber.rb +43 -21
  138. data/lib/active_record/migration/command_recorder.rb +59 -18
  139. data/lib/active_record/migration/compatibility.rb +126 -0
  140. data/lib/active_record/migration.rb +363 -133
  141. data/lib/active_record/model_schema.rb +129 -41
  142. data/lib/active_record/nested_attributes.rb +58 -29
  143. data/lib/active_record/null_relation.rb +16 -8
  144. data/lib/active_record/persistence.rb +121 -80
  145. data/lib/active_record/query_cache.rb +15 -18
  146. data/lib/active_record/querying.rb +10 -9
  147. data/lib/active_record/railtie.rb +23 -16
  148. data/lib/active_record/railties/controller_runtime.rb +1 -1
  149. data/lib/active_record/railties/databases.rake +69 -46
  150. data/lib/active_record/readonly_attributes.rb +1 -1
  151. data/lib/active_record/reflection.rb +282 -115
  152. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  153. data/lib/active_record/relation/batches.rb +139 -34
  154. data/lib/active_record/relation/calculations.rb +79 -108
  155. data/lib/active_record/relation/delegation.rb +7 -20
  156. data/lib/active_record/relation/finder_methods.rb +163 -81
  157. data/lib/active_record/relation/from_clause.rb +32 -0
  158. data/lib/active_record/relation/merger.rb +16 -42
  159. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  160. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  161. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  162. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  163. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  164. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  165. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  166. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  167. data/lib/active_record/relation/predicate_builder.rb +120 -107
  168. data/lib/active_record/relation/query_attribute.rb +19 -0
  169. data/lib/active_record/relation/query_methods.rb +308 -244
  170. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  171. data/lib/active_record/relation/spawn_methods.rb +4 -7
  172. data/lib/active_record/relation/where_clause.rb +174 -0
  173. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  174. data/lib/active_record/relation.rb +176 -116
  175. data/lib/active_record/result.rb +4 -3
  176. data/lib/active_record/runtime_registry.rb +1 -1
  177. data/lib/active_record/sanitization.rb +95 -66
  178. data/lib/active_record/schema.rb +26 -22
  179. data/lib/active_record/schema_dumper.rb +62 -38
  180. data/lib/active_record/schema_migration.rb +11 -14
  181. data/lib/active_record/scoping/default.rb +23 -9
  182. data/lib/active_record/scoping/named.rb +49 -28
  183. data/lib/active_record/scoping.rb +32 -15
  184. data/lib/active_record/secure_token.rb +38 -0
  185. data/lib/active_record/serialization.rb +2 -4
  186. data/lib/active_record/statement_cache.rb +16 -14
  187. data/lib/active_record/store.rb +8 -3
  188. data/lib/active_record/suppressor.rb +58 -0
  189. data/lib/active_record/table_metadata.rb +68 -0
  190. data/lib/active_record/tasks/database_tasks.rb +57 -43
  191. data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
  192. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  193. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  194. data/lib/active_record/timestamp.rb +20 -9
  195. data/lib/active_record/touch_later.rb +58 -0
  196. data/lib/active_record/transactions.rb +138 -56
  197. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  198. data/lib/active_record/type/date.rb +2 -45
  199. data/lib/active_record/type/date_time.rb +2 -49
  200. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  201. data/lib/active_record/type/internal/timezone.rb +15 -0
  202. data/lib/active_record/type/serialized.rb +15 -14
  203. data/lib/active_record/type/time.rb +10 -16
  204. data/lib/active_record/type/type_map.rb +4 -4
  205. data/lib/active_record/type.rb +66 -17
  206. data/lib/active_record/type_caster/connection.rb +29 -0
  207. data/lib/active_record/type_caster/map.rb +19 -0
  208. data/lib/active_record/type_caster.rb +7 -0
  209. data/lib/active_record/validations/absence.rb +23 -0
  210. data/lib/active_record/validations/associated.rb +10 -3
  211. data/lib/active_record/validations/length.rb +24 -0
  212. data/lib/active_record/validations/presence.rb +11 -12
  213. data/lib/active_record/validations/uniqueness.rb +30 -29
  214. data/lib/active_record/validations.rb +33 -32
  215. data/lib/active_record.rb +8 -4
  216. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  217. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  218. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  219. data/lib/rails/generators/active_record/migration.rb +7 -0
  220. data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
  221. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  222. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  223. metadata +59 -34
  224. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  225. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  226. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  227. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  228. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  229. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  230. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  231. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  232. data/lib/active_record/type/big_integer.rb +0 -13
  233. data/lib/active_record/type/binary.rb +0 -50
  234. data/lib/active_record/type/boolean.rb +0 -31
  235. data/lib/active_record/type/decimal.rb +0 -64
  236. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  237. data/lib/active_record/type/decorator.rb +0 -14
  238. data/lib/active_record/type/float.rb +0 -19
  239. data/lib/active_record/type/integer.rb +0 -59
  240. data/lib/active_record/type/mutable.rb +0 -16
  241. data/lib/active_record/type/numeric.rb +0 -36
  242. data/lib/active_record/type/string.rb +0 -40
  243. data/lib/active_record/type/text.rb +0 -11
  244. data/lib/active_record/type/time_value.rb +0 -38
  245. data/lib/active_record/type/unsigned_integer.rb +0 -15
  246. data/lib/active_record/type/value.rb +0 -110
@@ -20,24 +20,25 @@ module ActiveRecord
20
20
  @odd = false
21
21
  end
22
22
 
23
- def render_bind(column, value)
24
- if column
25
- if column.binary?
26
- # This specifically deals with the PG adapter that casts bytea columns into a Hash.
27
- value = value[:value] if value.is_a?(Hash)
28
- value = value ? "<#{value.bytesize} bytes of binary data>" : "<NULL binary data>"
23
+ def render_bind(attribute)
24
+ value = if attribute.type.binary? && attribute.value
25
+ if attribute.value.is_a?(Hash)
26
+ "<#{attribute.value_for_database.to_s.bytesize} bytes of binary data>"
27
+ else
28
+ "<#{attribute.value.bytesize} bytes of binary data>"
29
29
  end
30
-
31
- [column.name, value]
32
30
  else
33
- [nil, value]
31
+ attribute.value_for_database
34
32
  end
33
+
34
+ [attribute.name, value]
35
35
  end
36
36
 
37
37
  def sql(event)
38
- self.class.runtime += event.duration
39
38
  return unless logger.debug?
40
39
 
40
+ self.class.runtime += event.duration
41
+
41
42
  payload = event.payload
42
43
 
43
44
  return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
@@ -47,23 +48,44 @@ module ActiveRecord
47
48
  binds = nil
48
49
 
49
50
  unless (payload[:binds] || []).empty?
50
- binds = " " + payload[:binds].map { |col,v|
51
- render_bind(col, v)
52
- }.inspect
51
+ binds = " " + payload[:binds].map { |attr| render_bind(attr) }.inspect
53
52
  end
54
53
 
55
- if odd?
56
- name = color(name, CYAN, true)
57
- sql = color(sql, nil, true)
58
- else
59
- name = color(name, MAGENTA, true)
60
- end
54
+ name = colorize_payload_name(name, payload[:name])
55
+ sql = color(sql, sql_color(sql), true)
61
56
 
62
57
  debug " #{name} #{sql}#{binds}"
63
58
  end
64
59
 
65
- def odd?
66
- @odd = !@odd
60
+ private
61
+
62
+ def colorize_payload_name(name, payload_name)
63
+ if payload_name.blank? || payload_name == "SQL" # SQL vs Model Load/Exists
64
+ color(name, MAGENTA, true)
65
+ else
66
+ color(name, CYAN, true)
67
+ end
68
+ end
69
+
70
+ def sql_color(sql)
71
+ case sql
72
+ when /\A\s*rollback/mi
73
+ RED
74
+ when /select .*for update/mi, /\A\s*lock/mi
75
+ WHITE
76
+ when /\A\s*select/i
77
+ BLUE
78
+ when /\A\s*insert/i
79
+ GREEN
80
+ when /\A\s*update/i
81
+ YELLOW
82
+ when /\A\s*delete/i
83
+ RED
84
+ when /transaction\s*\Z/i
85
+ CYAN
86
+ else
87
+ MAGENTA
88
+ end
67
89
  end
68
90
 
69
91
  def logger
@@ -5,15 +5,36 @@ module ActiveRecord
5
5
  # knows how to invert the following commands:
6
6
  #
7
7
  # * add_column
8
+ # * add_foreign_key
8
9
  # * add_index
10
+ # * add_reference
9
11
  # * add_timestamps
10
- # * create_table
12
+ # * change_column
13
+ # * change_column_default (must supply a :from and :to option)
14
+ # * change_column_null
11
15
  # * create_join_table
16
+ # * create_table
17
+ # * disable_extension
18
+ # * drop_join_table
19
+ # * drop_table (must supply a block)
20
+ # * enable_extension
21
+ # * remove_column (must supply a type)
22
+ # * remove_columns (must specify at least one column name or more)
23
+ # * remove_foreign_key (must supply a second table)
24
+ # * remove_index
25
+ # * remove_reference
12
26
  # * remove_timestamps
13
27
  # * rename_column
14
28
  # * rename_index
15
29
  # * rename_table
16
30
  class CommandRecorder
31
+ ReversibleAndIrreversibleMethods = [:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
32
+ :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
33
+ :change_column_default, :add_reference, :remove_reference, :transaction,
34
+ :drop_join_table, :drop_table, :execute_block, :enable_extension, :disable_extension,
35
+ :change_column, :execute, :remove_columns, :change_column_null,
36
+ :add_foreign_key, :remove_foreign_key
37
+ ]
17
38
  include JoinTable
18
39
 
19
40
  attr_accessor :commands, :delegate, :reverting
@@ -41,7 +62,7 @@ module ActiveRecord
41
62
  @reverting = !@reverting
42
63
  end
43
64
 
44
- # record +command+. +command+ should be a method name and arguments.
65
+ # Record +command+. +command+ should be a method name and arguments.
45
66
  # For example:
46
67
  #
47
68
  # recorder.record(:method_name, [:arg1, :arg2])
@@ -62,7 +83,12 @@ module ActiveRecord
62
83
  # invert the +command+.
63
84
  def inverse_of(command, args, &block)
64
85
  method = :"invert_#{command}"
65
- raise IrreversibleMigration unless respond_to?(method, true)
86
+ raise IrreversibleMigration, <<-MSG.strip_heredoc unless respond_to?(method, true)
87
+ This migration uses #{command}, which is not automatically reversible.
88
+ To make the migration reversible you can either:
89
+ 1. Define #up and #down methods in place of the #change method.
90
+ 2. Use the #reversible method to define reversible behavior.
91
+ MSG
66
92
  send(method, args, &block)
67
93
  end
68
94
 
@@ -70,14 +96,7 @@ module ActiveRecord
70
96
  super || delegate.respond_to?(*args)
71
97
  end
72
98
 
73
- [:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
74
- :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
75
- :change_column_default, :add_reference, :remove_reference, :transaction,
76
- :drop_join_table, :drop_table, :execute_block, :enable_extension,
77
- :change_column, :execute, :remove_columns, :change_column_null,
78
- :add_foreign_key, :remove_foreign_key
79
- # irreversible methods need to be here too
80
- ].each do |method|
99
+ ReversibleAndIrreversibleMethods.each do |method|
81
100
  class_eval <<-EOV, __FILE__, __LINE__ + 1
82
101
  def #{method}(*args, &block) # def create_table(*args, &block)
83
102
  record(:"#{method}", args, &block) # record(:create_table, args, &block)
@@ -151,19 +170,31 @@ module ActiveRecord
151
170
  end
152
171
 
153
172
  def invert_remove_index(args)
154
- table, options = *args
155
-
156
- unless options && options.is_a?(Hash) && options[:column]
157
- raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
173
+ table, options_or_column = *args
174
+ if (options = options_or_column).is_a?(Hash)
175
+ unless options[:column]
176
+ raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
177
+ end
178
+ options = options.dup
179
+ [:add_index, [table, options.delete(:column), options]]
180
+ elsif (column = options_or_column).present?
181
+ [:add_index, [table, column]]
158
182
  end
159
-
160
- options = options.dup
161
- [:add_index, [table, options.delete(:column), options]]
162
183
  end
163
184
 
164
185
  alias :invert_add_belongs_to :invert_add_reference
165
186
  alias :invert_remove_belongs_to :invert_remove_reference
166
187
 
188
+ def invert_change_column_default(args)
189
+ table, column, options = *args
190
+
191
+ unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
192
+ raise ActiveRecord::IrreversibleMigration, "change_column_default is only reversible if given a :from and :to option."
193
+ end
194
+
195
+ [:change_column_default, [table, column, from: options[:to], to: options[:from]]]
196
+ end
197
+
167
198
  def invert_change_column_null(args)
168
199
  args[2] = !args[2]
169
200
  [:change_column_null, args]
@@ -184,6 +215,16 @@ module ActiveRecord
184
215
  [:remove_foreign_key, [from_table, options]]
185
216
  end
186
217
 
218
+ def invert_remove_foreign_key(args)
219
+ from_table, to_table, remove_options = args
220
+ raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil? || to_table.is_a?(Hash)
221
+
222
+ reversed_args = [from_table, to_table]
223
+ reversed_args << remove_options if remove_options
224
+
225
+ [:add_foreign_key, reversed_args]
226
+ end
227
+
187
228
  # Forwards any missing method call to the \target.
188
229
  def method_missing(method, *args, &block)
189
230
  if @delegate.respond_to?(method)
@@ -0,0 +1,126 @@
1
+ module ActiveRecord
2
+ class Migration
3
+ module Compatibility # :nodoc: all
4
+ def self.find(version)
5
+ version = version.to_s
6
+ name = "V#{version.tr('.', '_')}"
7
+ unless const_defined?(name)
8
+ versions = constants.grep(/\AV[0-9_]+\z/).map { |s| s.to_s.delete('V').tr('_', '.').inspect }
9
+ raise ArgumentError, "Unknown migration version #{version.inspect}; expected one of #{versions.sort.join(', ')}"
10
+ end
11
+ const_get(name)
12
+ end
13
+
14
+ V5_0 = Current
15
+
16
+ module FourTwoShared
17
+ module TableDefinition
18
+ def references(*, **options)
19
+ options[:index] ||= false
20
+ super
21
+ end
22
+ alias :belongs_to :references
23
+
24
+ def timestamps(*, **options)
25
+ options[:null] = true if options[:null].nil?
26
+ super
27
+ end
28
+ end
29
+
30
+ def create_table(table_name, options = {})
31
+ if block_given?
32
+ super(table_name, options) do |t|
33
+ class << t
34
+ prepend TableDefinition
35
+ end
36
+ yield t
37
+ end
38
+ else
39
+ super
40
+ end
41
+ end
42
+
43
+ def change_table(table_name, options = {})
44
+ if block_given?
45
+ super(table_name, options) do |t|
46
+ class << t
47
+ prepend TableDefinition
48
+ end
49
+ yield t
50
+ end
51
+ else
52
+ super
53
+ end
54
+ end
55
+
56
+ def add_reference(*, **options)
57
+ options[:index] ||= false
58
+ super
59
+ end
60
+ alias :add_belongs_to :add_reference
61
+
62
+ def add_timestamps(*, **options)
63
+ options[:null] = true if options[:null].nil?
64
+ super
65
+ end
66
+
67
+ def index_exists?(table_name, column_name, options = {})
68
+ column_names = Array(column_name).map(&:to_s)
69
+ options[:name] =
70
+ if options[:name].present?
71
+ options[:name].to_s
72
+ else
73
+ index_name(table_name, column: column_names)
74
+ end
75
+ super
76
+ end
77
+
78
+ def remove_index(table_name, options = {})
79
+ options = { column: options } unless options.is_a?(Hash)
80
+ options[:name] = index_name_for_remove(table_name, options)
81
+ super(table_name, options)
82
+ end
83
+
84
+ private
85
+
86
+ def index_name_for_remove(table_name, options = {})
87
+ index_name = index_name(table_name, options)
88
+
89
+ unless index_name_exists?(table_name, index_name, true)
90
+ if options.is_a?(Hash) && options.has_key?(:name)
91
+ options_without_column = options.dup
92
+ options_without_column.delete :column
93
+ index_name_without_column = index_name(table_name, options_without_column)
94
+
95
+ return index_name_without_column if index_name_exists?(table_name, index_name_without_column, false)
96
+ end
97
+
98
+ raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
99
+ end
100
+
101
+ index_name
102
+ end
103
+ end
104
+
105
+ class V4_2 < V5_0
106
+ # 4.2 is defined as a module because it needs to be shared with
107
+ # Legacy. When the time comes, V5_0 should be defined straight
108
+ # in its class.
109
+ include FourTwoShared
110
+ end
111
+
112
+ module Legacy
113
+ include FourTwoShared
114
+
115
+ def migrate(*)
116
+ ActiveSupport::Deprecation.warn \
117
+ "Directly inheriting from ActiveRecord::Migration is deprecated. " \
118
+ "Please specify the Rails release the migration was written for:\n" \
119
+ "\n" \
120
+ " class #{self.class.name} < ActiveRecord::Migration[4.2]"
121
+ super
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end