activerecord 5.2.3

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 (244) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +937 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +217 -0
  5. data/examples/performance.rb +185 -0
  6. data/examples/simple.rb +15 -0
  7. data/lib/active_record.rb +188 -0
  8. data/lib/active_record/aggregations.rb +283 -0
  9. data/lib/active_record/association_relation.rb +40 -0
  10. data/lib/active_record/associations.rb +1860 -0
  11. data/lib/active_record/associations/alias_tracker.rb +81 -0
  12. data/lib/active_record/associations/association.rb +299 -0
  13. data/lib/active_record/associations/association_scope.rb +168 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +130 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +40 -0
  16. data/lib/active_record/associations/builder/association.rb +140 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +163 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +82 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +135 -0
  20. data/lib/active_record/associations/builder/has_many.rb +17 -0
  21. data/lib/active_record/associations/builder/has_one.rb +30 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +42 -0
  23. data/lib/active_record/associations/collection_association.rb +513 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1131 -0
  25. data/lib/active_record/associations/foreign_association.rb +13 -0
  26. data/lib/active_record/associations/has_many_association.rb +144 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +227 -0
  28. data/lib/active_record/associations/has_one_association.rb +120 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency.rb +262 -0
  31. data/lib/active_record/associations/join_dependency/join_association.rb +60 -0
  32. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  33. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  34. data/lib/active_record/associations/preloader.rb +193 -0
  35. data/lib/active_record/associations/preloader/association.rb +131 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +107 -0
  37. data/lib/active_record/associations/singular_association.rb +73 -0
  38. data/lib/active_record/associations/through_association.rb +121 -0
  39. data/lib/active_record/attribute_assignment.rb +88 -0
  40. data/lib/active_record/attribute_decorators.rb +90 -0
  41. data/lib/active_record/attribute_methods.rb +492 -0
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +78 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +150 -0
  44. data/lib/active_record/attribute_methods/primary_key.rb +143 -0
  45. data/lib/active_record/attribute_methods/query.rb +42 -0
  46. data/lib/active_record/attribute_methods/read.rb +85 -0
  47. data/lib/active_record/attribute_methods/serialization.rb +90 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +91 -0
  49. data/lib/active_record/attribute_methods/write.rb +68 -0
  50. data/lib/active_record/attributes.rb +266 -0
  51. data/lib/active_record/autosave_association.rb +498 -0
  52. data/lib/active_record/base.rb +329 -0
  53. data/lib/active_record/callbacks.rb +353 -0
  54. data/lib/active_record/coders/json.rb +15 -0
  55. data/lib/active_record/coders/yaml_column.rb +50 -0
  56. data/lib/active_record/collection_cache_key.rb +53 -0
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1068 -0
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +72 -0
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +540 -0
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +145 -0
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +200 -0
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +146 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +685 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +95 -0
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1396 -0
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +283 -0
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +628 -0
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +887 -0
  70. data/lib/active_record/connection_adapters/column.rb +91 -0
  71. data/lib/active_record/connection_adapters/connection_specification.rb +287 -0
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  73. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  81. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  82. data/lib/active_record/connection_adapters/mysql2_adapter.rb +129 -0
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -0
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +163 -0
  85. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +56 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +111 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  109. data/lib/active_record/connection_adapters/postgresql/quoting.rb +168 -0
  110. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +206 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +774 -0
  115. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  116. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  117. data/lib/active_record/connection_adapters/postgresql_adapter.rb +863 -0
  118. data/lib/active_record/connection_adapters/schema_cache.rb +118 -0
  119. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +573 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +145 -0
  129. data/lib/active_record/core.rb +559 -0
  130. data/lib/active_record/counter_cache.rb +218 -0
  131. data/lib/active_record/define_callbacks.rb +22 -0
  132. data/lib/active_record/dynamic_matchers.rb +122 -0
  133. data/lib/active_record/enum.rb +244 -0
  134. data/lib/active_record/errors.rb +380 -0
  135. data/lib/active_record/explain.rb +50 -0
  136. data/lib/active_record/explain_registry.rb +32 -0
  137. data/lib/active_record/explain_subscriber.rb +34 -0
  138. data/lib/active_record/fixture_set/file.rb +82 -0
  139. data/lib/active_record/fixtures.rb +1065 -0
  140. data/lib/active_record/gem_version.rb +17 -0
  141. data/lib/active_record/inheritance.rb +283 -0
  142. data/lib/active_record/integration.rb +155 -0
  143. data/lib/active_record/internal_metadata.rb +45 -0
  144. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  145. data/lib/active_record/locale/en.yml +48 -0
  146. data/lib/active_record/locking/optimistic.rb +198 -0
  147. data/lib/active_record/locking/pessimistic.rb +89 -0
  148. data/lib/active_record/log_subscriber.rb +137 -0
  149. data/lib/active_record/migration.rb +1378 -0
  150. data/lib/active_record/migration/command_recorder.rb +240 -0
  151. data/lib/active_record/migration/compatibility.rb +217 -0
  152. data/lib/active_record/migration/join_table.rb +17 -0
  153. data/lib/active_record/model_schema.rb +521 -0
  154. data/lib/active_record/nested_attributes.rb +600 -0
  155. data/lib/active_record/no_touching.rb +58 -0
  156. data/lib/active_record/null_relation.rb +68 -0
  157. data/lib/active_record/persistence.rb +763 -0
  158. data/lib/active_record/query_cache.rb +45 -0
  159. data/lib/active_record/querying.rb +70 -0
  160. data/lib/active_record/railtie.rb +226 -0
  161. data/lib/active_record/railties/console_sandbox.rb +7 -0
  162. data/lib/active_record/railties/controller_runtime.rb +56 -0
  163. data/lib/active_record/railties/databases.rake +377 -0
  164. data/lib/active_record/readonly_attributes.rb +24 -0
  165. data/lib/active_record/reflection.rb +1044 -0
  166. data/lib/active_record/relation.rb +629 -0
  167. data/lib/active_record/relation/batches.rb +287 -0
  168. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  169. data/lib/active_record/relation/calculations.rb +417 -0
  170. data/lib/active_record/relation/delegation.rb +147 -0
  171. data/lib/active_record/relation/finder_methods.rb +565 -0
  172. data/lib/active_record/relation/from_clause.rb +26 -0
  173. data/lib/active_record/relation/merger.rb +193 -0
  174. data/lib/active_record/relation/predicate_builder.rb +152 -0
  175. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  176. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  177. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  178. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  179. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  180. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  181. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  182. data/lib/active_record/relation/query_attribute.rb +45 -0
  183. data/lib/active_record/relation/query_methods.rb +1231 -0
  184. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  185. data/lib/active_record/relation/spawn_methods.rb +77 -0
  186. data/lib/active_record/relation/where_clause.rb +186 -0
  187. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  188. data/lib/active_record/result.rb +149 -0
  189. data/lib/active_record/runtime_registry.rb +24 -0
  190. data/lib/active_record/sanitization.rb +222 -0
  191. data/lib/active_record/schema.rb +70 -0
  192. data/lib/active_record/schema_dumper.rb +255 -0
  193. data/lib/active_record/schema_migration.rb +56 -0
  194. data/lib/active_record/scoping.rb +106 -0
  195. data/lib/active_record/scoping/default.rb +152 -0
  196. data/lib/active_record/scoping/named.rb +213 -0
  197. data/lib/active_record/secure_token.rb +40 -0
  198. data/lib/active_record/serialization.rb +22 -0
  199. data/lib/active_record/statement_cache.rb +121 -0
  200. data/lib/active_record/store.rb +211 -0
  201. data/lib/active_record/suppressor.rb +61 -0
  202. data/lib/active_record/table_metadata.rb +82 -0
  203. data/lib/active_record/tasks/database_tasks.rb +337 -0
  204. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  205. data/lib/active_record/tasks/postgresql_database_tasks.rb +143 -0
  206. data/lib/active_record/tasks/sqlite_database_tasks.rb +83 -0
  207. data/lib/active_record/timestamp.rb +153 -0
  208. data/lib/active_record/touch_later.rb +64 -0
  209. data/lib/active_record/transactions.rb +502 -0
  210. data/lib/active_record/translation.rb +24 -0
  211. data/lib/active_record/type.rb +79 -0
  212. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  213. data/lib/active_record/type/date.rb +9 -0
  214. data/lib/active_record/type/date_time.rb +9 -0
  215. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  216. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  217. data/lib/active_record/type/internal/timezone.rb +17 -0
  218. data/lib/active_record/type/json.rb +30 -0
  219. data/lib/active_record/type/serialized.rb +71 -0
  220. data/lib/active_record/type/text.rb +11 -0
  221. data/lib/active_record/type/time.rb +21 -0
  222. data/lib/active_record/type/type_map.rb +62 -0
  223. data/lib/active_record/type/unsigned_integer.rb +17 -0
  224. data/lib/active_record/type_caster.rb +9 -0
  225. data/lib/active_record/type_caster/connection.rb +33 -0
  226. data/lib/active_record/type_caster/map.rb +23 -0
  227. data/lib/active_record/validations.rb +93 -0
  228. data/lib/active_record/validations/absence.rb +25 -0
  229. data/lib/active_record/validations/associated.rb +60 -0
  230. data/lib/active_record/validations/length.rb +26 -0
  231. data/lib/active_record/validations/presence.rb +68 -0
  232. data/lib/active_record/validations/uniqueness.rb +238 -0
  233. data/lib/active_record/version.rb +10 -0
  234. data/lib/rails/generators/active_record.rb +19 -0
  235. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  236. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  237. data/lib/rails/generators/active_record/migration.rb +35 -0
  238. data/lib/rails/generators/active_record/migration/migration_generator.rb +78 -0
  239. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  240. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +46 -0
  241. data/lib/rails/generators/active_record/model/model_generator.rb +48 -0
  242. data/lib/rails/generators/active_record/model/templates/model.rb.tt +13 -0
  243. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  244. metadata +333 -0
@@ -0,0 +1,1378 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "zlib"
5
+ require "active_support/core_ext/module/attribute_accessors"
6
+
7
+ module ActiveRecord
8
+ class MigrationError < ActiveRecordError#:nodoc:
9
+ def initialize(message = nil)
10
+ message = "\n\n#{message}\n\n" if message
11
+ super
12
+ end
13
+ end
14
+
15
+ # Exception that can be raised to stop migrations from being rolled back.
16
+ # For example the following migration is not reversible.
17
+ # Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
18
+ #
19
+ # class IrreversibleMigrationExample < ActiveRecord::Migration[5.0]
20
+ # def change
21
+ # create_table :distributors do |t|
22
+ # t.string :zipcode
23
+ # end
24
+ #
25
+ # execute <<-SQL
26
+ # ALTER TABLE distributors
27
+ # ADD CONSTRAINT zipchk
28
+ # CHECK (char_length(zipcode) = 5) NO INHERIT;
29
+ # SQL
30
+ # end
31
+ # end
32
+ #
33
+ # There are two ways to mitigate this problem.
34
+ #
35
+ # 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
36
+ #
37
+ # class ReversibleMigrationExample < ActiveRecord::Migration[5.0]
38
+ # def up
39
+ # create_table :distributors do |t|
40
+ # t.string :zipcode
41
+ # end
42
+ #
43
+ # execute <<-SQL
44
+ # ALTER TABLE distributors
45
+ # ADD CONSTRAINT zipchk
46
+ # CHECK (char_length(zipcode) = 5) NO INHERIT;
47
+ # SQL
48
+ # end
49
+ #
50
+ # def down
51
+ # execute <<-SQL
52
+ # ALTER TABLE distributors
53
+ # DROP CONSTRAINT zipchk
54
+ # SQL
55
+ #
56
+ # drop_table :distributors
57
+ # end
58
+ # end
59
+ #
60
+ # 2. Use the #reversible method in <tt>#change</tt> method:
61
+ #
62
+ # class ReversibleMigrationExample < ActiveRecord::Migration[5.0]
63
+ # def change
64
+ # create_table :distributors do |t|
65
+ # t.string :zipcode
66
+ # end
67
+ #
68
+ # reversible do |dir|
69
+ # dir.up do
70
+ # execute <<-SQL
71
+ # ALTER TABLE distributors
72
+ # ADD CONSTRAINT zipchk
73
+ # CHECK (char_length(zipcode) = 5) NO INHERIT;
74
+ # SQL
75
+ # end
76
+ #
77
+ # dir.down do
78
+ # execute <<-SQL
79
+ # ALTER TABLE distributors
80
+ # DROP CONSTRAINT zipchk
81
+ # SQL
82
+ # end
83
+ # end
84
+ # end
85
+ # end
86
+ class IrreversibleMigration < MigrationError
87
+ end
88
+
89
+ class DuplicateMigrationVersionError < MigrationError#:nodoc:
90
+ def initialize(version = nil)
91
+ if version
92
+ super("Multiple migrations have the version number #{version}.")
93
+ else
94
+ super("Duplicate migration version error.")
95
+ end
96
+ end
97
+ end
98
+
99
+ class DuplicateMigrationNameError < MigrationError#:nodoc:
100
+ def initialize(name = nil)
101
+ if name
102
+ super("Multiple migrations have the name #{name}.")
103
+ else
104
+ super("Duplicate migration name.")
105
+ end
106
+ end
107
+ end
108
+
109
+ class UnknownMigrationVersionError < MigrationError #:nodoc:
110
+ def initialize(version = nil)
111
+ if version
112
+ super("No migration with version number #{version}.")
113
+ else
114
+ super("Unknown migration version.")
115
+ end
116
+ end
117
+ end
118
+
119
+ class IllegalMigrationNameError < MigrationError#:nodoc:
120
+ def initialize(name = nil)
121
+ if name
122
+ super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).")
123
+ else
124
+ super("Illegal name for migration.")
125
+ end
126
+ end
127
+ end
128
+
129
+ class PendingMigrationError < MigrationError#:nodoc:
130
+ def initialize(message = nil)
131
+ if !message && defined?(Rails.env)
132
+ super("Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate RAILS_ENV=#{::Rails.env}")
133
+ elsif !message
134
+ super("Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate")
135
+ else
136
+ super
137
+ end
138
+ end
139
+ end
140
+
141
+ class ConcurrentMigrationError < MigrationError #:nodoc:
142
+ DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running.".freeze
143
+ RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock".freeze
144
+
145
+ def initialize(message = DEFAULT_MESSAGE)
146
+ super
147
+ end
148
+ end
149
+
150
+ class NoEnvironmentInSchemaError < MigrationError #:nodoc:
151
+ def initialize
152
+ msg = "Environment data not found in the schema. To resolve this issue, run: \n\n bin/rails db:environment:set"
153
+ if defined?(Rails.env)
154
+ super("#{msg} RAILS_ENV=#{::Rails.env}")
155
+ else
156
+ super(msg)
157
+ end
158
+ end
159
+ end
160
+
161
+ class ProtectedEnvironmentError < ActiveRecordError #:nodoc:
162
+ def initialize(env = "production")
163
+ msg = "You are attempting to run a destructive action against your '#{env}' database.\n".dup
164
+ msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
165
+ msg << "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
166
+ super(msg)
167
+ end
168
+ end
169
+
170
+ class EnvironmentMismatchError < ActiveRecordError
171
+ def initialize(current: nil, stored: nil)
172
+ msg = "You are attempting to modify a database that was last run in `#{ stored }` environment.\n".dup
173
+ msg << "You are running in `#{ current }` environment. "
174
+ msg << "If you are sure you want to continue, first set the environment using:\n\n"
175
+ msg << " bin/rails db:environment:set"
176
+ if defined?(Rails.env)
177
+ super("#{msg} RAILS_ENV=#{::Rails.env}\n\n")
178
+ else
179
+ super("#{msg}\n\n")
180
+ end
181
+ end
182
+ end
183
+
184
+ # = Active Record Migrations
185
+ #
186
+ # Migrations can manage the evolution of a schema used by several physical
187
+ # databases. It's a solution to the common problem of adding a field to make
188
+ # a new feature work in your local database, but being unsure of how to
189
+ # push that change to other developers and to the production server. With
190
+ # migrations, you can describe the transformations in self-contained classes
191
+ # that can be checked into version control systems and executed against
192
+ # another database that might be one, two, or five versions behind.
193
+ #
194
+ # Example of a simple migration:
195
+ #
196
+ # class AddSsl < ActiveRecord::Migration[5.0]
197
+ # def up
198
+ # add_column :accounts, :ssl_enabled, :boolean, default: true
199
+ # end
200
+ #
201
+ # def down
202
+ # remove_column :accounts, :ssl_enabled
203
+ # end
204
+ # end
205
+ #
206
+ # This migration will add a boolean flag to the accounts table and remove it
207
+ # if you're backing out of the migration. It shows how all migrations have
208
+ # two methods +up+ and +down+ that describes the transformations
209
+ # required to implement or remove the migration. These methods can consist
210
+ # of both the migration specific methods like +add_column+ and +remove_column+,
211
+ # but may also contain regular Ruby code for generating data needed for the
212
+ # transformations.
213
+ #
214
+ # Example of a more complex migration that also needs to initialize data:
215
+ #
216
+ # class AddSystemSettings < ActiveRecord::Migration[5.0]
217
+ # def up
218
+ # create_table :system_settings do |t|
219
+ # t.string :name
220
+ # t.string :label
221
+ # t.text :value
222
+ # t.string :type
223
+ # t.integer :position
224
+ # end
225
+ #
226
+ # SystemSetting.create name: 'notice',
227
+ # label: 'Use notice?',
228
+ # value: 1
229
+ # end
230
+ #
231
+ # def down
232
+ # drop_table :system_settings
233
+ # end
234
+ # end
235
+ #
236
+ # This migration first adds the +system_settings+ table, then creates the very
237
+ # first row in it using the Active Record model that relies on the table. It
238
+ # also uses the more advanced +create_table+ syntax where you can specify a
239
+ # complete table schema in one block call.
240
+ #
241
+ # == Available transformations
242
+ #
243
+ # === Creation
244
+ #
245
+ # * <tt>create_join_table(table_1, table_2, options)</tt>: Creates a join
246
+ # table having its name as the lexical order of the first two
247
+ # arguments. See
248
+ # ActiveRecord::ConnectionAdapters::SchemaStatements#create_join_table for
249
+ # details.
250
+ # * <tt>create_table(name, options)</tt>: Creates a table called +name+ and
251
+ # makes the table object available to a block that can then add columns to it,
252
+ # following the same format as +add_column+. See example above. The options hash
253
+ # is for fragments like "DEFAULT CHARSET=UTF-8" that are appended to the create
254
+ # table definition.
255
+ # * <tt>add_column(table_name, column_name, type, options)</tt>: Adds a new column
256
+ # to the table called +table_name+
257
+ # named +column_name+ specified to be one of the following types:
258
+ # <tt>:string</tt>, <tt>:text</tt>, <tt>:integer</tt>, <tt>:float</tt>,
259
+ # <tt>:decimal</tt>, <tt>:datetime</tt>, <tt>:timestamp</tt>, <tt>:time</tt>,
260
+ # <tt>:date</tt>, <tt>:binary</tt>, <tt>:boolean</tt>. A default value can be
261
+ # specified by passing an +options+ hash like <tt>{ default: 11 }</tt>.
262
+ # Other options include <tt>:limit</tt> and <tt>:null</tt> (e.g.
263
+ # <tt>{ limit: 50, null: false }</tt>) -- see
264
+ # ActiveRecord::ConnectionAdapters::TableDefinition#column for details.
265
+ # * <tt>add_foreign_key(from_table, to_table, options)</tt>: Adds a new
266
+ # foreign key. +from_table+ is the table with the key column, +to_table+ contains
267
+ # the referenced primary key.
268
+ # * <tt>add_index(table_name, column_names, options)</tt>: Adds a new index
269
+ # with the name of the column. Other options include
270
+ # <tt>:name</tt>, <tt>:unique</tt> (e.g.
271
+ # <tt>{ name: 'users_name_index', unique: true }</tt>) and <tt>:order</tt>
272
+ # (e.g. <tt>{ order: { name: :desc } }</tt>).
273
+ # * <tt>add_reference(:table_name, :reference_name)</tt>: Adds a new column
274
+ # +reference_name_id+ by default an integer. See
275
+ # ActiveRecord::ConnectionAdapters::SchemaStatements#add_reference for details.
276
+ # * <tt>add_timestamps(table_name, options)</tt>: Adds timestamps (+created_at+
277
+ # and +updated_at+) columns to +table_name+.
278
+ #
279
+ # === Modification
280
+ #
281
+ # * <tt>change_column(table_name, column_name, type, options)</tt>: Changes
282
+ # the column to a different type using the same parameters as add_column.
283
+ # * <tt>change_column_default(table_name, column_name, default_or_changes)</tt>:
284
+ # Sets a default value for +column_name+ defined by +default_or_changes+ on
285
+ # +table_name+. Passing a hash containing <tt>:from</tt> and <tt>:to</tt>
286
+ # as +default_or_changes+ will make this change reversible in the migration.
287
+ # * <tt>change_column_null(table_name, column_name, null, default = nil)</tt>:
288
+ # Sets or removes a +NOT NULL+ constraint on +column_name+. The +null+ flag
289
+ # indicates whether the value can be +NULL+. See
290
+ # ActiveRecord::ConnectionAdapters::SchemaStatements#change_column_null for
291
+ # details.
292
+ # * <tt>change_table(name, options)</tt>: Allows to make column alterations to
293
+ # the table called +name+. It makes the table object available to a block that
294
+ # can then add/remove columns, indexes or foreign keys to it.
295
+ # * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames
296
+ # a column but keeps the type and content.
297
+ # * <tt>rename_index(table_name, old_name, new_name)</tt>: Renames an index.
298
+ # * <tt>rename_table(old_name, new_name)</tt>: Renames the table called +old_name+
299
+ # to +new_name+.
300
+ #
301
+ # === Deletion
302
+ #
303
+ # * <tt>drop_table(name)</tt>: Drops the table called +name+.
304
+ # * <tt>drop_join_table(table_1, table_2, options)</tt>: Drops the join table
305
+ # specified by the given arguments.
306
+ # * <tt>remove_column(table_name, column_name, type, options)</tt>: Removes the column
307
+ # named +column_name+ from the table called +table_name+.
308
+ # * <tt>remove_columns(table_name, *column_names)</tt>: Removes the given
309
+ # columns from the table definition.
310
+ # * <tt>remove_foreign_key(from_table, options_or_to_table)</tt>: Removes the
311
+ # given foreign key from the table called +table_name+.
312
+ # * <tt>remove_index(table_name, column: column_names)</tt>: Removes the index
313
+ # specified by +column_names+.
314
+ # * <tt>remove_index(table_name, name: index_name)</tt>: Removes the index
315
+ # specified by +index_name+.
316
+ # * <tt>remove_reference(table_name, ref_name, options)</tt>: Removes the
317
+ # reference(s) on +table_name+ specified by +ref_name+.
318
+ # * <tt>remove_timestamps(table_name, options)</tt>: Removes the timestamp
319
+ # columns (+created_at+ and +updated_at+) from the table definition.
320
+ #
321
+ # == Irreversible transformations
322
+ #
323
+ # Some transformations are destructive in a manner that cannot be reversed.
324
+ # Migrations of that kind should raise an <tt>ActiveRecord::IrreversibleMigration</tt>
325
+ # exception in their +down+ method.
326
+ #
327
+ # == Running migrations from within Rails
328
+ #
329
+ # The Rails package has several tools to help create and apply migrations.
330
+ #
331
+ # To generate a new migration, you can use
332
+ # rails generate migration MyNewMigration
333
+ #
334
+ # where MyNewMigration is the name of your migration. The generator will
335
+ # create an empty migration file <tt>timestamp_my_new_migration.rb</tt>
336
+ # in the <tt>db/migrate/</tt> directory where <tt>timestamp</tt> is the
337
+ # UTC formatted date and time that the migration was generated.
338
+ #
339
+ # There is a special syntactic shortcut to generate migrations that add fields to a table.
340
+ #
341
+ # rails generate migration add_fieldname_to_tablename fieldname:string
342
+ #
343
+ # This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
344
+ # class AddFieldnameToTablename < ActiveRecord::Migration[5.0]
345
+ # def change
346
+ # add_column :tablenames, :fieldname, :string
347
+ # end
348
+ # end
349
+ #
350
+ # To run migrations against the currently configured database, use
351
+ # <tt>rails db:migrate</tt>. This will update the database by running all of the
352
+ # pending migrations, creating the <tt>schema_migrations</tt> table
353
+ # (see "About the schema_migrations table" section below) if missing. It will also
354
+ # invoke the db:schema:dump task, which will update your db/schema.rb file
355
+ # to match the structure of your database.
356
+ #
357
+ # To roll the database back to a previous migration version, use
358
+ # <tt>rails db:rollback VERSION=X</tt> where <tt>X</tt> is the version to which
359
+ # you wish to downgrade. Alternatively, you can also use the STEP option if you
360
+ # wish to rollback last few migrations. <tt>rails db:rollback STEP=2</tt> will rollback
361
+ # the latest two migrations.
362
+ #
363
+ # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
364
+ # that step will fail and you'll have some manual work to do.
365
+ #
366
+ # == Database support
367
+ #
368
+ # Migrations are currently supported in MySQL, PostgreSQL, SQLite,
369
+ # SQL Server, and Oracle (all supported databases except DB2).
370
+ #
371
+ # == More examples
372
+ #
373
+ # Not all migrations change the schema. Some just fix the data:
374
+ #
375
+ # class RemoveEmptyTags < ActiveRecord::Migration[5.0]
376
+ # def up
377
+ # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
378
+ # end
379
+ #
380
+ # def down
381
+ # # not much we can do to restore deleted data
382
+ # raise ActiveRecord::IrreversibleMigration, "Can't recover the deleted tags"
383
+ # end
384
+ # end
385
+ #
386
+ # Others remove columns when they migrate up instead of down:
387
+ #
388
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[5.0]
389
+ # def up
390
+ # remove_column :items, :incomplete_items_count
391
+ # remove_column :items, :completed_items_count
392
+ # end
393
+ #
394
+ # def down
395
+ # add_column :items, :incomplete_items_count
396
+ # add_column :items, :completed_items_count
397
+ # end
398
+ # end
399
+ #
400
+ # And sometimes you need to do something in SQL not abstracted directly by migrations:
401
+ #
402
+ # class MakeJoinUnique < ActiveRecord::Migration[5.0]
403
+ # def up
404
+ # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
405
+ # end
406
+ #
407
+ # def down
408
+ # execute "ALTER TABLE `pages_linked_pages` DROP INDEX `page_id_linked_page_id`"
409
+ # end
410
+ # end
411
+ #
412
+ # == Using a model after changing its table
413
+ #
414
+ # Sometimes you'll want to add a column in a migration and populate it
415
+ # immediately after. In that case, you'll need to make a call to
416
+ # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
417
+ # latest column data from after the new column was added. Example:
418
+ #
419
+ # class AddPeopleSalary < ActiveRecord::Migration[5.0]
420
+ # def up
421
+ # add_column :people, :salary, :integer
422
+ # Person.reset_column_information
423
+ # Person.all.each do |p|
424
+ # p.update_attribute :salary, SalaryCalculator.compute(p)
425
+ # end
426
+ # end
427
+ # end
428
+ #
429
+ # == Controlling verbosity
430
+ #
431
+ # By default, migrations will describe the actions they are taking, writing
432
+ # them to the console as they happen, along with benchmarks describing how
433
+ # long each step took.
434
+ #
435
+ # You can quiet them down by setting ActiveRecord::Migration.verbose = false.
436
+ #
437
+ # You can also insert your own messages and benchmarks by using the +say_with_time+
438
+ # method:
439
+ #
440
+ # def up
441
+ # ...
442
+ # say_with_time "Updating salaries..." do
443
+ # Person.all.each do |p|
444
+ # p.update_attribute :salary, SalaryCalculator.compute(p)
445
+ # end
446
+ # end
447
+ # ...
448
+ # end
449
+ #
450
+ # The phrase "Updating salaries..." would then be printed, along with the
451
+ # benchmark for the block when the block completes.
452
+ #
453
+ # == Timestamped Migrations
454
+ #
455
+ # By default, Rails generates migrations that look like:
456
+ #
457
+ # 20080717013526_your_migration_name.rb
458
+ #
459
+ # The prefix is a generation timestamp (in UTC).
460
+ #
461
+ # If you'd prefer to use numeric prefixes, you can turn timestamped migrations
462
+ # off by setting:
463
+ #
464
+ # config.active_record.timestamped_migrations = false
465
+ #
466
+ # In application.rb.
467
+ #
468
+ # == Reversible Migrations
469
+ #
470
+ # Reversible migrations are migrations that know how to go +down+ for you.
471
+ # You simply supply the +up+ logic, and the Migration system figures out
472
+ # how to execute the down commands for you.
473
+ #
474
+ # To define a reversible migration, define the +change+ method in your
475
+ # migration like this:
476
+ #
477
+ # class TenderloveMigration < ActiveRecord::Migration[5.0]
478
+ # def change
479
+ # create_table(:horses) do |t|
480
+ # t.column :content, :text
481
+ # t.column :remind_at, :datetime
482
+ # end
483
+ # end
484
+ # end
485
+ #
486
+ # This migration will create the horses table for you on the way up, and
487
+ # automatically figure out how to drop the table on the way down.
488
+ #
489
+ # Some commands like +remove_column+ cannot be reversed. If you care to
490
+ # define how to move up and down in these cases, you should define the +up+
491
+ # and +down+ methods as before.
492
+ #
493
+ # If a command cannot be reversed, an
494
+ # <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
495
+ # the migration is moving down.
496
+ #
497
+ # For a list of commands that are reversible, please see
498
+ # <tt>ActiveRecord::Migration::CommandRecorder</tt>.
499
+ #
500
+ # == Transactional Migrations
501
+ #
502
+ # If the database adapter supports DDL transactions, all migrations will
503
+ # automatically be wrapped in a transaction. There are queries that you
504
+ # can't execute inside a transaction though, and for these situations
505
+ # you can turn the automatic transactions off.
506
+ #
507
+ # class ChangeEnum < ActiveRecord::Migration[5.0]
508
+ # disable_ddl_transaction!
509
+ #
510
+ # def up
511
+ # execute "ALTER TYPE model_size ADD VALUE 'new_value'"
512
+ # end
513
+ # end
514
+ #
515
+ # Remember that you can still open your own transactions, even if you
516
+ # are in a Migration with <tt>self.disable_ddl_transaction!</tt>.
517
+ class Migration
518
+ autoload :CommandRecorder, "active_record/migration/command_recorder"
519
+ autoload :Compatibility, "active_record/migration/compatibility"
520
+
521
+ # This must be defined before the inherited hook, below
522
+ class Current < Migration # :nodoc:
523
+ end
524
+
525
+ def self.inherited(subclass) # :nodoc:
526
+ super
527
+ if subclass.superclass == Migration
528
+ raise StandardError, "Directly inheriting from ActiveRecord::Migration is not supported. " \
529
+ "Please specify the Rails release the migration was written for:\n" \
530
+ "\n" \
531
+ " class #{subclass} < ActiveRecord::Migration[4.2]"
532
+ end
533
+ end
534
+
535
+ def self.[](version)
536
+ Compatibility.find(version)
537
+ end
538
+
539
+ def self.current_version
540
+ ActiveRecord::VERSION::STRING.to_f
541
+ end
542
+
543
+ MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
544
+
545
+ # This class is used to verify that all migrations have been run before
546
+ # loading a web page if <tt>config.active_record.migration_error</tt> is set to :page_load
547
+ class CheckPending
548
+ def initialize(app)
549
+ @app = app
550
+ @last_check = 0
551
+ end
552
+
553
+ def call(env)
554
+ mtime = ActiveRecord::Base.connection.migration_context.last_migration.mtime.to_i
555
+ if @last_check < mtime
556
+ ActiveRecord::Migration.check_pending!(connection)
557
+ @last_check = mtime
558
+ end
559
+ @app.call(env)
560
+ end
561
+
562
+ private
563
+
564
+ def connection
565
+ ActiveRecord::Base.connection
566
+ end
567
+ end
568
+
569
+ class << self
570
+ attr_accessor :delegate # :nodoc:
571
+ attr_accessor :disable_ddl_transaction # :nodoc:
572
+
573
+ def nearest_delegate # :nodoc:
574
+ delegate || superclass.nearest_delegate
575
+ end
576
+
577
+ # Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending.
578
+ def check_pending!(connection = Base.connection)
579
+ raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration?
580
+ end
581
+
582
+ def load_schema_if_pending!
583
+ if Base.connection.migration_context.needs_migration? || !Base.connection.migration_context.any_migrations?
584
+ # Roundtrip to Rake to allow plugins to hook into database initialization.
585
+ root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
586
+ FileUtils.cd(root) do
587
+ current_config = Base.connection_config
588
+ Base.clear_all_connections!
589
+ system("bin/rails db:test:prepare")
590
+ # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
591
+ Base.establish_connection(current_config)
592
+ end
593
+ check_pending!
594
+ end
595
+ end
596
+
597
+ def maintain_test_schema! # :nodoc:
598
+ if ActiveRecord::Base.maintain_test_schema
599
+ suppress_messages { load_schema_if_pending! }
600
+ end
601
+ end
602
+
603
+ def method_missing(name, *args, &block) # :nodoc:
604
+ nearest_delegate.send(name, *args, &block)
605
+ end
606
+
607
+ def migrate(direction)
608
+ new.migrate direction
609
+ end
610
+
611
+ # Disable the transaction wrapping this migration.
612
+ # You can still create your own transactions even after calling #disable_ddl_transaction!
613
+ #
614
+ # For more details read the {"Transactional Migrations" section above}[rdoc-ref:Migration].
615
+ def disable_ddl_transaction!
616
+ @disable_ddl_transaction = true
617
+ end
618
+ end
619
+
620
+ def disable_ddl_transaction # :nodoc:
621
+ self.class.disable_ddl_transaction
622
+ end
623
+
624
+ cattr_accessor :verbose
625
+ attr_accessor :name, :version
626
+
627
+ def initialize(name = self.class.name, version = nil)
628
+ @name = name
629
+ @version = version
630
+ @connection = nil
631
+ end
632
+
633
+ self.verbose = true
634
+ # instantiate the delegate object after initialize is defined
635
+ self.delegate = new
636
+
637
+ # Reverses the migration commands for the given block and
638
+ # the given migrations.
639
+ #
640
+ # The following migration will remove the table 'horses'
641
+ # and create the table 'apples' on the way up, and the reverse
642
+ # on the way down.
643
+ #
644
+ # class FixTLMigration < ActiveRecord::Migration[5.0]
645
+ # def change
646
+ # revert do
647
+ # create_table(:horses) do |t|
648
+ # t.text :content
649
+ # t.datetime :remind_at
650
+ # end
651
+ # end
652
+ # create_table(:apples) do |t|
653
+ # t.string :variety
654
+ # end
655
+ # end
656
+ # end
657
+ #
658
+ # Or equivalently, if +TenderloveMigration+ is defined as in the
659
+ # documentation for Migration:
660
+ #
661
+ # require_relative '20121212123456_tenderlove_migration'
662
+ #
663
+ # class FixupTLMigration < ActiveRecord::Migration[5.0]
664
+ # def change
665
+ # revert TenderloveMigration
666
+ #
667
+ # create_table(:apples) do |t|
668
+ # t.string :variety
669
+ # end
670
+ # end
671
+ # end
672
+ #
673
+ # This command can be nested.
674
+ def revert(*migration_classes)
675
+ run(*migration_classes.reverse, revert: true) unless migration_classes.empty?
676
+ if block_given?
677
+ if connection.respond_to? :revert
678
+ connection.revert { yield }
679
+ else
680
+ recorder = CommandRecorder.new(connection)
681
+ @connection = recorder
682
+ suppress_messages do
683
+ connection.revert { yield }
684
+ end
685
+ @connection = recorder.delegate
686
+ recorder.commands.each do |cmd, args, block|
687
+ send(cmd, *args, &block)
688
+ end
689
+ end
690
+ end
691
+ end
692
+
693
+ def reverting?
694
+ connection.respond_to?(:reverting) && connection.reverting
695
+ end
696
+
697
+ ReversibleBlockHelper = Struct.new(:reverting) do # :nodoc:
698
+ def up
699
+ yield unless reverting
700
+ end
701
+
702
+ def down
703
+ yield if reverting
704
+ end
705
+ end
706
+
707
+ # Used to specify an operation that can be run in one direction or another.
708
+ # Call the methods +up+ and +down+ of the yielded object to run a block
709
+ # only in one given direction.
710
+ # The whole block will be called in the right order within the migration.
711
+ #
712
+ # In the following example, the looping on users will always be done
713
+ # when the three columns 'first_name', 'last_name' and 'full_name' exist,
714
+ # even when migrating down:
715
+ #
716
+ # class SplitNameMigration < ActiveRecord::Migration[5.0]
717
+ # def change
718
+ # add_column :users, :first_name, :string
719
+ # add_column :users, :last_name, :string
720
+ #
721
+ # reversible do |dir|
722
+ # User.reset_column_information
723
+ # User.all.each do |u|
724
+ # dir.up { u.first_name, u.last_name = u.full_name.split(' ') }
725
+ # dir.down { u.full_name = "#{u.first_name} #{u.last_name}" }
726
+ # u.save
727
+ # end
728
+ # end
729
+ #
730
+ # revert { add_column :users, :full_name, :string }
731
+ # end
732
+ # end
733
+ def reversible
734
+ helper = ReversibleBlockHelper.new(reverting?)
735
+ execute_block { yield helper }
736
+ end
737
+
738
+ # Used to specify an operation that is only run when migrating up
739
+ # (for example, populating a new column with its initial values).
740
+ #
741
+ # In the following example, the new column +published+ will be given
742
+ # the value +true+ for all existing records.
743
+ #
744
+ # class AddPublishedToPosts < ActiveRecord::Migration[5.2]
745
+ # def change
746
+ # add_column :posts, :published, :boolean, default: false
747
+ # up_only do
748
+ # execute "update posts set published = 'true'"
749
+ # end
750
+ # end
751
+ # end
752
+ def up_only
753
+ execute_block { yield } unless reverting?
754
+ end
755
+
756
+ # Runs the given migration classes.
757
+ # Last argument can specify options:
758
+ # - :direction (default is :up)
759
+ # - :revert (default is false)
760
+ def run(*migration_classes)
761
+ opts = migration_classes.extract_options!
762
+ dir = opts[:direction] || :up
763
+ dir = (dir == :down ? :up : :down) if opts[:revert]
764
+ if reverting?
765
+ # If in revert and going :up, say, we want to execute :down without reverting, so
766
+ revert { run(*migration_classes, direction: dir, revert: true) }
767
+ else
768
+ migration_classes.each do |migration_class|
769
+ migration_class.new.exec_migration(connection, dir)
770
+ end
771
+ end
772
+ end
773
+
774
+ def up
775
+ self.class.delegate = self
776
+ return unless self.class.respond_to?(:up)
777
+ self.class.up
778
+ end
779
+
780
+ def down
781
+ self.class.delegate = self
782
+ return unless self.class.respond_to?(:down)
783
+ self.class.down
784
+ end
785
+
786
+ # Execute this migration in the named direction
787
+ def migrate(direction)
788
+ return unless respond_to?(direction)
789
+
790
+ case direction
791
+ when :up then announce "migrating"
792
+ when :down then announce "reverting"
793
+ end
794
+
795
+ time = nil
796
+ ActiveRecord::Base.connection_pool.with_connection do |conn|
797
+ time = Benchmark.measure do
798
+ exec_migration(conn, direction)
799
+ end
800
+ end
801
+
802
+ case direction
803
+ when :up then announce "migrated (%.4fs)" % time.real; write
804
+ when :down then announce "reverted (%.4fs)" % time.real; write
805
+ end
806
+ end
807
+
808
+ def exec_migration(conn, direction)
809
+ @connection = conn
810
+ if respond_to?(:change)
811
+ if direction == :down
812
+ revert { change }
813
+ else
814
+ change
815
+ end
816
+ else
817
+ send(direction)
818
+ end
819
+ ensure
820
+ @connection = nil
821
+ end
822
+
823
+ def write(text = "")
824
+ puts(text) if verbose
825
+ end
826
+
827
+ def announce(message)
828
+ text = "#{version} #{name}: #{message}"
829
+ length = [0, 75 - text.length].max
830
+ write "== %s %s" % [text, "=" * length]
831
+ end
832
+
833
+ def say(message, subitem = false)
834
+ write "#{subitem ? " ->" : "--"} #{message}"
835
+ end
836
+
837
+ def say_with_time(message)
838
+ say(message)
839
+ result = nil
840
+ time = Benchmark.measure { result = yield }
841
+ say "%.4fs" % time.real, :subitem
842
+ say("#{result} rows", :subitem) if result.is_a?(Integer)
843
+ result
844
+ end
845
+
846
+ def suppress_messages
847
+ save, self.verbose = verbose, false
848
+ yield
849
+ ensure
850
+ self.verbose = save
851
+ end
852
+
853
+ def connection
854
+ @connection || ActiveRecord::Base.connection
855
+ end
856
+
857
+ def method_missing(method, *arguments, &block)
858
+ arg_list = arguments.map(&:inspect) * ", "
859
+
860
+ say_with_time "#{method}(#{arg_list})" do
861
+ unless connection.respond_to? :revert
862
+ unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
863
+ arguments[0] = proper_table_name(arguments.first, table_name_options)
864
+ if [:rename_table, :add_foreign_key].include?(method) ||
865
+ (method == :remove_foreign_key && !arguments.second.is_a?(Hash))
866
+ arguments[1] = proper_table_name(arguments.second, table_name_options)
867
+ end
868
+ end
869
+ end
870
+ return super unless connection.respond_to?(method)
871
+ connection.send(method, *arguments, &block)
872
+ end
873
+ end
874
+
875
+ def copy(destination, sources, options = {})
876
+ copied = []
877
+
878
+ FileUtils.mkdir_p(destination) unless File.exist?(destination)
879
+
880
+ destination_migrations = ActiveRecord::MigrationContext.new(destination).migrations
881
+ last = destination_migrations.last
882
+ sources.each do |scope, path|
883
+ source_migrations = ActiveRecord::MigrationContext.new(path).migrations
884
+
885
+ source_migrations.each do |migration|
886
+ source = File.binread(migration.filename)
887
+ inserted_comment = "# This migration comes from #{scope} (originally #{migration.version})\n"
888
+ magic_comments = "".dup
889
+ loop do
890
+ # If we have a magic comment in the original migration,
891
+ # insert our comment after the first newline(end of the magic comment line)
892
+ # so the magic keep working.
893
+ # Note that magic comments must be at the first line(except sh-bang).
894
+ source.sub!(/\A(?:#.*\b(?:en)?coding:\s*\S+|#\s*frozen_string_literal:\s*(?:true|false)).*\n/) do |magic_comment|
895
+ magic_comments << magic_comment; ""
896
+ end || break
897
+ end
898
+ source = "#{magic_comments}#{inserted_comment}#{source}"
899
+
900
+ if duplicate = destination_migrations.detect { |m| m.name == migration.name }
901
+ if options[:on_skip] && duplicate.scope != scope.to_s
902
+ options[:on_skip].call(scope, migration)
903
+ end
904
+ next
905
+ end
906
+
907
+ migration.version = next_migration_number(last ? last.version + 1 : 0).to_i
908
+ new_path = File.join(destination, "#{migration.version}_#{migration.name.underscore}.#{scope}.rb")
909
+ old_path, migration.filename = migration.filename, new_path
910
+ last = migration
911
+
912
+ File.binwrite(migration.filename, source)
913
+ copied << migration
914
+ options[:on_copy].call(scope, migration, old_path) if options[:on_copy]
915
+ destination_migrations << migration
916
+ end
917
+ end
918
+
919
+ copied
920
+ end
921
+
922
+ # Finds the correct table name given an Active Record object.
923
+ # Uses the Active Record object's own table_name, or pre/suffix from the
924
+ # options passed in.
925
+ def proper_table_name(name, options = {})
926
+ if name.respond_to? :table_name
927
+ name.table_name
928
+ else
929
+ "#{options[:table_name_prefix]}#{name}#{options[:table_name_suffix]}"
930
+ end
931
+ end
932
+
933
+ # Determines the version number of the next migration.
934
+ def next_migration_number(number)
935
+ if ActiveRecord::Base.timestamped_migrations
936
+ [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
937
+ else
938
+ SchemaMigration.normalize_migration_number(number)
939
+ end
940
+ end
941
+
942
+ # Builds a hash for use in ActiveRecord::Migration#proper_table_name using
943
+ # the Active Record object's table_name prefix and suffix
944
+ def table_name_options(config = ActiveRecord::Base) #:nodoc:
945
+ {
946
+ table_name_prefix: config.table_name_prefix,
947
+ table_name_suffix: config.table_name_suffix
948
+ }
949
+ end
950
+
951
+ private
952
+ def execute_block
953
+ if connection.respond_to? :execute_block
954
+ super # use normal delegation to record the block
955
+ else
956
+ yield
957
+ end
958
+ end
959
+ end
960
+
961
+ # MigrationProxy is used to defer loading of the actual migration classes
962
+ # until they are needed
963
+ MigrationProxy = Struct.new(:name, :version, :filename, :scope) do
964
+ def initialize(name, version, filename, scope)
965
+ super
966
+ @migration = nil
967
+ end
968
+
969
+ def basename
970
+ File.basename(filename)
971
+ end
972
+
973
+ def mtime
974
+ File.mtime filename
975
+ end
976
+
977
+ delegate :migrate, :announce, :write, :disable_ddl_transaction, to: :migration
978
+
979
+ private
980
+
981
+ def migration
982
+ @migration ||= load_migration
983
+ end
984
+
985
+ def load_migration
986
+ require(File.expand_path(filename))
987
+ name.constantize.new(name, version)
988
+ end
989
+ end
990
+
991
+ class NullMigration < MigrationProxy #:nodoc:
992
+ def initialize
993
+ super(nil, 0, nil, nil)
994
+ end
995
+
996
+ def mtime
997
+ 0
998
+ end
999
+ end
1000
+
1001
+ class MigrationContext # :nodoc:
1002
+ attr_reader :migrations_paths
1003
+
1004
+ def initialize(migrations_paths)
1005
+ @migrations_paths = migrations_paths
1006
+ end
1007
+
1008
+ def migrate(target_version = nil, &block)
1009
+ case
1010
+ when target_version.nil?
1011
+ up(target_version, &block)
1012
+ when current_version == 0 && target_version == 0
1013
+ []
1014
+ when current_version > target_version
1015
+ down(target_version, &block)
1016
+ else
1017
+ up(target_version, &block)
1018
+ end
1019
+ end
1020
+
1021
+ def rollback(steps = 1)
1022
+ move(:down, steps)
1023
+ end
1024
+
1025
+ def forward(steps = 1)
1026
+ move(:up, steps)
1027
+ end
1028
+
1029
+ def up(target_version = nil)
1030
+ selected_migrations = if block_given?
1031
+ migrations.select { |m| yield m }
1032
+ else
1033
+ migrations
1034
+ end
1035
+
1036
+ Migrator.new(:up, selected_migrations, target_version).migrate
1037
+ end
1038
+
1039
+ def down(target_version = nil)
1040
+ selected_migrations = if block_given?
1041
+ migrations.select { |m| yield m }
1042
+ else
1043
+ migrations
1044
+ end
1045
+
1046
+ Migrator.new(:down, selected_migrations, target_version).migrate
1047
+ end
1048
+
1049
+ def run(direction, target_version)
1050
+ Migrator.new(direction, migrations, target_version).run
1051
+ end
1052
+
1053
+ def open
1054
+ Migrator.new(:up, migrations, nil)
1055
+ end
1056
+
1057
+ def get_all_versions
1058
+ if SchemaMigration.table_exists?
1059
+ SchemaMigration.all_versions.map(&:to_i)
1060
+ else
1061
+ []
1062
+ end
1063
+ end
1064
+
1065
+ def current_version
1066
+ get_all_versions.max || 0
1067
+ rescue ActiveRecord::NoDatabaseError
1068
+ end
1069
+
1070
+ def needs_migration?
1071
+ (migrations.collect(&:version) - get_all_versions).size > 0
1072
+ end
1073
+
1074
+ def any_migrations?
1075
+ migrations.any?
1076
+ end
1077
+
1078
+ def last_migration #:nodoc:
1079
+ migrations.last || NullMigration.new
1080
+ end
1081
+
1082
+ def parse_migration_filename(filename) # :nodoc:
1083
+ File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1084
+ end
1085
+
1086
+ def migrations
1087
+ migrations = migration_files.map do |file|
1088
+ version, name, scope = parse_migration_filename(file)
1089
+ raise IllegalMigrationNameError.new(file) unless version
1090
+ version = version.to_i
1091
+ name = name.camelize
1092
+
1093
+ MigrationProxy.new(name, version, file, scope)
1094
+ end
1095
+
1096
+ migrations.sort_by(&:version)
1097
+ end
1098
+
1099
+ def migrations_status
1100
+ db_list = ActiveRecord::SchemaMigration.normalized_versions
1101
+
1102
+ file_list = migration_files.map do |file|
1103
+ version, name, scope = parse_migration_filename(file)
1104
+ raise IllegalMigrationNameError.new(file) unless version
1105
+ version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
1106
+ status = db_list.delete(version) ? "up" : "down"
1107
+ [status, version, (name + scope).humanize]
1108
+ end.compact
1109
+
1110
+ db_list.map! do |version|
1111
+ ["up", version, "********** NO FILE **********"]
1112
+ end
1113
+
1114
+ (db_list + file_list).sort_by { |_, version, _| version }
1115
+ end
1116
+
1117
+ def migration_files
1118
+ paths = Array(migrations_paths)
1119
+ Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
1120
+ end
1121
+
1122
+ def current_environment
1123
+ ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
1124
+ end
1125
+
1126
+ def protected_environment?
1127
+ ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
1128
+ end
1129
+
1130
+ def last_stored_environment
1131
+ return nil if current_version == 0
1132
+ raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1133
+
1134
+ environment = ActiveRecord::InternalMetadata[:environment]
1135
+ raise NoEnvironmentInSchemaError unless environment
1136
+ environment
1137
+ end
1138
+
1139
+ private
1140
+ def move(direction, steps)
1141
+ migrator = Migrator.new(direction, migrations)
1142
+
1143
+ if current_version != 0 && !migrator.current_migration
1144
+ raise UnknownMigrationVersionError.new(current_version)
1145
+ end
1146
+
1147
+ start_index =
1148
+ if current_version == 0
1149
+ 0
1150
+ else
1151
+ migrator.migrations.index(migrator.current_migration)
1152
+ end
1153
+
1154
+ finish = migrator.migrations[start_index + steps]
1155
+ version = finish ? finish.version : 0
1156
+ send(direction, version)
1157
+ end
1158
+ end
1159
+
1160
+ class Migrator # :nodoc:
1161
+ class << self
1162
+ attr_accessor :migrations_paths
1163
+
1164
+ def migrations_path=(path)
1165
+ ActiveSupport::Deprecation.warn \
1166
+ "`ActiveRecord::Migrator.migrations_path=` is now deprecated and will be removed in Rails 6.0. " \
1167
+ "You can set the `migrations_paths` on the `connection` instead through the `database.yml`."
1168
+ self.migrations_paths = [path]
1169
+ end
1170
+
1171
+ # For cases where a table doesn't exist like loading from schema cache
1172
+ def current_version
1173
+ MigrationContext.new(migrations_paths).current_version
1174
+ end
1175
+ end
1176
+
1177
+ self.migrations_paths = ["db/migrate"]
1178
+
1179
+ def initialize(direction, migrations, target_version = nil)
1180
+ @direction = direction
1181
+ @target_version = target_version
1182
+ @migrated_versions = nil
1183
+ @migrations = migrations
1184
+
1185
+ validate(@migrations)
1186
+
1187
+ ActiveRecord::SchemaMigration.create_table
1188
+ ActiveRecord::InternalMetadata.create_table
1189
+ end
1190
+
1191
+ def current_version
1192
+ migrated.max || 0
1193
+ end
1194
+
1195
+ def current_migration
1196
+ migrations.detect { |m| m.version == current_version }
1197
+ end
1198
+ alias :current :current_migration
1199
+
1200
+ def run
1201
+ if use_advisory_lock?
1202
+ with_advisory_lock { run_without_lock }
1203
+ else
1204
+ run_without_lock
1205
+ end
1206
+ end
1207
+
1208
+ def migrate
1209
+ if use_advisory_lock?
1210
+ with_advisory_lock { migrate_without_lock }
1211
+ else
1212
+ migrate_without_lock
1213
+ end
1214
+ end
1215
+
1216
+ def runnable
1217
+ runnable = migrations[start..finish]
1218
+ if up?
1219
+ runnable.reject { |m| ran?(m) }
1220
+ else
1221
+ # skip the last migration if we're headed down, but not ALL the way down
1222
+ runnable.pop if target
1223
+ runnable.find_all { |m| ran?(m) }
1224
+ end
1225
+ end
1226
+
1227
+ def migrations
1228
+ down? ? @migrations.reverse : @migrations.sort_by(&:version)
1229
+ end
1230
+
1231
+ def pending_migrations
1232
+ already_migrated = migrated
1233
+ migrations.reject { |m| already_migrated.include?(m.version) }
1234
+ end
1235
+
1236
+ def migrated
1237
+ @migrated_versions || load_migrated
1238
+ end
1239
+
1240
+ def load_migrated
1241
+ @migrated_versions = Set.new(Base.connection.migration_context.get_all_versions)
1242
+ end
1243
+
1244
+ private
1245
+
1246
+ # Used for running a specific migration.
1247
+ def run_without_lock
1248
+ migration = migrations.detect { |m| m.version == @target_version }
1249
+ raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
1250
+ result = execute_migration_in_transaction(migration, @direction)
1251
+
1252
+ record_environment
1253
+ result
1254
+ end
1255
+
1256
+ # Used for running multiple migrations up to or down to a certain value.
1257
+ def migrate_without_lock
1258
+ if invalid_target?
1259
+ raise UnknownMigrationVersionError.new(@target_version)
1260
+ end
1261
+
1262
+ result = runnable.each do |migration|
1263
+ execute_migration_in_transaction(migration, @direction)
1264
+ end
1265
+
1266
+ record_environment
1267
+ result
1268
+ end
1269
+
1270
+ # Stores the current environment in the database.
1271
+ def record_environment
1272
+ return if down?
1273
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
1274
+ end
1275
+
1276
+ def ran?(migration)
1277
+ migrated.include?(migration.version.to_i)
1278
+ end
1279
+
1280
+ # Return true if a valid version is not provided.
1281
+ def invalid_target?
1282
+ @target_version && @target_version != 0 && !target
1283
+ end
1284
+
1285
+ def execute_migration_in_transaction(migration, direction)
1286
+ return if down? && !migrated.include?(migration.version.to_i)
1287
+ return if up? && migrated.include?(migration.version.to_i)
1288
+
1289
+ Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
1290
+
1291
+ ddl_transaction(migration) do
1292
+ migration.migrate(direction)
1293
+ record_version_state_after_migrating(migration.version)
1294
+ end
1295
+ rescue => e
1296
+ msg = "An error has occurred, ".dup
1297
+ msg << "this and " if use_transaction?(migration)
1298
+ msg << "all later migrations canceled:\n\n#{e}"
1299
+ raise StandardError, msg, e.backtrace
1300
+ end
1301
+
1302
+ def target
1303
+ migrations.detect { |m| m.version == @target_version }
1304
+ end
1305
+
1306
+ def finish
1307
+ migrations.index(target) || migrations.size - 1
1308
+ end
1309
+
1310
+ def start
1311
+ up? ? 0 : (migrations.index(current) || 0)
1312
+ end
1313
+
1314
+ def validate(migrations)
1315
+ name, = migrations.group_by(&:name).find { |_, v| v.length > 1 }
1316
+ raise DuplicateMigrationNameError.new(name) if name
1317
+
1318
+ version, = migrations.group_by(&:version).find { |_, v| v.length > 1 }
1319
+ raise DuplicateMigrationVersionError.new(version) if version
1320
+ end
1321
+
1322
+ def record_version_state_after_migrating(version)
1323
+ if down?
1324
+ migrated.delete(version)
1325
+ ActiveRecord::SchemaMigration.where(version: version.to_s).delete_all
1326
+ else
1327
+ migrated << version
1328
+ ActiveRecord::SchemaMigration.create!(version: version.to_s)
1329
+ end
1330
+ end
1331
+
1332
+ def up?
1333
+ @direction == :up
1334
+ end
1335
+
1336
+ def down?
1337
+ @direction == :down
1338
+ end
1339
+
1340
+ # Wrap the migration in a transaction only if supported by the adapter.
1341
+ def ddl_transaction(migration)
1342
+ if use_transaction?(migration)
1343
+ Base.transaction { yield }
1344
+ else
1345
+ yield
1346
+ end
1347
+ end
1348
+
1349
+ def use_transaction?(migration)
1350
+ !migration.disable_ddl_transaction && Base.connection.supports_ddl_transactions?
1351
+ end
1352
+
1353
+ def use_advisory_lock?
1354
+ Base.connection.supports_advisory_locks?
1355
+ end
1356
+
1357
+ def with_advisory_lock
1358
+ lock_id = generate_migrator_advisory_lock_id
1359
+ connection = Base.connection
1360
+ got_lock = connection.get_advisory_lock(lock_id)
1361
+ raise ConcurrentMigrationError unless got_lock
1362
+ load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1363
+ yield
1364
+ ensure
1365
+ if got_lock && !connection.release_advisory_lock(lock_id)
1366
+ raise ConcurrentMigrationError.new(
1367
+ ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
1368
+ )
1369
+ end
1370
+ end
1371
+
1372
+ MIGRATOR_SALT = 2053462845
1373
+ def generate_migrator_advisory_lock_id
1374
+ db_name_hash = Zlib.crc32(Base.connection.current_database)
1375
+ MIGRATOR_SALT * db_name_hash
1376
+ end
1377
+ end
1378
+ end