activerecord 4.2.11.3 → 5.0.7.2

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 (251) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1638 -1132
  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.rb +7 -2
  8. data/lib/active_record/aggregations.rb +34 -21
  9. data/lib/active_record/association_relation.rb +7 -4
  10. data/lib/active_record/associations.rb +347 -218
  11. data/lib/active_record/associations/alias_tracker.rb +19 -16
  12. data/lib/active_record/associations/association.rb +22 -10
  13. data/lib/active_record/associations/association_scope.rb +75 -104
  14. data/lib/active_record/associations/belongs_to_association.rb +21 -32
  15. data/lib/active_record/associations/builder/association.rb +28 -34
  16. data/lib/active_record/associations/builder/belongs_to.rb +43 -18
  17. data/lib/active_record/associations/builder/collection_association.rb +7 -19
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +16 -11
  19. data/lib/active_record/associations/builder/has_many.rb +4 -4
  20. data/lib/active_record/associations/builder/has_one.rb +11 -6
  21. data/lib/active_record/associations/builder/singular_association.rb +13 -11
  22. data/lib/active_record/associations/collection_association.rb +85 -69
  23. data/lib/active_record/associations/collection_proxy.rb +104 -46
  24. data/lib/active_record/associations/foreign_association.rb +1 -1
  25. data/lib/active_record/associations/has_many_association.rb +21 -78
  26. data/lib/active_record/associations/has_many_through_association.rb +6 -47
  27. data/lib/active_record/associations/has_one_association.rb +12 -5
  28. data/lib/active_record/associations/join_dependency.rb +38 -22
  29. data/lib/active_record/associations/join_dependency/join_association.rb +15 -14
  30. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  31. data/lib/active_record/associations/preloader.rb +14 -4
  32. data/lib/active_record/associations/preloader/association.rb +52 -71
  33. data/lib/active_record/associations/preloader/collection_association.rb +0 -7
  34. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  35. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  36. data/lib/active_record/associations/preloader/singular_association.rb +0 -1
  37. data/lib/active_record/associations/preloader/through_association.rb +36 -17
  38. data/lib/active_record/associations/singular_association.rb +13 -1
  39. data/lib/active_record/associations/through_association.rb +12 -4
  40. data/lib/active_record/attribute.rb +69 -19
  41. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  42. data/lib/active_record/attribute_assignment.rb +19 -140
  43. data/lib/active_record/attribute_decorators.rb +6 -5
  44. data/lib/active_record/attribute_methods.rb +69 -44
  45. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  46. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  47. data/lib/active_record/attribute_methods/primary_key.rb +16 -3
  48. data/lib/active_record/attribute_methods/query.rb +2 -2
  49. data/lib/active_record/attribute_methods/read.rb +31 -59
  50. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  51. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
  52. data/lib/active_record/attribute_methods/write.rb +13 -37
  53. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  54. data/lib/active_record/attribute_set.rb +32 -3
  55. data/lib/active_record/attribute_set/builder.rb +42 -16
  56. data/lib/active_record/attributes.rb +199 -81
  57. data/lib/active_record/autosave_association.rb +54 -17
  58. data/lib/active_record/base.rb +32 -23
  59. data/lib/active_record/callbacks.rb +39 -43
  60. data/lib/active_record/coders/json.rb +1 -1
  61. data/lib/active_record/coders/yaml_column.rb +20 -8
  62. data/lib/active_record/collection_cache_key.rb +50 -0
  63. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +467 -189
  64. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  65. data/lib/active_record/connection_adapters/abstract/database_statements.rb +66 -62
  66. data/lib/active_record/connection_adapters/abstract/query_cache.rb +39 -4
  67. data/lib/active_record/connection_adapters/abstract/quoting.rb +86 -13
  68. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  69. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  70. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -188
  71. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  72. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +407 -156
  73. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  74. data/lib/active_record/connection_adapters/abstract_adapter.rb +177 -71
  75. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +433 -399
  76. data/lib/active_record/connection_adapters/column.rb +28 -43
  77. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  78. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  79. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  80. data/lib/active_record/connection_adapters/mysql/database_statements.rb +108 -0
  81. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  82. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  83. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  84. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  85. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  86. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  87. data/lib/active_record/connection_adapters/mysql2_adapter.rb +25 -166
  88. data/lib/active_record/connection_adapters/postgresql/column.rb +33 -11
  89. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -72
  90. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  92. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +37 -57
  93. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +3 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -2
  95. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  96. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  97. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +13 -3
  98. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  99. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  102. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +56 -19
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +250 -154
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -2
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +264 -170
  116. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  118. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  121. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +151 -194
  122. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  123. data/lib/active_record/connection_handling.rb +37 -14
  124. data/lib/active_record/core.rb +92 -108
  125. data/lib/active_record/counter_cache.rb +13 -24
  126. data/lib/active_record/dynamic_matchers.rb +1 -20
  127. data/lib/active_record/enum.rb +116 -76
  128. data/lib/active_record/errors.rb +87 -48
  129. data/lib/active_record/explain.rb +20 -9
  130. data/lib/active_record/explain_registry.rb +1 -1
  131. data/lib/active_record/explain_subscriber.rb +1 -1
  132. data/lib/active_record/fixture_set/file.rb +26 -5
  133. data/lib/active_record/fixtures.rb +77 -41
  134. data/lib/active_record/gem_version.rb +4 -4
  135. data/lib/active_record/inheritance.rb +32 -40
  136. data/lib/active_record/integration.rb +17 -14
  137. data/lib/active_record/internal_metadata.rb +56 -0
  138. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  139. data/lib/active_record/locale/en.yml +3 -2
  140. data/lib/active_record/locking/optimistic.rb +15 -15
  141. data/lib/active_record/locking/pessimistic.rb +1 -1
  142. data/lib/active_record/log_subscriber.rb +48 -24
  143. data/lib/active_record/migration.rb +362 -111
  144. data/lib/active_record/migration/command_recorder.rb +59 -18
  145. data/lib/active_record/migration/compatibility.rb +126 -0
  146. data/lib/active_record/model_schema.rb +270 -73
  147. data/lib/active_record/nested_attributes.rb +58 -29
  148. data/lib/active_record/no_touching.rb +4 -0
  149. data/lib/active_record/null_relation.rb +16 -8
  150. data/lib/active_record/persistence.rb +152 -90
  151. data/lib/active_record/query_cache.rb +18 -23
  152. data/lib/active_record/querying.rb +12 -11
  153. data/lib/active_record/railtie.rb +23 -16
  154. data/lib/active_record/railties/controller_runtime.rb +1 -1
  155. data/lib/active_record/railties/databases.rake +52 -41
  156. data/lib/active_record/readonly_attributes.rb +1 -1
  157. data/lib/active_record/reflection.rb +302 -115
  158. data/lib/active_record/relation.rb +187 -120
  159. data/lib/active_record/relation/batches.rb +141 -36
  160. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  161. data/lib/active_record/relation/calculations.rb +92 -117
  162. data/lib/active_record/relation/delegation.rb +8 -20
  163. data/lib/active_record/relation/finder_methods.rb +173 -89
  164. data/lib/active_record/relation/from_clause.rb +32 -0
  165. data/lib/active_record/relation/merger.rb +16 -42
  166. data/lib/active_record/relation/predicate_builder.rb +120 -107
  167. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  168. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  169. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  170. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  171. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  172. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  173. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  174. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  175. data/lib/active_record/relation/query_attribute.rb +19 -0
  176. data/lib/active_record/relation/query_methods.rb +308 -244
  177. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  178. data/lib/active_record/relation/spawn_methods.rb +4 -7
  179. data/lib/active_record/relation/where_clause.rb +174 -0
  180. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  181. data/lib/active_record/result.rb +11 -4
  182. data/lib/active_record/runtime_registry.rb +1 -1
  183. data/lib/active_record/sanitization.rb +105 -66
  184. data/lib/active_record/schema.rb +26 -22
  185. data/lib/active_record/schema_dumper.rb +54 -37
  186. data/lib/active_record/schema_migration.rb +11 -14
  187. data/lib/active_record/scoping.rb +34 -16
  188. data/lib/active_record/scoping/default.rb +28 -10
  189. data/lib/active_record/scoping/named.rb +59 -26
  190. data/lib/active_record/secure_token.rb +38 -0
  191. data/lib/active_record/serialization.rb +3 -5
  192. data/lib/active_record/statement_cache.rb +17 -15
  193. data/lib/active_record/store.rb +8 -3
  194. data/lib/active_record/suppressor.rb +58 -0
  195. data/lib/active_record/table_metadata.rb +69 -0
  196. data/lib/active_record/tasks/database_tasks.rb +66 -49
  197. data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
  198. data/lib/active_record/tasks/postgresql_database_tasks.rb +12 -3
  199. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  200. data/lib/active_record/timestamp.rb +20 -9
  201. data/lib/active_record/touch_later.rb +63 -0
  202. data/lib/active_record/transactions.rb +139 -57
  203. data/lib/active_record/type.rb +66 -17
  204. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  205. data/lib/active_record/type/date.rb +2 -45
  206. data/lib/active_record/type/date_time.rb +2 -49
  207. data/lib/active_record/type/internal/abstract_json.rb +33 -0
  208. data/lib/active_record/type/internal/timezone.rb +15 -0
  209. data/lib/active_record/type/serialized.rb +15 -14
  210. data/lib/active_record/type/time.rb +10 -16
  211. data/lib/active_record/type/type_map.rb +4 -4
  212. data/lib/active_record/type_caster.rb +7 -0
  213. data/lib/active_record/type_caster/connection.rb +29 -0
  214. data/lib/active_record/type_caster/map.rb +19 -0
  215. data/lib/active_record/validations.rb +33 -32
  216. data/lib/active_record/validations/absence.rb +23 -0
  217. data/lib/active_record/validations/associated.rb +10 -3
  218. data/lib/active_record/validations/length.rb +24 -0
  219. data/lib/active_record/validations/presence.rb +11 -12
  220. data/lib/active_record/validations/uniqueness.rb +33 -33
  221. data/lib/rails/generators/active_record/migration.rb +15 -0
  222. data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -5
  223. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  224. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  225. data/lib/rails/generators/active_record/model/model_generator.rb +33 -16
  226. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  227. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  228. metadata +58 -34
  229. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  230. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  231. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  232. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  233. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  234. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  235. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  236. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  237. data/lib/active_record/type/big_integer.rb +0 -13
  238. data/lib/active_record/type/binary.rb +0 -50
  239. data/lib/active_record/type/boolean.rb +0 -31
  240. data/lib/active_record/type/decimal.rb +0 -64
  241. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  242. data/lib/active_record/type/decorator.rb +0 -14
  243. data/lib/active_record/type/float.rb +0 -19
  244. data/lib/active_record/type/integer.rb +0 -59
  245. data/lib/active_record/type/mutable.rb +0 -16
  246. data/lib/active_record/type/numeric.rb +0 -36
  247. data/lib/active_record/type/string.rb +0 -40
  248. data/lib/active_record/type/text.rb +0 -11
  249. data/lib/active_record/type/time_value.rb +0 -38
  250. data/lib/active_record/type/unsigned_integer.rb +0 -15
  251. data/lib/active_record/type/value.rb +0 -110
@@ -1,5 +1,6 @@
1
+ require "set"
2
+ require "zlib"
1
3
  require "active_support/core_ext/module/attribute_accessors"
2
- require 'set'
3
4
 
4
5
  module ActiveRecord
5
6
  class MigrationError < ActiveRecordError#:nodoc:
@@ -9,40 +10,170 @@ module ActiveRecord
9
10
  end
10
11
  end
11
12
 
12
- # Exception that can be raised to stop migrations from going backwards.
13
+ # Exception that can be raised to stop migrations from being rolled back.
14
+ # For example the following migration is not reversible.
15
+ # Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
16
+ #
17
+ # class IrreversibleMigrationExample < ActiveRecord::Migration[5.0]
18
+ # def change
19
+ # create_table :distributors do |t|
20
+ # t.string :zipcode
21
+ # end
22
+ #
23
+ # execute <<-SQL
24
+ # ALTER TABLE distributors
25
+ # ADD CONSTRAINT zipchk
26
+ # CHECK (char_length(zipcode) = 5) NO INHERIT;
27
+ # SQL
28
+ # end
29
+ # end
30
+ #
31
+ # There are two ways to mitigate this problem.
32
+ #
33
+ # 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
34
+ #
35
+ # class ReversibleMigrationExample < ActiveRecord::Migration[5.0]
36
+ # def up
37
+ # create_table :distributors do |t|
38
+ # t.string :zipcode
39
+ # end
40
+ #
41
+ # execute <<-SQL
42
+ # ALTER TABLE distributors
43
+ # ADD CONSTRAINT zipchk
44
+ # CHECK (char_length(zipcode) = 5) NO INHERIT;
45
+ # SQL
46
+ # end
47
+ #
48
+ # def down
49
+ # execute <<-SQL
50
+ # ALTER TABLE distributors
51
+ # DROP CONSTRAINT zipchk
52
+ # SQL
53
+ #
54
+ # drop_table :distributors
55
+ # end
56
+ # end
57
+ #
58
+ # 2. Use the #reversible method in <tt>#change</tt> method:
59
+ #
60
+ # class ReversibleMigrationExample < ActiveRecord::Migration[5.0]
61
+ # def change
62
+ # create_table :distributors do |t|
63
+ # t.string :zipcode
64
+ # end
65
+ #
66
+ # reversible do |dir|
67
+ # dir.up do
68
+ # execute <<-SQL
69
+ # ALTER TABLE distributors
70
+ # ADD CONSTRAINT zipchk
71
+ # CHECK (char_length(zipcode) = 5) NO INHERIT;
72
+ # SQL
73
+ # end
74
+ #
75
+ # dir.down do
76
+ # execute <<-SQL
77
+ # ALTER TABLE distributors
78
+ # DROP CONSTRAINT zipchk
79
+ # SQL
80
+ # end
81
+ # end
82
+ # end
83
+ # end
13
84
  class IrreversibleMigration < MigrationError
14
85
  end
15
86
 
16
87
  class DuplicateMigrationVersionError < MigrationError#:nodoc:
17
- def initialize(version)
18
- super("Multiple migrations have the version number #{version}")
88
+ def initialize(version = nil)
89
+ if version
90
+ super("Multiple migrations have the version number #{version}.")
91
+ else
92
+ super("Duplicate migration version error.")
93
+ end
19
94
  end
20
95
  end
21
96
 
22
97
  class DuplicateMigrationNameError < MigrationError#:nodoc:
23
- def initialize(name)
24
- super("Multiple migrations have the name #{name}")
98
+ def initialize(name = nil)
99
+ if name
100
+ super("Multiple migrations have the name #{name}.")
101
+ else
102
+ super("Duplicate migration name.")
103
+ end
25
104
  end
26
105
  end
27
106
 
28
107
  class UnknownMigrationVersionError < MigrationError #:nodoc:
29
- def initialize(version)
30
- super("No migration with version number #{version}")
108
+ def initialize(version = nil)
109
+ if version
110
+ super("No migration with version number #{version}.")
111
+ else
112
+ super("Unknown migration version.")
113
+ end
31
114
  end
32
115
  end
33
116
 
34
117
  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)")
118
+ def initialize(name = nil)
119
+ if name
120
+ super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).")
121
+ else
122
+ super("Illegal name for migration.")
123
+ end
37
124
  end
38
125
  end
39
126
 
40
127
  class PendingMigrationError < MigrationError#:nodoc:
128
+ def initialize(message = nil)
129
+ if !message && defined?(Rails.env)
130
+ super("Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate RAILS_ENV=#{::Rails.env}")
131
+ elsif !message
132
+ super("Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate")
133
+ else
134
+ super
135
+ end
136
+ end
137
+ end
138
+
139
+ class ConcurrentMigrationError < MigrationError #:nodoc:
140
+ DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running.".freeze
141
+
142
+ def initialize(message = DEFAULT_MESSAGE)
143
+ super
144
+ end
145
+ end
146
+
147
+ class NoEnvironmentInSchemaError < MigrationError #:nodoc:
41
148
  def initialize
149
+ msg = "Environment data not found in the schema. To resolve this issue, run: \n\n bin/rails db:environment:set"
150
+ if defined?(Rails.env)
151
+ super("#{msg} RAILS_ENV=#{::Rails.env}")
152
+ else
153
+ super(msg)
154
+ end
155
+ end
156
+ end
157
+
158
+ class ProtectedEnvironmentError < ActiveRecordError #:nodoc:
159
+ def initialize(env = "production")
160
+ msg = "You are attempting to run a destructive action against your '#{env}' database.\n"
161
+ msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
162
+ msg << "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
163
+ super(msg)
164
+ end
165
+ end
166
+
167
+ class EnvironmentMismatchError < ActiveRecordError
168
+ def initialize(current: nil, stored: nil)
169
+ msg = "You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
170
+ msg << "You are running in `#{ current }` environment. "
171
+ msg << "If you are sure you want to continue, first set the environment using:\n\n"
172
+ msg << " bin/rails db:environment:set"
42
173
  if defined?(Rails.env)
43
- super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate RAILS_ENV=#{::Rails.env}")
174
+ super("#{msg} RAILS_ENV=#{::Rails.env}\n\n")
44
175
  else
45
- super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate")
176
+ super("#{msg}\n\n")
46
177
  end
47
178
  end
48
179
  end
@@ -59,7 +190,7 @@ module ActiveRecord
59
190
  #
60
191
  # Example of a simple migration:
61
192
  #
62
- # class AddSsl < ActiveRecord::Migration
193
+ # class AddSsl < ActiveRecord::Migration[5.0]
63
194
  # def up
64
195
  # add_column :accounts, :ssl_enabled, :boolean, default: true
65
196
  # end
@@ -79,7 +210,7 @@ module ActiveRecord
79
210
  #
80
211
  # Example of a more complex migration that also needs to initialize data:
81
212
  #
82
- # class AddSystemSettings < ActiveRecord::Migration
213
+ # class AddSystemSettings < ActiveRecord::Migration[5.0]
83
214
  # def up
84
215
  # create_table :system_settings do |t|
85
216
  # t.string :name
@@ -106,17 +237,18 @@ module ActiveRecord
106
237
  #
107
238
  # == Available transformations
108
239
  #
240
+ # === Creation
241
+ #
242
+ # * <tt>create_join_table(table_1, table_2, options)</tt>: Creates a join
243
+ # table having its name as the lexical order of the first two
244
+ # arguments. See
245
+ # ActiveRecord::ConnectionAdapters::SchemaStatements#create_join_table for
246
+ # details.
109
247
  # * <tt>create_table(name, options)</tt>: Creates a table called +name+ and
110
248
  # makes the table object available to a block that can then add columns to it,
111
249
  # following the same format as +add_column+. See example above. The options hash
112
250
  # is for fragments like "DEFAULT CHARSET=UTF-8" that are appended to the create
113
251
  # 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
252
  # * <tt>add_column(table_name, column_name, type, options)</tt>: Adds a new column
121
253
  # to the table called +table_name+
122
254
  # named +column_name+ specified to be one of the following types:
@@ -127,21 +259,59 @@ module ActiveRecord
127
259
  # Other options include <tt>:limit</tt> and <tt>:null</tt> (e.g.
128
260
  # <tt>{ limit: 50, null: false }</tt>) -- see
129
261
  # 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+.
262
+ # * <tt>add_foreign_key(from_table, to_table, options)</tt>: Adds a new
263
+ # foreign key. +from_table+ is the table with the key column, +to_table+ contains
264
+ # the referenced primary key.
136
265
  # * <tt>add_index(table_name, column_names, options)</tt>: Adds a new index
137
266
  # with the name of the column. Other options include
138
267
  # <tt>:name</tt>, <tt>:unique</tt> (e.g.
139
268
  # <tt>{ name: 'users_name_index', unique: true }</tt>) and <tt>:order</tt>
140
269
  # (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+.
270
+ # * <tt>add_reference(:table_name, :reference_name)</tt>: Adds a new column
271
+ # +reference_name_id+ by default an integer. See
272
+ # ActiveRecord::ConnectionAdapters::SchemaStatements#add_reference for details.
273
+ # * <tt>add_timestamps(table_name, options)</tt>: Adds timestamps (+created_at+
274
+ # and +updated_at+) columns to +table_name+.
275
+ #
276
+ # === Modification
277
+ #
278
+ # * <tt>change_column(table_name, column_name, type, options)</tt>: Changes
279
+ # the column to a different type using the same parameters as add_column.
280
+ # * <tt>change_column_default(table_name, column_name, default)</tt>: Sets a
281
+ # default value for +column_name+ defined by +default+ on +table_name+.
282
+ # * <tt>change_column_null(table_name, column_name, null, default = nil)</tt>:
283
+ # Sets or removes a +NOT NULL+ constraint on +column_name+. The +null+ flag
284
+ # indicates whether the value can be +NULL+. See
285
+ # ActiveRecord::ConnectionAdapters::SchemaStatements#change_column_null for
286
+ # details.
287
+ # * <tt>change_table(name, options)</tt>: Allows to make column alterations to
288
+ # the table called +name+. It makes the table object available to a block that
289
+ # can then add/remove columns, indexes or foreign keys to it.
290
+ # * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames
291
+ # a column but keeps the type and content.
292
+ # * <tt>rename_index(table_name, old_name, new_name)</tt>: Renames an index.
293
+ # * <tt>rename_table(old_name, new_name)</tt>: Renames the table called +old_name+
294
+ # to +new_name+.
295
+ #
296
+ # === Deletion
297
+ #
298
+ # * <tt>drop_table(name)</tt>: Drops the table called +name+.
299
+ # * <tt>drop_join_table(table_1, table_2, options)</tt>: Drops the join table
300
+ # specified by the given arguments.
301
+ # * <tt>remove_column(table_name, column_name, type, options)</tt>: Removes the column
302
+ # named +column_name+ from the table called +table_name+.
303
+ # * <tt>remove_columns(table_name, *column_names)</tt>: Removes the given
304
+ # columns from the table definition.
305
+ # * <tt>remove_foreign_key(from_table, options_or_to_table)</tt>: Removes the
306
+ # given foreign key from the table called +table_name+.
307
+ # * <tt>remove_index(table_name, column: column_names)</tt>: Removes the index
308
+ # specified by +column_names+.
143
309
  # * <tt>remove_index(table_name, name: index_name)</tt>: Removes the index
144
310
  # specified by +index_name+.
311
+ # * <tt>remove_reference(table_name, ref_name, options)</tt>: Removes the
312
+ # reference(s) on +table_name+ specified by +ref_name+.
313
+ # * <tt>remove_timestamps(table_name, options)</tt>: Removes the timestamp
314
+ # columns (+created_at+ and +updated_at+) from the table definition.
145
315
  #
146
316
  # == Irreversible transformations
147
317
  #
@@ -165,24 +335,24 @@ module ActiveRecord
165
335
  #
166
336
  # rails generate migration add_fieldname_to_tablename fieldname:string
167
337
  #
168
- # This will generate the file <tt>timestamp_add_fieldname_to_tablename</tt>, which will look like this:
169
- # class AddFieldnameToTablename < ActiveRecord::Migration
338
+ # This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
339
+ # class AddFieldnameToTablename < ActiveRecord::Migration[5.0]
170
340
  # def change
171
- # add_column :tablenames, :field, :string
341
+ # add_column :tablenames, :fieldname, :string
172
342
  # end
173
343
  # end
174
344
  #
175
345
  # 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
346
+ # <tt>rails db:migrate</tt>. This will update the database by running all of the
177
347
  # pending migrations, creating the <tt>schema_migrations</tt> table
178
348
  # (see "About the schema_migrations table" section below) if missing. It will also
179
349
  # invoke the db:schema:dump task, which will update your db/schema.rb file
180
350
  # to match the structure of your database.
181
351
  #
182
352
  # 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
353
+ # <tt>rails db:migrate VERSION=X</tt> where <tt>X</tt> is the version to which
184
354
  # 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
355
+ # wish to rollback last few migrations. <tt>rails db:migrate STEP=2</tt> will rollback
186
356
  # the latest two migrations.
187
357
  #
188
358
  # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
@@ -197,7 +367,7 @@ module ActiveRecord
197
367
  #
198
368
  # Not all migrations change the schema. Some just fix the data:
199
369
  #
200
- # class RemoveEmptyTags < ActiveRecord::Migration
370
+ # class RemoveEmptyTags < ActiveRecord::Migration[5.0]
201
371
  # def up
202
372
  # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
203
373
  # end
@@ -210,7 +380,7 @@ module ActiveRecord
210
380
  #
211
381
  # Others remove columns when they migrate up instead of down:
212
382
  #
213
- # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration
383
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[5.0]
214
384
  # def up
215
385
  # remove_column :items, :incomplete_items_count
216
386
  # remove_column :items, :completed_items_count
@@ -224,7 +394,7 @@ module ActiveRecord
224
394
  #
225
395
  # And sometimes you need to do something in SQL not abstracted directly by migrations:
226
396
  #
227
- # class MakeJoinUnique < ActiveRecord::Migration
397
+ # class MakeJoinUnique < ActiveRecord::Migration[5.0]
228
398
  # def up
229
399
  # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
230
400
  # end
@@ -241,7 +411,7 @@ module ActiveRecord
241
411
  # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
242
412
  # latest column data from after the new column was added. Example:
243
413
  #
244
- # class AddPeopleSalary < ActiveRecord::Migration
414
+ # class AddPeopleSalary < ActiveRecord::Migration[5.0]
245
415
  # def up
246
416
  # add_column :people, :salary, :integer
247
417
  # Person.reset_column_information
@@ -275,21 +445,6 @@ module ActiveRecord
275
445
  # The phrase "Updating salaries..." would then be printed, along with the
276
446
  # benchmark for the block when the block completes.
277
447
  #
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
448
  # == Timestamped Migrations
294
449
  #
295
450
  # By default, Rails generates migrations that look like:
@@ -314,7 +469,7 @@ module ActiveRecord
314
469
  # To define a reversible migration, define the +change+ method in your
315
470
  # migration like this:
316
471
  #
317
- # class TenderloveMigration < ActiveRecord::Migration
472
+ # class TenderloveMigration < ActiveRecord::Migration[5.0]
318
473
  # def change
319
474
  # create_table(:horses) do |t|
320
475
  # t.column :content, :text
@@ -344,7 +499,7 @@ module ActiveRecord
344
499
  # can't execute inside a transaction though, and for these situations
345
500
  # you can turn the automatic transactions off.
346
501
  #
347
- # class ChangeEnum < ActiveRecord::Migration
502
+ # class ChangeEnum < ActiveRecord::Migration[5.0]
348
503
  # disable_ddl_transaction!
349
504
  #
350
505
  # def up
@@ -356,10 +511,31 @@ module ActiveRecord
356
511
  # are in a Migration with <tt>self.disable_ddl_transaction!</tt>.
357
512
  class Migration
358
513
  autoload :CommandRecorder, 'active_record/migration/command_recorder'
514
+ autoload :Compatibility, 'active_record/migration/compatibility'
359
515
 
516
+ # This must be defined before the inherited hook, below
517
+ class Current < Migration # :nodoc:
518
+ end
519
+
520
+ def self.inherited(subclass) # :nodoc:
521
+ super
522
+ if subclass.superclass == Migration
523
+ subclass.include Compatibility::Legacy
524
+ end
525
+ end
526
+
527
+ def self.[](version)
528
+ Compatibility.find(version)
529
+ end
530
+
531
+ def self.current_version
532
+ ActiveRecord::VERSION::STRING.to_f
533
+ end
534
+
535
+ MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
360
536
 
361
537
  # This class is used to verify that all migrations have been run before
362
- # loading a web page if config.active_record.migration_error is set to :page_load
538
+ # loading a web page if <tt>config.active_record.migration_error</tt> is set to :page_load
363
539
  class CheckPending
364
540
  def initialize(app)
365
541
  @app = app
@@ -388,17 +564,22 @@ module ActiveRecord
388
564
  attr_accessor :delegate # :nodoc:
389
565
  attr_accessor :disable_ddl_transaction # :nodoc:
390
566
 
567
+ def nearest_delegate # :nodoc:
568
+ delegate || superclass.nearest_delegate
569
+ end
570
+
571
+ # Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending.
391
572
  def check_pending!(connection = Base.connection)
392
573
  raise ActiveRecord::PendingMigrationError if ActiveRecord::Migrator.needs_migration?(connection)
393
574
  end
394
575
 
395
576
  def load_schema_if_pending!
396
577
  if ActiveRecord::Migrator.needs_migration? || !ActiveRecord::Migrator.any_migrations?
397
- # Roundrip to Rake to allow plugins to hook into database initialization.
578
+ # Roundtrip to Rake to allow plugins to hook into database initialization.
398
579
  FileUtils.cd Rails.root do
399
580
  current_config = Base.connection_config
400
581
  Base.clear_all_connections!
401
- system("bin/rake db:test:prepare")
582
+ system("bin/rails db:test:prepare")
402
583
  # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
403
584
  Base.establish_connection(current_config)
404
585
  end
@@ -413,7 +594,7 @@ module ActiveRecord
413
594
  end
414
595
 
415
596
  def method_missing(name, *args, &block) # :nodoc:
416
- (delegate || superclass.delegate).send(name, *args, &block)
597
+ nearest_delegate.send(name, *args, &block)
417
598
  end
418
599
 
419
600
  def migrate(direction)
@@ -453,7 +634,7 @@ module ActiveRecord
453
634
  # and create the table 'apples' on the way up, and the reverse
454
635
  # on the way down.
455
636
  #
456
- # class FixTLMigration < ActiveRecord::Migration
637
+ # class FixTLMigration < ActiveRecord::Migration[5.0]
457
638
  # def change
458
639
  # revert do
459
640
  # create_table(:horses) do |t|
@@ -470,9 +651,9 @@ module ActiveRecord
470
651
  # Or equivalently, if +TenderloveMigration+ is defined as in the
471
652
  # documentation for Migration:
472
653
  #
473
- # require_relative '2012121212_tenderlove_migration'
654
+ # require_relative '20121212123456_tenderlove_migration'
474
655
  #
475
- # class FixupTLMigration < ActiveRecord::Migration
656
+ # class FixupTLMigration < ActiveRecord::Migration[5.0]
476
657
  # def change
477
658
  # revert TenderloveMigration
478
659
  #
@@ -486,13 +667,13 @@ module ActiveRecord
486
667
  def revert(*migration_classes)
487
668
  run(*migration_classes.reverse, revert: true) unless migration_classes.empty?
488
669
  if block_given?
489
- if @connection.respond_to? :revert
490
- @connection.revert { yield }
670
+ if connection.respond_to? :revert
671
+ connection.revert { yield }
491
672
  else
492
- recorder = CommandRecorder.new(@connection)
673
+ recorder = CommandRecorder.new(connection)
493
674
  @connection = recorder
494
675
  suppress_messages do
495
- @connection.revert { yield }
676
+ connection.revert { yield }
496
677
  end
497
678
  @connection = recorder.delegate
498
679
  recorder.commands.each do |cmd, args, block|
@@ -503,7 +684,7 @@ module ActiveRecord
503
684
  end
504
685
 
505
686
  def reverting?
506
- @connection.respond_to?(:reverting) && @connection.reverting
687
+ connection.respond_to?(:reverting) && connection.reverting
507
688
  end
508
689
 
509
690
  class ReversibleBlockHelper < Struct.new(:reverting) # :nodoc:
@@ -525,7 +706,7 @@ module ActiveRecord
525
706
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
526
707
  # even when migrating down:
527
708
  #
528
- # class SplitNameMigration < ActiveRecord::Migration
709
+ # class SplitNameMigration < ActiveRecord::Migration[5.0]
529
710
  # def change
530
711
  # add_column :users, :first_name, :string
531
712
  # add_column :users, :last_name, :string
@@ -560,7 +741,7 @@ module ActiveRecord
560
741
  revert { run(*migration_classes, direction: dir, revert: true) }
561
742
  else
562
743
  migration_classes.each do |migration_class|
563
- migration_class.new.exec_migration(@connection, dir)
744
+ migration_class.new.exec_migration(connection, dir)
564
745
  end
565
746
  end
566
747
  end
@@ -649,10 +830,10 @@ module ActiveRecord
649
830
  end
650
831
 
651
832
  def method_missing(method, *arguments, &block)
652
- arg_list = arguments.map{ |a| a.inspect } * ', '
833
+ arg_list = arguments.map(&:inspect) * ', '
653
834
 
654
835
  say_with_time "#{method}(#{arg_list})" do
655
- unless @connection.respond_to? :revert
836
+ unless connection.respond_to? :revert
656
837
  unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
657
838
  arguments[0] = proper_table_name(arguments.first, table_name_options)
658
839
  if [:rename_table, :add_foreign_key].include?(method) ||
@@ -731,7 +912,9 @@ module ActiveRecord
731
912
  end
732
913
  end
733
914
 
734
- def table_name_options(config = ActiveRecord::Base)
915
+ # Builds a hash for use in ActiveRecord::Migration#proper_table_name using
916
+ # the Active Record object's table_name prefix and suffix
917
+ def table_name_options(config = ActiveRecord::Base) #:nodoc:
735
918
  {
736
919
  table_name_prefix: config.table_name_prefix,
737
920
  table_name_suffix: config.table_name_suffix
@@ -823,7 +1006,7 @@ module ActiveRecord
823
1006
  new(:up, migrations, target_version).migrate
824
1007
  end
825
1008
 
826
- def down(migrations_paths, target_version = nil, &block)
1009
+ def down(migrations_paths, target_version = nil)
827
1010
  migrations = migrations(migrations_paths)
828
1011
  migrations.select! { |m| yield m } if block_given?
829
1012
 
@@ -843,10 +1026,12 @@ module ActiveRecord
843
1026
  end
844
1027
 
845
1028
  def get_all_versions(connection = Base.connection)
846
- if connection.table_exists?(schema_migrations_table_name)
847
- SchemaMigration.all.map { |x| x.version.to_i }.sort
848
- else
849
- []
1029
+ ActiveSupport::Deprecation.silence do
1030
+ if connection.table_exists?(schema_migrations_table_name)
1031
+ SchemaMigration.all.map { |x| x.version.to_i }.sort
1032
+ else
1033
+ []
1034
+ end
850
1035
  end
851
1036
  end
852
1037
 
@@ -862,26 +1047,18 @@ module ActiveRecord
862
1047
  migrations(migrations_paths).any?
863
1048
  end
864
1049
 
865
- def last_version
866
- last_migration.version
867
- end
868
-
869
1050
  def last_migration #:nodoc:
870
1051
  migrations(migrations_paths).last || NullMigration.new
871
1052
  end
872
1053
 
873
1054
  def migrations_paths
874
1055
  @migrations_paths ||= ['db/migrate']
875
- # just to not break things if someone uses: migration_path = some_string
1056
+ # just to not break things if someone uses: migrations_path = some_string
876
1057
  Array(@migrations_paths)
877
1058
  end
878
1059
 
879
- def migrations_path
880
- migrations_paths.first
881
- end
882
-
883
1060
  def parse_migration_filename(filename) # :nodoc:
884
- File.basename(filename).scan(/\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/).first
1061
+ File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
885
1062
  end
886
1063
 
887
1064
  def migrations(paths)
@@ -948,6 +1125,7 @@ module ActiveRecord
948
1125
  validate(@migrations)
949
1126
 
950
1127
  Base.connection.initialize_schema_migrations_table
1128
+ Base.connection.initialize_internal_metadata_table
951
1129
  end
952
1130
 
953
1131
  def current_version
@@ -960,32 +1138,18 @@ module ActiveRecord
960
1138
  alias :current :current_migration
961
1139
 
962
1140
  def run
963
- migration = migrations.detect { |m| m.version == @target_version }
964
- raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
965
- unless (up? && migrated.include?(migration.version.to_i)) || (down? && !migrated.include?(migration.version.to_i))
966
- begin
967
- execute_migration_in_transaction(migration, @direction)
968
- rescue => e
969
- canceled_msg = use_transaction?(migration) ? ", this migration was canceled" : ""
970
- raise StandardError, "An error has occurred#{canceled_msg}:\n\n#{e}", e.backtrace
971
- end
1141
+ if use_advisory_lock?
1142
+ with_advisory_lock { run_without_lock }
1143
+ else
1144
+ run_without_lock
972
1145
  end
973
1146
  end
974
1147
 
975
1148
  def migrate
976
- if !target && @target_version && @target_version > 0
977
- raise UnknownMigrationVersionError.new(@target_version)
978
- end
979
-
980
- runnable.each do |migration|
981
- Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
982
-
983
- begin
984
- execute_migration_in_transaction(migration, @direction)
985
- rescue => e
986
- canceled_msg = use_transaction?(migration) ? "this and " : ""
987
- raise StandardError, "An error has occurred, #{canceled_msg}all later migrations canceled:\n\n#{e}", e.backtrace
988
- end
1149
+ if use_advisory_lock?
1150
+ with_advisory_lock { migrate_without_lock }
1151
+ else
1152
+ migrate_without_lock
989
1153
  end
990
1154
  end
991
1155
 
@@ -1010,19 +1174,69 @@ module ActiveRecord
1010
1174
  end
1011
1175
 
1012
1176
  def migrated
1013
- @migrated_versions ||= Set.new(self.class.get_all_versions)
1177
+ @migrated_versions || load_migrated
1178
+ end
1179
+
1180
+ def load_migrated
1181
+ @migrated_versions = Set.new(self.class.get_all_versions)
1014
1182
  end
1015
1183
 
1016
1184
  private
1185
+
1186
+ # Used for running a specific migration.
1187
+ def run_without_lock
1188
+ migration = migrations.detect { |m| m.version == @target_version }
1189
+ raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
1190
+ result = execute_migration_in_transaction(migration, @direction)
1191
+
1192
+ record_environment
1193
+ result
1194
+ end
1195
+
1196
+ # Used for running multiple migrations up to or down to a certain value.
1197
+ def migrate_without_lock
1198
+ if invalid_target?
1199
+ raise UnknownMigrationVersionError.new(@target_version)
1200
+ end
1201
+
1202
+ result = runnable.each do |migration|
1203
+ execute_migration_in_transaction(migration, @direction)
1204
+ end
1205
+
1206
+ record_environment
1207
+ result
1208
+ end
1209
+
1210
+ # Stores the current environment in the database.
1211
+ def record_environment
1212
+ return if down?
1213
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
1214
+ end
1215
+
1017
1216
  def ran?(migration)
1018
1217
  migrated.include?(migration.version.to_i)
1019
1218
  end
1020
1219
 
1220
+ # Return true if a valid version is not provided.
1221
+ def invalid_target?
1222
+ !target && @target_version && @target_version > 0
1223
+ end
1224
+
1021
1225
  def execute_migration_in_transaction(migration, direction)
1226
+ return if down? && !migrated.include?(migration.version.to_i)
1227
+ return if up? && migrated.include?(migration.version.to_i)
1228
+
1229
+ Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
1230
+
1022
1231
  ddl_transaction(migration) do
1023
1232
  migration.migrate(direction)
1024
1233
  record_version_state_after_migrating(migration.version)
1025
1234
  end
1235
+ rescue => e
1236
+ msg = "An error has occurred, "
1237
+ msg << "this and " if use_transaction?(migration)
1238
+ msg << "all later migrations canceled:\n\n#{e}"
1239
+ raise StandardError, msg, e.backtrace
1026
1240
  end
1027
1241
 
1028
1242
  def target
@@ -1051,10 +1265,27 @@ module ActiveRecord
1051
1265
  ActiveRecord::SchemaMigration.where(:version => version.to_s).delete_all
1052
1266
  else
1053
1267
  migrated << version
1054
- ActiveRecord::SchemaMigration.create!(:version => version.to_s)
1268
+ ActiveRecord::SchemaMigration.create!(version: version.to_s)
1055
1269
  end
1056
1270
  end
1057
1271
 
1272
+ def self.last_stored_environment
1273
+ return nil if current_version == 0
1274
+ raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1275
+
1276
+ environment = ActiveRecord::InternalMetadata[:environment]
1277
+ raise NoEnvironmentInSchemaError unless environment
1278
+ environment
1279
+ end
1280
+
1281
+ def self.current_environment
1282
+ ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
1283
+ end
1284
+
1285
+ def self.protected_environment?
1286
+ ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
1287
+ end
1288
+
1058
1289
  def up?
1059
1290
  @direction == :up
1060
1291
  end
@@ -1075,5 +1306,25 @@ module ActiveRecord
1075
1306
  def use_transaction?(migration)
1076
1307
  !migration.disable_ddl_transaction && Base.connection.supports_ddl_transactions?
1077
1308
  end
1309
+
1310
+ def use_advisory_lock?
1311
+ Base.connection.supports_advisory_locks?
1312
+ end
1313
+
1314
+ def with_advisory_lock
1315
+ lock_id = generate_migrator_advisory_lock_id
1316
+ got_lock = Base.connection.get_advisory_lock(lock_id)
1317
+ raise ConcurrentMigrationError unless got_lock
1318
+ load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1319
+ yield
1320
+ ensure
1321
+ Base.connection.release_advisory_lock(lock_id) if got_lock
1322
+ end
1323
+
1324
+ MIGRATOR_SALT = 2053462845
1325
+ def generate_migrator_advisory_lock_id
1326
+ db_name_hash = Zlib.crc32(Base.connection.current_database)
1327
+ MIGRATOR_SALT * db_name_hash
1328
+ end
1078
1329
  end
1079
1330
  end