activerecord 4.2.0 → 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 (249) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1537 -789
  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 +37 -23
  8. data/lib/active_record/association_relation.rb +16 -3
  9. data/lib/active_record/associations/alias_tracker.rb +19 -16
  10. data/lib/active_record/associations/association.rb +23 -9
  11. data/lib/active_record/associations/association_scope.rb +74 -102
  12. data/lib/active_record/associations/belongs_to_association.rb +26 -29
  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 +12 -20
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +22 -15
  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 +61 -33
  21. data/lib/active_record/associations/collection_proxy.rb +81 -35
  22. data/lib/active_record/associations/foreign_association.rb +11 -0
  23. data/lib/active_record/associations/has_many_association.rb +21 -57
  24. data/lib/active_record/associations/has_many_through_association.rb +15 -45
  25. data/lib/active_record/associations/has_one_association.rb +13 -5
  26. data/lib/active_record/associations/join_dependency/join_association.rb +20 -8
  27. data/lib/active_record/associations/join_dependency.rb +37 -21
  28. data/lib/active_record/associations/preloader/association.rb +51 -53
  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 +18 -8
  34. data/lib/active_record/associations/singular_association.rb +8 -8
  35. data/lib/active_record/associations/through_association.rb +22 -9
  36. data/lib/active_record/associations.rb +321 -212
  37. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  38. data/lib/active_record/attribute.rb +79 -15
  39. data/lib/active_record/attribute_assignment.rb +20 -141
  40. data/lib/active_record/attribute_decorators.rb +6 -5
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +6 -1
  42. data/lib/active_record/attribute_methods/dirty.rb +51 -81
  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 +65 -14
  48. data/lib/active_record/attribute_methods/write.rb +14 -38
  49. data/lib/active_record/attribute_methods.rb +70 -45
  50. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  51. data/lib/active_record/attribute_set/builder.rb +37 -15
  52. data/lib/active_record/attribute_set.rb +34 -3
  53. data/lib/active_record/attributes.rb +199 -73
  54. data/lib/active_record/autosave_association.rb +73 -25
  55. data/lib/active_record/base.rb +35 -27
  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 +457 -181
  61. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  62. data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -59
  63. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -3
  64. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -9
  65. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -4
  66. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  67. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +246 -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 +438 -136
  70. data/lib/active_record/connection_adapters/abstract/transaction.rb +53 -40
  71. data/lib/active_record/connection_adapters/abstract_adapter.rb +166 -66
  72. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +429 -335
  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 +26 -177
  85. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  86. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +11 -73
  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 -56
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -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 -13
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  95. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  98. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  99. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  101. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +17 -5
  102. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  103. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  106. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  107. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  108. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  109. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +248 -154
  111. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  112. data/lib/active_record/connection_adapters/postgresql_adapter.rb +258 -170
  113. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  114. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  115. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  116. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  117. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +150 -209
  119. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  120. data/lib/active_record/connection_handling.rb +38 -15
  121. data/lib/active_record/core.rb +109 -114
  122. data/lib/active_record/counter_cache.rb +14 -25
  123. data/lib/active_record/dynamic_matchers.rb +1 -20
  124. data/lib/active_record/enum.rb +115 -79
  125. data/lib/active_record/errors.rb +88 -48
  126. data/lib/active_record/explain_registry.rb +1 -1
  127. data/lib/active_record/explain_subscriber.rb +2 -2
  128. data/lib/active_record/fixture_set/file.rb +26 -5
  129. data/lib/active_record/fixtures.rb +84 -46
  130. data/lib/active_record/gem_version.rb +2 -2
  131. data/lib/active_record/inheritance.rb +32 -40
  132. data/lib/active_record/integration.rb +4 -4
  133. data/lib/active_record/internal_metadata.rb +56 -0
  134. data/lib/active_record/legacy_yaml_adapter.rb +46 -0
  135. data/lib/active_record/locale/en.yml +3 -2
  136. data/lib/active_record/locking/optimistic.rb +27 -25
  137. data/lib/active_record/locking/pessimistic.rb +1 -1
  138. data/lib/active_record/log_subscriber.rb +43 -21
  139. data/lib/active_record/migration/command_recorder.rb +59 -18
  140. data/lib/active_record/migration/compatibility.rb +126 -0
  141. data/lib/active_record/migration.rb +372 -114
  142. data/lib/active_record/model_schema.rb +128 -38
  143. data/lib/active_record/nested_attributes.rb +71 -32
  144. data/lib/active_record/no_touching.rb +1 -1
  145. data/lib/active_record/null_relation.rb +16 -8
  146. data/lib/active_record/persistence.rb +124 -80
  147. data/lib/active_record/query_cache.rb +15 -18
  148. data/lib/active_record/querying.rb +10 -9
  149. data/lib/active_record/railtie.rb +28 -19
  150. data/lib/active_record/railties/controller_runtime.rb +1 -1
  151. data/lib/active_record/railties/databases.rake +67 -51
  152. data/lib/active_record/readonly_attributes.rb +1 -1
  153. data/lib/active_record/reflection.rb +318 -139
  154. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  155. data/lib/active_record/relation/batches.rb +139 -34
  156. data/lib/active_record/relation/calculations.rb +80 -102
  157. data/lib/active_record/relation/delegation.rb +7 -20
  158. data/lib/active_record/relation/finder_methods.rb +167 -97
  159. data/lib/active_record/relation/from_clause.rb +32 -0
  160. data/lib/active_record/relation/merger.rb +38 -41
  161. data/lib/active_record/relation/predicate_builder/array_handler.rb +12 -16
  162. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  163. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  164. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  165. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  166. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  167. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  168. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  169. data/lib/active_record/relation/predicate_builder.rb +124 -82
  170. data/lib/active_record/relation/query_attribute.rb +19 -0
  171. data/lib/active_record/relation/query_methods.rb +323 -257
  172. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  173. data/lib/active_record/relation/spawn_methods.rb +11 -10
  174. data/lib/active_record/relation/where_clause.rb +174 -0
  175. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  176. data/lib/active_record/relation.rb +176 -115
  177. data/lib/active_record/result.rb +4 -3
  178. data/lib/active_record/runtime_registry.rb +1 -1
  179. data/lib/active_record/sanitization.rb +95 -66
  180. data/lib/active_record/schema.rb +26 -22
  181. data/lib/active_record/schema_dumper.rb +62 -38
  182. data/lib/active_record/schema_migration.rb +11 -17
  183. data/lib/active_record/scoping/default.rb +24 -9
  184. data/lib/active_record/scoping/named.rb +49 -28
  185. data/lib/active_record/scoping.rb +32 -15
  186. data/lib/active_record/secure_token.rb +38 -0
  187. data/lib/active_record/serialization.rb +2 -4
  188. data/lib/active_record/statement_cache.rb +16 -14
  189. data/lib/active_record/store.rb +8 -3
  190. data/lib/active_record/suppressor.rb +58 -0
  191. data/lib/active_record/table_metadata.rb +68 -0
  192. data/lib/active_record/tasks/database_tasks.rb +59 -42
  193. data/lib/active_record/tasks/mysql_database_tasks.rb +32 -26
  194. data/lib/active_record/tasks/postgresql_database_tasks.rb +29 -9
  195. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  196. data/lib/active_record/timestamp.rb +20 -9
  197. data/lib/active_record/touch_later.rb +58 -0
  198. data/lib/active_record/transactions.rb +159 -67
  199. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  200. data/lib/active_record/type/date.rb +2 -41
  201. data/lib/active_record/type/date_time.rb +2 -38
  202. data/lib/active_record/type/hash_lookup_type_map.rb +8 -2
  203. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  204. data/lib/active_record/type/internal/timezone.rb +15 -0
  205. data/lib/active_record/type/serialized.rb +21 -14
  206. data/lib/active_record/type/time.rb +10 -16
  207. data/lib/active_record/type/type_map.rb +4 -4
  208. data/lib/active_record/type.rb +66 -17
  209. data/lib/active_record/type_caster/connection.rb +29 -0
  210. data/lib/active_record/type_caster/map.rb +19 -0
  211. data/lib/active_record/type_caster.rb +7 -0
  212. data/lib/active_record/validations/absence.rb +23 -0
  213. data/lib/active_record/validations/associated.rb +10 -3
  214. data/lib/active_record/validations/length.rb +24 -0
  215. data/lib/active_record/validations/presence.rb +11 -12
  216. data/lib/active_record/validations/uniqueness.rb +29 -18
  217. data/lib/active_record/validations.rb +33 -32
  218. data/lib/active_record.rb +9 -2
  219. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  220. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -6
  221. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -7
  222. data/lib/rails/generators/active_record/migration.rb +7 -0
  223. data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
  224. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  225. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  226. metadata +60 -34
  227. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  228. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  229. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  230. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  231. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  232. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  233. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  234. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  235. data/lib/active_record/type/big_integer.rb +0 -13
  236. data/lib/active_record/type/binary.rb +0 -50
  237. data/lib/active_record/type/boolean.rb +0 -30
  238. data/lib/active_record/type/decimal.rb +0 -40
  239. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  240. data/lib/active_record/type/decorator.rb +0 -14
  241. data/lib/active_record/type/float.rb +0 -19
  242. data/lib/active_record/type/integer.rb +0 -55
  243. data/lib/active_record/type/mutable.rb +0 -16
  244. data/lib/active_record/type/numeric.rb +0 -36
  245. data/lib/active_record/type/string.rb +0 -36
  246. data/lib/active_record/type/text.rb +0 -11
  247. data/lib/active_record/type/time_value.rb +0 -38
  248. data/lib/active_record/type/unsigned_integer.rb +0 -15
  249. data/lib/active_record/type/value.rb +0 -101
@@ -9,40 +9,170 @@ module ActiveRecord
9
9
  end
10
10
  end
11
11
 
12
- # Exception that can be raised to stop migrations from going backwards.
12
+ # Exception that can be raised to stop migrations from being rolled back.
13
+ # For example the following migration is not reversible.
14
+ # Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
15
+ #
16
+ # class IrreversibleMigrationExample < ActiveRecord::Migration[5.0]
17
+ # def change
18
+ # create_table :distributors do |t|
19
+ # t.string :zipcode
20
+ # end
21
+ #
22
+ # execute <<-SQL
23
+ # ALTER TABLE distributors
24
+ # ADD CONSTRAINT zipchk
25
+ # CHECK (char_length(zipcode) = 5) NO INHERIT;
26
+ # SQL
27
+ # end
28
+ # end
29
+ #
30
+ # There are two ways to mitigate this problem.
31
+ #
32
+ # 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
33
+ #
34
+ # class ReversibleMigrationExample < ActiveRecord::Migration[5.0]
35
+ # def up
36
+ # create_table :distributors do |t|
37
+ # t.string :zipcode
38
+ # end
39
+ #
40
+ # execute <<-SQL
41
+ # ALTER TABLE distributors
42
+ # ADD CONSTRAINT zipchk
43
+ # CHECK (char_length(zipcode) = 5) NO INHERIT;
44
+ # SQL
45
+ # end
46
+ #
47
+ # def down
48
+ # execute <<-SQL
49
+ # ALTER TABLE distributors
50
+ # DROP CONSTRAINT zipchk
51
+ # SQL
52
+ #
53
+ # drop_table :distributors
54
+ # end
55
+ # end
56
+ #
57
+ # 2. Use the #reversible method in <tt>#change</tt> method:
58
+ #
59
+ # class ReversibleMigrationExample < ActiveRecord::Migration[5.0]
60
+ # def change
61
+ # create_table :distributors do |t|
62
+ # t.string :zipcode
63
+ # end
64
+ #
65
+ # reversible do |dir|
66
+ # dir.up do
67
+ # execute <<-SQL
68
+ # ALTER TABLE distributors
69
+ # ADD CONSTRAINT zipchk
70
+ # CHECK (char_length(zipcode) = 5) NO INHERIT;
71
+ # SQL
72
+ # end
73
+ #
74
+ # dir.down do
75
+ # execute <<-SQL
76
+ # ALTER TABLE distributors
77
+ # DROP CONSTRAINT zipchk
78
+ # SQL
79
+ # end
80
+ # end
81
+ # end
82
+ # end
13
83
  class IrreversibleMigration < MigrationError
14
84
  end
15
85
 
16
86
  class DuplicateMigrationVersionError < MigrationError#:nodoc:
17
- def initialize(version)
18
- super("Multiple migrations have the version number #{version}")
87
+ def initialize(version = nil)
88
+ if version
89
+ super("Multiple migrations have the version number #{version}.")
90
+ else
91
+ super("Duplicate migration version error.")
92
+ end
19
93
  end
20
94
  end
21
95
 
22
96
  class DuplicateMigrationNameError < MigrationError#:nodoc:
23
- def initialize(name)
24
- super("Multiple migrations have the name #{name}")
97
+ def initialize(name = nil)
98
+ if name
99
+ super("Multiple migrations have the name #{name}.")
100
+ else
101
+ super("Duplicate migration name.")
102
+ end
25
103
  end
26
104
  end
27
105
 
28
106
  class UnknownMigrationVersionError < MigrationError #:nodoc:
29
- def initialize(version)
30
- super("No migration with version number #{version}")
107
+ def initialize(version = nil)
108
+ if version
109
+ super("No migration with version number #{version}.")
110
+ else
111
+ super("Unknown migration version.")
112
+ end
31
113
  end
32
114
  end
33
115
 
34
116
  class IllegalMigrationNameError < MigrationError#:nodoc:
35
- def initialize(name)
36
- super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed)")
117
+ def initialize(name = nil)
118
+ if name
119
+ super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).")
120
+ else
121
+ super("Illegal name for migration.")
122
+ end
37
123
  end
38
124
  end
39
125
 
40
126
  class PendingMigrationError < MigrationError#:nodoc:
127
+ def initialize(message = nil)
128
+ if !message && defined?(Rails.env)
129
+ super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rails db:migrate RAILS_ENV=#{::Rails.env}")
130
+ elsif !message
131
+ super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rails db:migrate")
132
+ else
133
+ super
134
+ end
135
+ end
136
+ end
137
+
138
+ class ConcurrentMigrationError < MigrationError #:nodoc:
139
+ DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running.".freeze
140
+
141
+ def initialize(message = DEFAULT_MESSAGE)
142
+ super
143
+ end
144
+ end
145
+
146
+ class NoEnvironmentInSchemaError < MigrationError #:nodoc:
41
147
  def initialize
42
- if defined?(Rails)
43
- super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate RAILS_ENV=#{::Rails.env}")
148
+ msg = "Environment data not found in the schema. To resolve this issue, run: \n\n\tbin/rails db:environment:set"
149
+ if defined?(Rails.env)
150
+ super("#{msg} RAILS_ENV=#{::Rails.env}")
151
+ else
152
+ super(msg)
153
+ end
154
+ end
155
+ end
156
+
157
+ class ProtectedEnvironmentError < ActiveRecordError #:nodoc:
158
+ def initialize(env = "production")
159
+ msg = "You are attempting to run a destructive action against your '#{env}' database.\n"
160
+ msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
161
+ msg << "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
162
+ super(msg)
163
+ end
164
+ end
165
+
166
+ class EnvironmentMismatchError < ActiveRecordError
167
+ def initialize(current: nil, stored: nil)
168
+ msg = "You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
169
+ msg << "You are running in `#{ current }` environment. "
170
+ msg << "If you are sure you want to continue, first set the environment using:\n\n"
171
+ msg << "\tbin/rails db:environment:set"
172
+ if defined?(Rails.env)
173
+ super("#{msg} RAILS_ENV=#{::Rails.env}\n\n")
44
174
  else
45
- super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate")
175
+ super("#{msg}\n\n")
46
176
  end
47
177
  end
48
178
  end
@@ -59,7 +189,7 @@ module ActiveRecord
59
189
  #
60
190
  # Example of a simple migration:
61
191
  #
62
- # class AddSsl < ActiveRecord::Migration
192
+ # class AddSsl < ActiveRecord::Migration[5.0]
63
193
  # def up
64
194
  # add_column :accounts, :ssl_enabled, :boolean, default: true
65
195
  # end
@@ -79,7 +209,7 @@ module ActiveRecord
79
209
  #
80
210
  # Example of a more complex migration that also needs to initialize data:
81
211
  #
82
- # class AddSystemSettings < ActiveRecord::Migration
212
+ # class AddSystemSettings < ActiveRecord::Migration[5.0]
83
213
  # def up
84
214
  # create_table :system_settings do |t|
85
215
  # t.string :name
@@ -106,17 +236,18 @@ module ActiveRecord
106
236
  #
107
237
  # == Available transformations
108
238
  #
239
+ # === Creation
240
+ #
241
+ # * <tt>create_join_table(table_1, table_2, options)</tt>: Creates a join
242
+ # table having its name as the lexical order of the first two
243
+ # arguments. See
244
+ # ActiveRecord::ConnectionAdapters::SchemaStatements#create_join_table for
245
+ # details.
109
246
  # * <tt>create_table(name, options)</tt>: Creates a table called +name+ and
110
247
  # makes the table object available to a block that can then add columns to it,
111
248
  # following the same format as +add_column+. See example above. The options hash
112
249
  # is for fragments like "DEFAULT CHARSET=UTF-8" that are appended to the create
113
250
  # table definition.
114
- # * <tt>drop_table(name)</tt>: Drops the table called +name+.
115
- # * <tt>change_table(name, options)</tt>: Allows to make column alterations to
116
- # the table called +name+. It makes the table object available to a block that
117
- # can then add/remove columns, indexes or foreign keys to it.
118
- # * <tt>rename_table(old_name, new_name)</tt>: Renames the table called +old_name+
119
- # to +new_name+.
120
251
  # * <tt>add_column(table_name, column_name, type, options)</tt>: Adds a new column
121
252
  # to the table called +table_name+
122
253
  # named +column_name+ specified to be one of the following types:
@@ -127,21 +258,59 @@ module ActiveRecord
127
258
  # Other options include <tt>:limit</tt> and <tt>:null</tt> (e.g.
128
259
  # <tt>{ limit: 50, null: false }</tt>) -- see
129
260
  # ActiveRecord::ConnectionAdapters::TableDefinition#column for details.
130
- # * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames
131
- # a column but keeps the type and content.
132
- # * <tt>change_column(table_name, column_name, type, options)</tt>: Changes
133
- # the column to a different type using the same parameters as add_column.
134
- # * <tt>remove_column(table_name, column_name, type, options)</tt>: Removes the column
135
- # named +column_name+ from the table called +table_name+.
261
+ # * <tt>add_foreign_key(from_table, to_table, options)</tt>: Adds a new
262
+ # foreign key. +from_table+ is the table with the key column, +to_table+ contains
263
+ # the referenced primary key.
136
264
  # * <tt>add_index(table_name, column_names, options)</tt>: Adds a new index
137
265
  # with the name of the column. Other options include
138
266
  # <tt>:name</tt>, <tt>:unique</tt> (e.g.
139
267
  # <tt>{ name: 'users_name_index', unique: true }</tt>) and <tt>:order</tt>
140
268
  # (e.g. <tt>{ order: { name: :desc } }</tt>).
141
- # * <tt>remove_index(table_name, column: column_name)</tt>: Removes the index
142
- # specified by +column_name+.
269
+ # * <tt>add_reference(:table_name, :reference_name)</tt>: Adds a new column
270
+ # +reference_name_id+ by default an integer. See
271
+ # ActiveRecord::ConnectionAdapters::SchemaStatements#add_reference for details.
272
+ # * <tt>add_timestamps(table_name, options)</tt>: Adds timestamps (+created_at+
273
+ # and +updated_at+) columns to +table_name+.
274
+ #
275
+ # === Modification
276
+ #
277
+ # * <tt>change_column(table_name, column_name, type, options)</tt>: Changes
278
+ # the column to a different type using the same parameters as add_column.
279
+ # * <tt>change_column_default(table_name, column_name, default)</tt>: Sets a
280
+ # default value for +column_name+ defined by +default+ on +table_name+.
281
+ # * <tt>change_column_null(table_name, column_name, null, default = nil)</tt>:
282
+ # Sets or removes a +NOT NULL+ constraint on +column_name+. The +null+ flag
283
+ # indicates whether the value can be +NULL+. See
284
+ # ActiveRecord::ConnectionAdapters::SchemaStatements#change_column_null for
285
+ # details.
286
+ # * <tt>change_table(name, options)</tt>: Allows to make column alterations to
287
+ # the table called +name+. It makes the table object available to a block that
288
+ # can then add/remove columns, indexes or foreign keys to it.
289
+ # * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames
290
+ # a column but keeps the type and content.
291
+ # * <tt>rename_index(table_name, old_name, new_name)</tt>: Renames an index.
292
+ # * <tt>rename_table(old_name, new_name)</tt>: Renames the table called +old_name+
293
+ # to +new_name+.
294
+ #
295
+ # === Deletion
296
+ #
297
+ # * <tt>drop_table(name)</tt>: Drops the table called +name+.
298
+ # * <tt>drop_join_table(table_1, table_2, options)</tt>: Drops the join table
299
+ # specified by the given arguments.
300
+ # * <tt>remove_column(table_name, column_name, type, options)</tt>: Removes the column
301
+ # named +column_name+ from the table called +table_name+.
302
+ # * <tt>remove_columns(table_name, *column_names)</tt>: Removes the given
303
+ # columns from the table definition.
304
+ # * <tt>remove_foreign_key(from_table, options_or_to_table)</tt>: Removes the
305
+ # given foreign key from the table called +table_name+.
306
+ # * <tt>remove_index(table_name, column: column_names)</tt>: Removes the index
307
+ # specified by +column_names+.
143
308
  # * <tt>remove_index(table_name, name: index_name)</tt>: Removes the index
144
309
  # specified by +index_name+.
310
+ # * <tt>remove_reference(table_name, ref_name, options)</tt>: Removes the
311
+ # reference(s) on +table_name+ specified by +ref_name+.
312
+ # * <tt>remove_timestamps(table_name, options)</tt>: Removes the timestamp
313
+ # columns (+created_at+ and +updated_at+) from the table definition.
145
314
  #
146
315
  # == Irreversible transformations
147
316
  #
@@ -165,24 +334,24 @@ module ActiveRecord
165
334
  #
166
335
  # rails generate migration add_fieldname_to_tablename fieldname:string
167
336
  #
168
- # This will generate the file <tt>timestamp_add_fieldname_to_tablename</tt>, which will look like this:
169
- # class AddFieldnameToTablename < ActiveRecord::Migration
337
+ # This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
338
+ # class AddFieldnameToTablename < ActiveRecord::Migration[5.0]
170
339
  # def change
171
- # add_column :tablenames, :field, :string
340
+ # add_column :tablenames, :fieldname, :string
172
341
  # end
173
342
  # end
174
343
  #
175
344
  # To run migrations against the currently configured database, use
176
- # <tt>rake db:migrate</tt>. This will update the database by running all of the
345
+ # <tt>rails db:migrate</tt>. This will update the database by running all of the
177
346
  # pending migrations, creating the <tt>schema_migrations</tt> table
178
347
  # (see "About the schema_migrations table" section below) if missing. It will also
179
348
  # invoke the db:schema:dump task, which will update your db/schema.rb file
180
349
  # to match the structure of your database.
181
350
  #
182
351
  # To roll the database back to a previous migration version, use
183
- # <tt>rake db:migrate VERSION=X</tt> where <tt>X</tt> is the version to which
352
+ # <tt>rails db:migrate VERSION=X</tt> where <tt>X</tt> is the version to which
184
353
  # you wish to downgrade. Alternatively, you can also use the STEP option if you
185
- # wish to rollback last few migrations. <tt>rake db:migrate STEP=2</tt> will rollback
354
+ # wish to rollback last few migrations. <tt>rails db:migrate STEP=2</tt> will rollback
186
355
  # the latest two migrations.
187
356
  #
188
357
  # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
@@ -197,7 +366,7 @@ module ActiveRecord
197
366
  #
198
367
  # Not all migrations change the schema. Some just fix the data:
199
368
  #
200
- # class RemoveEmptyTags < ActiveRecord::Migration
369
+ # class RemoveEmptyTags < ActiveRecord::Migration[5.0]
201
370
  # def up
202
371
  # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
203
372
  # end
@@ -210,7 +379,7 @@ module ActiveRecord
210
379
  #
211
380
  # Others remove columns when they migrate up instead of down:
212
381
  #
213
- # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration
382
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[5.0]
214
383
  # def up
215
384
  # remove_column :items, :incomplete_items_count
216
385
  # remove_column :items, :completed_items_count
@@ -224,7 +393,7 @@ module ActiveRecord
224
393
  #
225
394
  # And sometimes you need to do something in SQL not abstracted directly by migrations:
226
395
  #
227
- # class MakeJoinUnique < ActiveRecord::Migration
396
+ # class MakeJoinUnique < ActiveRecord::Migration[5.0]
228
397
  # def up
229
398
  # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
230
399
  # end
@@ -241,7 +410,7 @@ module ActiveRecord
241
410
  # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
242
411
  # latest column data from after the new column was added. Example:
243
412
  #
244
- # class AddPeopleSalary < ActiveRecord::Migration
413
+ # class AddPeopleSalary < ActiveRecord::Migration[5.0]
245
414
  # def up
246
415
  # add_column :people, :salary, :integer
247
416
  # Person.reset_column_information
@@ -275,21 +444,6 @@ module ActiveRecord
275
444
  # The phrase "Updating salaries..." would then be printed, along with the
276
445
  # benchmark for the block when the block completes.
277
446
  #
278
- # == About the schema_migrations table
279
- #
280
- # Rails versions 2.0 and prior used to create a table called
281
- # <tt>schema_info</tt> when using migrations. This table contained the
282
- # version of the schema as of the last applied migration.
283
- #
284
- # Starting with Rails 2.1, the <tt>schema_info</tt> table is
285
- # (automatically) replaced by the <tt>schema_migrations</tt> table, which
286
- # contains the version numbers of all the migrations applied.
287
- #
288
- # As a result, it is now possible to add migration files that are numbered
289
- # lower than the current schema version: when migrating up, those
290
- # never-applied "interleaved" migrations will be automatically applied, and
291
- # when migrating down, never-applied "interleaved" migrations will be skipped.
292
- #
293
447
  # == Timestamped Migrations
294
448
  #
295
449
  # By default, Rails generates migrations that look like:
@@ -307,15 +461,14 @@ module ActiveRecord
307
461
  #
308
462
  # == Reversible Migrations
309
463
  #
310
- # Starting with Rails 3.1, you will be able to define reversible migrations.
311
464
  # Reversible migrations are migrations that know how to go +down+ for you.
312
- # You simply supply the +up+ logic, and the Migration system will figure out
465
+ # You simply supply the +up+ logic, and the Migration system figures out
313
466
  # how to execute the down commands for you.
314
467
  #
315
468
  # To define a reversible migration, define the +change+ method in your
316
469
  # migration like this:
317
470
  #
318
- # class TenderloveMigration < ActiveRecord::Migration
471
+ # class TenderloveMigration < ActiveRecord::Migration[5.0]
319
472
  # def change
320
473
  # create_table(:horses) do |t|
321
474
  # t.column :content, :text
@@ -345,7 +498,7 @@ module ActiveRecord
345
498
  # can't execute inside a transaction though, and for these situations
346
499
  # you can turn the automatic transactions off.
347
500
  #
348
- # class ChangeEnum < ActiveRecord::Migration
501
+ # class ChangeEnum < ActiveRecord::Migration[5.0]
349
502
  # disable_ddl_transaction!
350
503
  #
351
504
  # def up
@@ -357,10 +510,31 @@ module ActiveRecord
357
510
  # are in a Migration with <tt>self.disable_ddl_transaction!</tt>.
358
511
  class Migration
359
512
  autoload :CommandRecorder, 'active_record/migration/command_recorder'
513
+ autoload :Compatibility, 'active_record/migration/compatibility'
360
514
 
515
+ # This must be defined before the inherited hook, below
516
+ class Current < Migration # :nodoc:
517
+ end
518
+
519
+ def self.inherited(subclass) # :nodoc:
520
+ super
521
+ if subclass.superclass == Migration
522
+ subclass.include Compatibility::Legacy
523
+ end
524
+ end
525
+
526
+ def self.[](version)
527
+ Compatibility.find(version)
528
+ end
529
+
530
+ def self.current_version
531
+ ActiveRecord::VERSION::STRING.to_f
532
+ end
533
+
534
+ MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
361
535
 
362
536
  # This class is used to verify that all migrations have been run before
363
- # loading a web page if config.active_record.migration_error is set to :page_load
537
+ # loading a web page if <tt>config.active_record.migration_error</tt> is set to :page_load
364
538
  class CheckPending
365
539
  def initialize(app)
366
540
  @app = app
@@ -389,17 +563,22 @@ module ActiveRecord
389
563
  attr_accessor :delegate # :nodoc:
390
564
  attr_accessor :disable_ddl_transaction # :nodoc:
391
565
 
566
+ def nearest_delegate # :nodoc:
567
+ delegate || superclass.nearest_delegate
568
+ end
569
+
570
+ # Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending.
392
571
  def check_pending!(connection = Base.connection)
393
572
  raise ActiveRecord::PendingMigrationError if ActiveRecord::Migrator.needs_migration?(connection)
394
573
  end
395
574
 
396
575
  def load_schema_if_pending!
397
576
  if ActiveRecord::Migrator.needs_migration? || !ActiveRecord::Migrator.any_migrations?
398
- # Roundrip to Rake to allow plugins to hook into database initialization.
577
+ # Roundtrip to Rake to allow plugins to hook into database initialization.
399
578
  FileUtils.cd Rails.root do
400
579
  current_config = Base.connection_config
401
580
  Base.clear_all_connections!
402
- system("bin/rake db:test:prepare")
581
+ system("bin/rails db:test:prepare")
403
582
  # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
404
583
  Base.establish_connection(current_config)
405
584
  end
@@ -414,14 +593,17 @@ module ActiveRecord
414
593
  end
415
594
 
416
595
  def method_missing(name, *args, &block) # :nodoc:
417
- (delegate || superclass.delegate).send(name, *args, &block)
596
+ nearest_delegate.send(name, *args, &block)
418
597
  end
419
598
 
420
599
  def migrate(direction)
421
600
  new.migrate direction
422
601
  end
423
602
 
424
- # Disable DDL transactions for this migration.
603
+ # Disable the transaction wrapping this migration.
604
+ # You can still create your own transactions even after calling #disable_ddl_transaction!
605
+ #
606
+ # For more details read the {"Transactional Migrations" section above}[rdoc-ref:Migration].
425
607
  def disable_ddl_transaction!
426
608
  @disable_ddl_transaction = true
427
609
  end
@@ -451,7 +633,7 @@ module ActiveRecord
451
633
  # and create the table 'apples' on the way up, and the reverse
452
634
  # on the way down.
453
635
  #
454
- # class FixTLMigration < ActiveRecord::Migration
636
+ # class FixTLMigration < ActiveRecord::Migration[5.0]
455
637
  # def change
456
638
  # revert do
457
639
  # create_table(:horses) do |t|
@@ -468,9 +650,9 @@ module ActiveRecord
468
650
  # Or equivalently, if +TenderloveMigration+ is defined as in the
469
651
  # documentation for Migration:
470
652
  #
471
- # require_relative '2012121212_tenderlove_migration'
653
+ # require_relative '20121212123456_tenderlove_migration'
472
654
  #
473
- # class FixupTLMigration < ActiveRecord::Migration
655
+ # class FixupTLMigration < ActiveRecord::Migration[5.0]
474
656
  # def change
475
657
  # revert TenderloveMigration
476
658
  #
@@ -484,13 +666,13 @@ module ActiveRecord
484
666
  def revert(*migration_classes)
485
667
  run(*migration_classes.reverse, revert: true) unless migration_classes.empty?
486
668
  if block_given?
487
- if @connection.respond_to? :revert
488
- @connection.revert { yield }
669
+ if connection.respond_to? :revert
670
+ connection.revert { yield }
489
671
  else
490
- recorder = CommandRecorder.new(@connection)
672
+ recorder = CommandRecorder.new(connection)
491
673
  @connection = recorder
492
674
  suppress_messages do
493
- @connection.revert { yield }
675
+ connection.revert { yield }
494
676
  end
495
677
  @connection = recorder.delegate
496
678
  recorder.commands.each do |cmd, args, block|
@@ -501,7 +683,7 @@ module ActiveRecord
501
683
  end
502
684
 
503
685
  def reverting?
504
- @connection.respond_to?(:reverting) && @connection.reverting
686
+ connection.respond_to?(:reverting) && connection.reverting
505
687
  end
506
688
 
507
689
  class ReversibleBlockHelper < Struct.new(:reverting) # :nodoc:
@@ -523,7 +705,7 @@ module ActiveRecord
523
705
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
524
706
  # even when migrating down:
525
707
  #
526
- # class SplitNameMigration < ActiveRecord::Migration
708
+ # class SplitNameMigration < ActiveRecord::Migration[5.0]
527
709
  # def change
528
710
  # add_column :users, :first_name, :string
529
711
  # add_column :users, :last_name, :string
@@ -558,7 +740,7 @@ module ActiveRecord
558
740
  revert { run(*migration_classes, direction: dir, revert: true) }
559
741
  else
560
742
  migration_classes.each do |migration_class|
561
- migration_class.new.exec_migration(@connection, dir)
743
+ migration_class.new.exec_migration(connection, dir)
562
744
  end
563
745
  end
564
746
  end
@@ -647,13 +829,14 @@ module ActiveRecord
647
829
  end
648
830
 
649
831
  def method_missing(method, *arguments, &block)
650
- arg_list = arguments.map{ |a| a.inspect } * ', '
832
+ arg_list = arguments.map(&:inspect) * ', '
651
833
 
652
834
  say_with_time "#{method}(#{arg_list})" do
653
- unless @connection.respond_to? :revert
835
+ unless connection.respond_to? :revert
654
836
  unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
655
837
  arguments[0] = proper_table_name(arguments.first, table_name_options)
656
- if [:rename_table, :add_foreign_key].include?(method)
838
+ if [:rename_table, :add_foreign_key].include?(method) ||
839
+ (method == :remove_foreign_key && !arguments.second.is_a?(Hash))
657
840
  arguments[1] = proper_table_name(arguments.second, table_name_options)
658
841
  end
659
842
  end
@@ -728,7 +911,9 @@ module ActiveRecord
728
911
  end
729
912
  end
730
913
 
731
- def table_name_options(config = ActiveRecord::Base)
914
+ # Builds a hash for use in ActiveRecord::Migration#proper_table_name using
915
+ # the Active Record object's table_name prefix and suffix
916
+ def table_name_options(config = ActiveRecord::Base) #:nodoc:
732
917
  {
733
918
  table_name_prefix: config.table_name_prefix,
734
919
  table_name_suffix: config.table_name_suffix
@@ -820,7 +1005,7 @@ module ActiveRecord
820
1005
  new(:up, migrations, target_version).migrate
821
1006
  end
822
1007
 
823
- def down(migrations_paths, target_version = nil, &block)
1008
+ def down(migrations_paths, target_version = nil)
824
1009
  migrations = migrations(migrations_paths)
825
1010
  migrations.select! { |m| yield m } if block_given?
826
1011
 
@@ -840,10 +1025,12 @@ module ActiveRecord
840
1025
  end
841
1026
 
842
1027
  def get_all_versions(connection = Base.connection)
843
- if connection.table_exists?(schema_migrations_table_name)
844
- SchemaMigration.all.map { |x| x.version.to_i }.sort
845
- else
846
- []
1028
+ ActiveSupport::Deprecation.silence do
1029
+ if connection.table_exists?(schema_migrations_table_name)
1030
+ SchemaMigration.all.map { |x| x.version.to_i }.sort
1031
+ else
1032
+ []
1033
+ end
847
1034
  end
848
1035
  end
849
1036
 
@@ -859,22 +1046,22 @@ module ActiveRecord
859
1046
  migrations(migrations_paths).any?
860
1047
  end
861
1048
 
862
- def last_version
863
- last_migration.version
864
- end
865
-
866
1049
  def last_migration #:nodoc:
867
1050
  migrations(migrations_paths).last || NullMigration.new
868
1051
  end
869
1052
 
870
1053
  def migrations_paths
871
1054
  @migrations_paths ||= ['db/migrate']
872
- # just to not break things if someone uses: migration_path = some_string
1055
+ # just to not break things if someone uses: migrations_path = some_string
873
1056
  Array(@migrations_paths)
874
1057
  end
875
1058
 
876
- def migrations_path
877
- migrations_paths.first
1059
+ def match_to_migration_filename?(filename) # :nodoc:
1060
+ File.basename(filename) =~ Migration::MigrationFilenameRegexp
1061
+ end
1062
+
1063
+ def parse_migration_filename(filename) # :nodoc:
1064
+ File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
878
1065
  end
879
1066
 
880
1067
  def migrations(paths)
@@ -883,8 +1070,7 @@ module ActiveRecord
883
1070
  files = Dir[*paths.map { |p| "#{p}/**/[0-9]*_*.rb" }]
884
1071
 
885
1072
  migrations = files.map do |file|
886
- version, name, scope = file.scan(/([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/).first
887
-
1073
+ version, name, scope = parse_migration_filename(file)
888
1074
  raise IllegalMigrationNameError.new(file) unless version
889
1075
  version = version.to_i
890
1076
  name = name.camelize
@@ -920,6 +1106,7 @@ module ActiveRecord
920
1106
  validate(@migrations)
921
1107
 
922
1108
  Base.connection.initialize_schema_migrations_table
1109
+ Base.connection.initialize_internal_metadata_table
923
1110
  end
924
1111
 
925
1112
  def current_version
@@ -932,32 +1119,18 @@ module ActiveRecord
932
1119
  alias :current :current_migration
933
1120
 
934
1121
  def run
935
- migration = migrations.detect { |m| m.version == @target_version }
936
- raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
937
- unless (up? && migrated.include?(migration.version.to_i)) || (down? && !migrated.include?(migration.version.to_i))
938
- begin
939
- execute_migration_in_transaction(migration, @direction)
940
- rescue => e
941
- canceled_msg = use_transaction?(migration) ? ", this migration was canceled" : ""
942
- raise StandardError, "An error has occurred#{canceled_msg}:\n\n#{e}", e.backtrace
943
- end
1122
+ if use_advisory_lock?
1123
+ with_advisory_lock { run_without_lock }
1124
+ else
1125
+ run_without_lock
944
1126
  end
945
1127
  end
946
1128
 
947
1129
  def migrate
948
- if !target && @target_version && @target_version > 0
949
- raise UnknownMigrationVersionError.new(@target_version)
950
- end
951
-
952
- runnable.each do |migration|
953
- Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
954
-
955
- begin
956
- execute_migration_in_transaction(migration, @direction)
957
- rescue => e
958
- canceled_msg = use_transaction?(migration) ? "this and " : ""
959
- raise StandardError, "An error has occurred, #{canceled_msg}all later migrations canceled:\n\n#{e}", e.backtrace
960
- end
1130
+ if use_advisory_lock?
1131
+ with_advisory_lock { migrate_without_lock }
1132
+ else
1133
+ migrate_without_lock
961
1134
  end
962
1135
  end
963
1136
 
@@ -982,19 +1155,67 @@ module ActiveRecord
982
1155
  end
983
1156
 
984
1157
  def migrated
985
- @migrated_versions ||= Set.new(self.class.get_all_versions)
1158
+ @migrated_versions || load_migrated
1159
+ end
1160
+
1161
+ def load_migrated
1162
+ @migrated_versions = Set.new(self.class.get_all_versions)
986
1163
  end
987
1164
 
988
1165
  private
1166
+
1167
+ # Used for running a specific migration.
1168
+ def run_without_lock
1169
+ migration = migrations.detect { |m| m.version == @target_version }
1170
+ raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
1171
+ execute_migration_in_transaction(migration, @direction)
1172
+
1173
+ record_environment
1174
+ end
1175
+
1176
+ # Used for running multiple migrations up to or down to a certain value.
1177
+ def migrate_without_lock
1178
+ if invalid_target?
1179
+ raise UnknownMigrationVersionError.new(@target_version)
1180
+ end
1181
+
1182
+ runnable.each do |migration|
1183
+ execute_migration_in_transaction(migration, @direction)
1184
+ end
1185
+
1186
+ record_environment
1187
+ end
1188
+
1189
+ # Stores the current environment in the database.
1190
+ def record_environment
1191
+ return if down?
1192
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
1193
+ end
1194
+
989
1195
  def ran?(migration)
990
1196
  migrated.include?(migration.version.to_i)
991
1197
  end
992
1198
 
1199
+ # Return true if a valid version is not provided.
1200
+ def invalid_target?
1201
+ !target && @target_version && @target_version > 0
1202
+ end
1203
+
993
1204
  def execute_migration_in_transaction(migration, direction)
1205
+ return if down? && !migrated.include?(migration.version.to_i)
1206
+ return if up? && migrated.include?(migration.version.to_i)
1207
+
1208
+ Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
1209
+
994
1210
  ddl_transaction(migration) do
995
1211
  migration.migrate(direction)
996
1212
  record_version_state_after_migrating(migration.version)
997
1213
  end
1214
+ rescue => e
1215
+ msg = "An error has occurred, "
1216
+ msg << "this and " if use_transaction?(migration)
1217
+ msg << "all later migrations canceled:\n\n#{e}"
1218
+ raise StandardError, msg, e.backtrace
998
1219
  end
999
1220
 
1000
1221
  def target
@@ -1023,10 +1244,27 @@ module ActiveRecord
1023
1244
  ActiveRecord::SchemaMigration.where(:version => version.to_s).delete_all
1024
1245
  else
1025
1246
  migrated << version
1026
- ActiveRecord::SchemaMigration.create!(:version => version.to_s)
1247
+ ActiveRecord::SchemaMigration.create!(version: version.to_s)
1027
1248
  end
1028
1249
  end
1029
1250
 
1251
+ def self.last_stored_environment
1252
+ return nil if current_version == 0
1253
+ raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1254
+
1255
+ environment = ActiveRecord::InternalMetadata[:environment]
1256
+ raise NoEnvironmentInSchemaError unless environment
1257
+ environment
1258
+ end
1259
+
1260
+ def self.current_environment
1261
+ ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
1262
+ end
1263
+
1264
+ def self.protected_environment?
1265
+ ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
1266
+ end
1267
+
1030
1268
  def up?
1031
1269
  @direction == :up
1032
1270
  end
@@ -1047,5 +1285,25 @@ module ActiveRecord
1047
1285
  def use_transaction?(migration)
1048
1286
  !migration.disable_ddl_transaction && Base.connection.supports_ddl_transactions?
1049
1287
  end
1288
+
1289
+ def use_advisory_lock?
1290
+ Base.connection.supports_advisory_locks?
1291
+ end
1292
+
1293
+ def with_advisory_lock
1294
+ lock_id = generate_migrator_advisory_lock_id
1295
+ got_lock = Base.connection.get_advisory_lock(lock_id)
1296
+ raise ConcurrentMigrationError unless got_lock
1297
+ load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1298
+ yield
1299
+ ensure
1300
+ Base.connection.release_advisory_lock(lock_id) if got_lock
1301
+ end
1302
+
1303
+ MIGRATOR_SALT = 2053462845
1304
+ def generate_migrator_advisory_lock_id
1305
+ db_name_hash = Zlib.crc32(Base.connection.current_database)
1306
+ MIGRATOR_SALT * db_name_hash
1307
+ end
1050
1308
  end
1051
1309
  end