activerecord 4.2.11.1 → 6.0.3.5

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