activerecord 4.2.0 → 6.0.5.1

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 +5 -5
  2. data/CHANGELOG.md +852 -801
  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 +267 -249
  9. data/lib/active_record/association_relation.rb +26 -6
  10. data/lib/active_record/associations/alias_tracker.rb +29 -36
  11. data/lib/active_record/associations/association.rb +137 -55
  12. data/lib/active_record/associations/association_scope.rb +110 -132
  13. data/lib/active_record/associations/belongs_to_association.rb +67 -54
  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 -29
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +58 -70
  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 +150 -275
  23. data/lib/active_record/associations/collection_proxy.rb +253 -152
  24. data/lib/active_record/associations/foreign_association.rb +20 -0
  25. data/lib/active_record/associations/has_many_association.rb +35 -84
  26. data/lib/active_record/associations/has_many_through_association.rb +62 -80
  27. data/lib/active_record/associations/has_one_association.rb +62 -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 +43 -78
  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 +159 -162
  33. data/lib/active_record/associations/preloader/association.rb +102 -113
  34. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  35. data/lib/active_record/associations/preloader.rb +96 -95
  36. data/lib/active_record/associations/singular_association.rb +18 -45
  37. data/lib/active_record/associations/through_association.rb +49 -24
  38. data/lib/active_record/associations.rb +1737 -1596
  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 +14 -5
  42. data/lib/active_record/attribute_methods/dirty.rb +174 -134
  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 +61 -37
  48. data/lib/active_record/attribute_methods/write.rb +33 -56
  49. data/lib/active_record/attribute_methods.rb +124 -143
  50. data/lib/active_record/attributes.rb +213 -74
  51. data/lib/active_record/autosave_association.rb +125 -54
  52. data/lib/active_record/base.rb +60 -49
  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 +36 -13
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +810 -291
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +253 -108
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +83 -24
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +171 -53
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -47
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +383 -239
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +736 -235
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +190 -87
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +487 -192
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +536 -600
  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 +268 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +59 -196
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +71 -115
  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 -57
  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 +5 -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 +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  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 +70 -34
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  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 +465 -291
  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 +565 -363
  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 -364
  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 +277 -233
  130. data/lib/active_record/counter_cache.rb +71 -50
  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 +172 -89
  138. data/lib/active_record/errors.rb +189 -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 +11 -6
  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 +225 -497
  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 +48 -0
  154. data/lib/active_record/locale/en.yml +3 -2
  155. data/lib/active_record/locking/optimistic.rb +99 -98
  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 +636 -290
  165. data/lib/active_record/model_schema.rb +344 -112
  166. data/lib/active_record/nested_attributes.rb +265 -215
  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 +559 -125
  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 +166 -47
  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 +341 -202
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +461 -302
  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 +270 -249
  182. data/lib/active_record/relation/delegation.rb +76 -84
  183. data/lib/active_record/relation/finder_methods.rb +287 -255
  184. data/lib/active_record/relation/from_clause.rb +30 -0
  185. data/lib/active_record/relation/merger.rb +86 -68
  186. data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -25
  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 +112 -92
  194. data/lib/active_record/relation/query_attribute.rb +50 -0
  195. data/lib/active_record/relation/query_methods.rb +612 -392
  196. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  197. data/lib/active_record/relation/spawn_methods.rb +18 -17
  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 +533 -340
  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 -20
  207. data/lib/active_record/scoping/default.rb +98 -82
  208. data/lib/active_record/scoping/named.rb +91 -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 +309 -99
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +58 -89
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -31
  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 +243 -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 +222 -146
  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 -41
  228. data/lib/active_record/type/date_time.rb +4 -38
  229. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  230. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  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 +29 -15
  234. data/lib/active_record/type/text.rb +2 -2
  235. data/lib/active_record/type/time.rb +21 -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 +43 -46
  247. data/lib/active_record/validations.rb +38 -35
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/active_record.rb +44 -21
  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 -8
  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.rb +7 -5
  340. metadata +174 -63
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  343. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  344. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  345. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  348. data/lib/active_record/attribute.rb +0 -149
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  352. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  353. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  354. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  355. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  356. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  357. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  358. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  359. data/lib/active_record/type/big_integer.rb +0 -13
  360. data/lib/active_record/type/binary.rb +0 -50
  361. data/lib/active_record/type/boolean.rb +0 -30
  362. data/lib/active_record/type/decimal.rb +0 -40
  363. data/lib/active_record/type/decorator.rb +0 -14
  364. data/lib/active_record/type/float.rb +0 -19
  365. data/lib/active_record/type/integer.rb +0 -55
  366. data/lib/active_record/type/mutable.rb +0 -16
  367. data/lib/active_record/type/numeric.rb +0 -36
  368. data/lib/active_record/type/string.rb +0 -36
  369. data/lib/active_record/type/time_value.rb +0 -38
  370. data/lib/active_record/type/value.rb +0 -101
  371. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  372. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  373. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -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
42
- if defined?(Rails)
43
- super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate RAILS_ENV=#{::Rails.env}")
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"
184
+ if defined?(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:
@@ -307,15 +475,14 @@ module ActiveRecord
307
475
  #
308
476
  # == Reversible Migrations
309
477
  #
310
- # Starting with Rails 3.1, you will be able to define reversible migrations.
311
478
  # Reversible migrations are migrations that know how to go +down+ for you.
312
- # You simply supply the +up+ logic, and the Migration system will figure out
479
+ # You simply supply the +up+ logic, and the Migration system figures out
313
480
  # how to execute the down commands for you.
314
481
  #
315
482
  # To define a reversible migration, define the +change+ method in your
316
483
  # migration like this:
317
484
  #
318
- # class TenderloveMigration < ActiveRecord::Migration
485
+ # class TenderloveMigration < ActiveRecord::Migration[5.0]
319
486
  # def change
320
487
  # create_table(:horses) do |t|
321
488
  # t.column :content, :text
@@ -327,9 +494,9 @@ module ActiveRecord
327
494
  # This migration will create the horses table for you on the way up, and
328
495
  # automatically figure out how to drop the table on the way down.
329
496
  #
330
- # Some commands like +remove_column+ cannot be reversed. If you care to
331
- # define how to move up and down in these cases, you should define the +up+
332
- # 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.
333
500
  #
334
501
  # If a command cannot be reversed, an
335
502
  # <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
@@ -345,7 +512,7 @@ module ActiveRecord
345
512
  # can't execute inside a transaction though, and for these situations
346
513
  # you can turn the automatic transactions off.
347
514
  #
348
- # class ChangeEnum < ActiveRecord::Migration
515
+ # class ChangeEnum < ActiveRecord::Migration[5.0]
349
516
  # disable_ddl_transaction!
350
517
  #
351
518
  # def up
@@ -356,11 +523,35 @@ module ActiveRecord
356
523
  # Remember that you can still open your own transactions, even if you
357
524
  # are in a Migration with <tt>self.disable_ddl_transaction!</tt>.
358
525
  class Migration
359
- autoload :CommandRecorder, 'active_record/migration/command_recorder'
526
+ autoload :CommandRecorder, "active_record/migration/command_recorder"
527
+ autoload :Compatibility, "active_record/migration/compatibility"
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
360
550
 
551
+ MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ #:nodoc:
361
552
 
362
553
  # This class is used to verify that all migrations have been run before
363
- # loading a web page if config.active_record.migration_error is set to :page_load
554
+ # loading a web page if <tt>config.active_record.migration_error</tt> is set to :page_load
364
555
  class CheckPending
365
556
  def initialize(app)
366
557
  @app = app
@@ -368,66 +559,81 @@ module ActiveRecord
368
559
  end
369
560
 
370
561
  def call(env)
371
- if connection.supports_migrations?
372
- mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
373
- if @last_check < mtime
374
- ActiveRecord::Migration.check_pending!(connection)
375
- @last_check = mtime
376
- 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
377
566
  end
378
567
  @app.call(env)
379
568
  end
380
569
 
381
570
  private
382
-
383
- def connection
384
- ActiveRecord::Base.connection
385
- end
571
+ def connection
572
+ ActiveRecord::Base.connection
573
+ end
386
574
  end
387
575
 
388
576
  class << self
389
- attr_accessor :delegate # :nodoc:
390
- attr_accessor :disable_ddl_transaction # :nodoc:
577
+ attr_accessor :delegate #:nodoc:
578
+ attr_accessor :disable_ddl_transaction #:nodoc:
391
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.
392
585
  def check_pending!(connection = Base.connection)
393
- raise ActiveRecord::PendingMigrationError if ActiveRecord::Migrator.needs_migration?(connection)
586
+ raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration?
394
587
  end
395
588
 
396
589
  def load_schema_if_pending!
397
- if ActiveRecord::Migrator.needs_migration? || !ActiveRecord::Migrator.any_migrations?
398
- # Roundrip to Rake to allow plugins to hook into database initialization.
399
- FileUtils.cd Rails.root do
400
- 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
401
601
  Base.clear_all_connections!
402
- system("bin/rake db:test:prepare")
403
- # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
404
- Base.establish_connection(current_config)
602
+ system("bin/rails db:test:prepare")
405
603
  end
406
- check_pending!
407
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!
408
610
  end
409
611
 
410
- def maintain_test_schema! # :nodoc:
612
+ def maintain_test_schema! #:nodoc:
411
613
  if ActiveRecord::Base.maintain_test_schema
412
614
  suppress_messages { load_schema_if_pending! }
413
615
  end
414
616
  end
415
617
 
416
- def method_missing(name, *args, &block) # :nodoc:
417
- (delegate || superclass.delegate).send(name, *args, &block)
618
+ def method_missing(name, *args, &block) #:nodoc:
619
+ nearest_delegate.send(name, *args, &block)
418
620
  end
621
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
419
622
 
420
623
  def migrate(direction)
421
624
  new.migrate direction
422
625
  end
423
626
 
424
- # Disable DDL transactions for this migration.
627
+ # Disable the transaction wrapping this migration.
628
+ # You can still create your own transactions even after calling #disable_ddl_transaction!
629
+ #
630
+ # For more details read the {"Transactional Migrations" section above}[rdoc-ref:Migration].
425
631
  def disable_ddl_transaction!
426
632
  @disable_ddl_transaction = true
427
633
  end
428
634
  end
429
635
 
430
- def disable_ddl_transaction # :nodoc:
636
+ def disable_ddl_transaction #:nodoc:
431
637
  self.class.disable_ddl_transaction
432
638
  end
433
639
 
@@ -451,7 +657,7 @@ module ActiveRecord
451
657
  # and create the table 'apples' on the way up, and the reverse
452
658
  # on the way down.
453
659
  #
454
- # class FixTLMigration < ActiveRecord::Migration
660
+ # class FixTLMigration < ActiveRecord::Migration[5.0]
455
661
  # def change
456
662
  # revert do
457
663
  # create_table(:horses) do |t|
@@ -468,9 +674,9 @@ module ActiveRecord
468
674
  # Or equivalently, if +TenderloveMigration+ is defined as in the
469
675
  # documentation for Migration:
470
676
  #
471
- # require_relative '2012121212_tenderlove_migration'
677
+ # require_relative '20121212123456_tenderlove_migration'
472
678
  #
473
- # class FixupTLMigration < ActiveRecord::Migration
679
+ # class FixupTLMigration < ActiveRecord::Migration[5.0]
474
680
  # def change
475
681
  # revert TenderloveMigration
476
682
  #
@@ -484,27 +690,25 @@ module ActiveRecord
484
690
  def revert(*migration_classes)
485
691
  run(*migration_classes.reverse, revert: true) unless migration_classes.empty?
486
692
  if block_given?
487
- if @connection.respond_to? :revert
488
- @connection.revert { yield }
693
+ if connection.respond_to? :revert
694
+ connection.revert { yield }
489
695
  else
490
- recorder = CommandRecorder.new(@connection)
696
+ recorder = command_recorder
491
697
  @connection = recorder
492
698
  suppress_messages do
493
- @connection.revert { yield }
699
+ connection.revert { yield }
494
700
  end
495
701
  @connection = recorder.delegate
496
- recorder.commands.each do |cmd, args, block|
497
- send(cmd, *args, &block)
498
- end
702
+ recorder.replay(self)
499
703
  end
500
704
  end
501
705
  end
502
706
 
503
707
  def reverting?
504
- @connection.respond_to?(:reverting) && @connection.reverting
708
+ connection.respond_to?(:reverting) && connection.reverting
505
709
  end
506
710
 
507
- class ReversibleBlockHelper < Struct.new(:reverting) # :nodoc:
711
+ ReversibleBlockHelper = Struct.new(:reverting) do #:nodoc:
508
712
  def up
509
713
  yield unless reverting
510
714
  end
@@ -523,7 +727,7 @@ module ActiveRecord
523
727
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
524
728
  # even when migrating down:
525
729
  #
526
- # class SplitNameMigration < ActiveRecord::Migration
730
+ # class SplitNameMigration < ActiveRecord::Migration[5.0]
527
731
  # def change
528
732
  # add_column :users, :first_name, :string
529
733
  # add_column :users, :last_name, :string
@@ -542,7 +746,25 @@ module ActiveRecord
542
746
  # end
543
747
  def reversible
544
748
  helper = ReversibleBlockHelper.new(reverting?)
545
- 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?
546
768
  end
547
769
 
548
770
  # Runs the given migration classes.
@@ -558,7 +780,7 @@ module ActiveRecord
558
780
  revert { run(*migration_classes, direction: dir, revert: true) }
559
781
  else
560
782
  migration_classes.each do |migration_class|
561
- migration_class.new.exec_migration(@connection, dir)
783
+ migration_class.new.exec_migration(connection, dir)
562
784
  end
563
785
  end
564
786
  end
@@ -584,7 +806,7 @@ module ActiveRecord
584
806
  when :down then announce "reverting"
585
807
  end
586
808
 
587
- time = nil
809
+ time = nil
588
810
  ActiveRecord::Base.connection_pool.with_connection do |conn|
589
811
  time = Benchmark.measure do
590
812
  exec_migration(conn, direction)
@@ -612,7 +834,7 @@ module ActiveRecord
612
834
  @connection = nil
613
835
  end
614
836
 
615
- def write(text="")
837
+ def write(text = "")
616
838
  puts(text) if verbose
617
839
  end
618
840
 
@@ -622,10 +844,14 @@ module ActiveRecord
622
844
  write "== %s %s" % [text, "=" * length]
623
845
  end
624
846
 
625
- 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)
626
850
  write "#{subitem ? " ->" : "--"} #{message}"
627
851
  end
628
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.
629
855
  def say_with_time(message)
630
856
  say(message)
631
857
  result = nil
@@ -635,6 +861,7 @@ module ActiveRecord
635
861
  result
636
862
  end
637
863
 
864
+ # Takes a block as an argument and suppresses any output generated by the block.
638
865
  def suppress_messages
639
866
  save, self.verbose = verbose, false
640
867
  yield
@@ -647,13 +874,14 @@ module ActiveRecord
647
874
  end
648
875
 
649
876
  def method_missing(method, *arguments, &block)
650
- arg_list = arguments.map{ |a| a.inspect } * ', '
877
+ arg_list = arguments.map(&:inspect) * ", "
651
878
 
652
879
  say_with_time "#{method}(#{arg_list})" do
653
- unless @connection.respond_to? :revert
880
+ unless connection.respond_to? :revert
654
881
  unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
655
882
  arguments[0] = proper_table_name(arguments.first, table_name_options)
656
- if [:rename_table, :add_foreign_key].include?(method)
883
+ if [:rename_table, :add_foreign_key].include?(method) ||
884
+ (method == :remove_foreign_key && !arguments.second.is_a?(Hash))
657
885
  arguments[1] = proper_table_name(arguments.second, table_name_options)
658
886
  end
659
887
  end
@@ -662,29 +890,33 @@ module ActiveRecord
662
890
  connection.send(method, *arguments, &block)
663
891
  end
664
892
  end
893
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
665
894
 
666
895
  def copy(destination, sources, options = {})
667
896
  copied = []
897
+ schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
668
898
 
669
899
  FileUtils.mkdir_p(destination) unless File.exist?(destination)
670
900
 
671
- destination_migrations = ActiveRecord::Migrator.migrations(destination)
901
+ destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
672
902
  last = destination_migrations.last
673
903
  sources.each do |scope, path|
674
- source_migrations = ActiveRecord::Migrator.migrations(path)
904
+ source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
675
905
 
676
906
  source_migrations.each do |migration|
677
907
  source = File.binread(migration.filename)
678
908
  inserted_comment = "# This migration comes from #{scope} (originally #{migration.version})\n"
679
- if /\A#.*\b(?:en)?coding:\s*\S+/ =~ source
909
+ magic_comments = +""
910
+ loop do
680
911
  # If we have a magic comment in the original migration,
681
912
  # insert our comment after the first newline(end of the magic comment line)
682
913
  # so the magic keep working.
683
914
  # Note that magic comments must be at the first line(except sh-bang).
684
- source[/\n/] = "\n#{inserted_comment}"
685
- else
686
- 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
687
918
  end
919
+ source = "#{magic_comments}#{inserted_comment}#{source}"
688
920
 
689
921
  if duplicate = destination_migrations.detect { |m| m.name == migration.name }
690
922
  if options[:on_skip] && duplicate.scope != scope.to_s
@@ -728,7 +960,9 @@ module ActiveRecord
728
960
  end
729
961
  end
730
962
 
731
- 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:
732
966
  {
733
967
  table_name_prefix: config.table_name_prefix,
734
968
  table_name_suffix: config.table_name_suffix
@@ -736,19 +970,22 @@ module ActiveRecord
736
970
  end
737
971
 
738
972
  private
739
- def execute_block
740
- if connection.respond_to? :execute_block
741
- super # use normal delegation to record the block
742
- else
743
- 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)
744
983
  end
745
- end
746
984
  end
747
985
 
748
986
  # MigrationProxy is used to defer loading of the actual migration classes
749
987
  # until they are needed
750
- class MigrationProxy < Struct.new(:name, :version, :filename, :scope)
751
-
988
+ MigrationProxy = Struct.new(:name, :version, :filename, :scope) do
752
989
  def initialize(name, version, filename, scope)
753
990
  super
754
991
  @migration = nil
@@ -765,7 +1002,6 @@ module ActiveRecord
765
1002
  delegate :migrate, :announce, :write, :disable_ddl_transaction, to: :migration
766
1003
 
767
1004
  private
768
-
769
1005
  def migration
770
1006
  @migration ||= load_migration
771
1007
  end
@@ -774,7 +1010,6 @@ module ActiveRecord
774
1010
  require(File.expand_path(filename))
775
1011
  name.constantize.new(name, version)
776
1012
  end
777
-
778
1013
  end
779
1014
 
780
1015
  class NullMigration < MigrationProxy #:nodoc:
@@ -787,139 +1022,189 @@ module ActiveRecord
787
1022
  end
788
1023
  end
789
1024
 
790
- class Migrator#:nodoc:
791
- class << self
792
- attr_writer :migrations_paths
793
- alias :migrations_path= :migrations_paths=
794
-
795
- def migrate(migrations_paths, target_version = nil, &block)
796
- case
797
- when target_version.nil?
798
- up(migrations_paths, target_version, &block)
799
- when current_version == 0 && target_version == 0
800
- []
801
- when current_version > target_version
802
- down(migrations_paths, target_version, &block)
803
- else
804
- up(migrations_paths, target_version, &block)
805
- end
806
- end
1025
+ class MigrationContext #:nodoc:
1026
+ attr_reader :migrations_paths, :schema_migration
807
1027
 
808
- def rollback(migrations_paths, steps=1)
809
- move(:down, migrations_paths, steps)
810
- end
1028
+ def initialize(migrations_paths, schema_migration)
1029
+ @migrations_paths = migrations_paths
1030
+ @schema_migration = schema_migration
1031
+ end
811
1032
 
812
- def forward(migrations_paths, steps=1)
813
- 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)
814
1043
  end
1044
+ end
815
1045
 
816
- def up(migrations_paths, target_version = nil)
817
- migrations = migrations(migrations_paths)
818
- migrations.select! { |m| yield m } if block_given?
1046
+ def rollback(steps = 1)
1047
+ move(:down, steps)
1048
+ end
1049
+
1050
+ def forward(steps = 1)
1051
+ move(:up, steps)
1052
+ end
819
1053
 
820
- new(:up, 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
821
1059
  end
822
1060
 
823
- def down(migrations_paths, target_version = nil, &block)
824
- migrations = migrations(migrations_paths)
825
- migrations.select! { |m| yield m } if block_given?
1061
+ Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
1062
+ end
826
1063
 
827
- new(:down, migrations, target_version).migrate
1064
+ def down(target_version = nil)
1065
+ selected_migrations = if block_given?
1066
+ migrations.select { |m| yield m }
1067
+ else
1068
+ migrations
828
1069
  end
829
1070
 
830
- def run(direction, migrations_paths, target_version)
831
- new(direction, migrations(migrations_paths), target_version).run
832
- end
1071
+ Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
1072
+ end
833
1073
 
834
- def open(migrations_paths)
835
- new(:up, migrations(migrations_paths), nil)
836
- end
1074
+ def run(direction, target_version)
1075
+ Migrator.new(direction, migrations, schema_migration, target_version).run
1076
+ end
837
1077
 
838
- def schema_migrations_table_name
839
- SchemaMigration.table_name
840
- end
1078
+ def open
1079
+ Migrator.new(:up, migrations, schema_migration)
1080
+ end
841
1081
 
842
- def get_all_versions(connection = Base.connection)
843
- if connection.table_exists?(schema_migrations_table_name)
844
- SchemaMigration.all.map { |x| x.version.to_i }.sort
845
- else
846
- []
847
- end
1082
+ def get_all_versions
1083
+ if schema_migration.table_exists?
1084
+ schema_migration.all_versions.map(&:to_i)
1085
+ else
1086
+ []
848
1087
  end
1088
+ end
849
1089
 
850
- def current_version(connection = Base.connection)
851
- get_all_versions(connection).max || 0
852
- end
1090
+ def current_version
1091
+ get_all_versions.max || 0
1092
+ rescue ActiveRecord::NoDatabaseError
1093
+ end
853
1094
 
854
- def needs_migration?(connection = Base.connection)
855
- (migrations(migrations_paths).collect(&:version) - get_all_versions(connection)).size > 0
856
- end
1095
+ def needs_migration?
1096
+ (migrations.collect(&:version) - get_all_versions).size > 0
1097
+ end
857
1098
 
858
- def any_migrations?
859
- migrations(migrations_paths).any?
860
- end
1099
+ def any_migrations?
1100
+ migrations.any?
1101
+ end
861
1102
 
862
- def last_version
863
- last_migration.version
864
- end
1103
+ def last_migration #:nodoc:
1104
+ migrations.last || NullMigration.new
1105
+ end
865
1106
 
866
- def last_migration #:nodoc:
867
- migrations(migrations_paths).last || NullMigration.new
868
- 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
869
1113
 
870
- def migrations_paths
871
- @migrations_paths ||= ['db/migrate']
872
- # just to not break things if someone uses: migration_path = some_string
873
- Array(@migrations_paths)
1114
+ MigrationProxy.new(name, version, file, scope)
874
1115
  end
875
1116
 
876
- def migrations_path
877
- migrations_paths.first
1117
+ migrations.sort_by(&:version)
1118
+ end
1119
+
1120
+ def migrations_status
1121
+ db_list = schema_migration.normalized_versions
1122
+
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
1130
+
1131
+ db_list.map! do |version|
1132
+ ["up", version, "********** NO FILE **********"]
878
1133
  end
879
1134
 
880
- def migrations(paths)
881
- paths = Array(paths)
1135
+ (db_list + file_list).sort_by { |_, version, _| version }
1136
+ end
882
1137
 
883
- files = Dir[*paths.map { |p| "#{p}/**/[0-9]*_*.rb" }]
1138
+ def current_environment
1139
+ ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
1140
+ end
884
1141
 
885
- migrations = files.map do |file|
886
- version, name, scope = file.scan(/([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/).first
1142
+ def protected_environment?
1143
+ ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
1144
+ end
887
1145
 
888
- raise IllegalMigrationNameError.new(file) unless version
889
- version = version.to_i
890
- name = name.camelize
1146
+ def last_stored_environment
1147
+ return nil if current_version == 0
1148
+ raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
891
1149
 
892
- MigrationProxy.new(name, version, file, scope)
893
- end
1150
+ environment = ActiveRecord::InternalMetadata[:environment]
1151
+ raise NoEnvironmentInSchemaError unless environment
1152
+ environment
1153
+ end
894
1154
 
895
- migrations.sort_by(&:version)
1155
+ private
1156
+ def migration_files
1157
+ paths = Array(migrations_paths)
1158
+ Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
896
1159
  end
897
1160
 
898
- private
1161
+ def parse_migration_filename(filename)
1162
+ File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1163
+ end
899
1164
 
900
- def move(direction, migrations_paths, steps)
901
- migrator = new(direction, migrations(migrations_paths))
902
- start_index = migrator.migrations.index(migrator.current_migration)
1165
+ def move(direction, steps)
1166
+ migrator = Migrator.new(direction, migrations, schema_migration)
903
1167
 
904
- if start_index
905
- finish = migrator.migrations[start_index + steps]
906
- version = finish ? finish.version : 0
907
- send(direction, migrations_paths, version)
1168
+ if current_version != 0 && !migrator.current_migration
1169
+ raise UnknownMigrationVersionError.new(current_version)
908
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
909
1192
  end
910
1193
  end
911
1194
 
912
- def initialize(direction, migrations, target_version = nil)
913
- raise StandardError.new("This database does not yet support migrations") unless Base.connection.supports_migrations?
1195
+ self.migrations_paths = ["db/migrate"]
914
1196
 
1197
+ def initialize(direction, migrations, schema_migration, target_version = nil)
915
1198
  @direction = direction
916
1199
  @target_version = target_version
917
1200
  @migrated_versions = nil
918
1201
  @migrations = migrations
1202
+ @schema_migration = schema_migration
919
1203
 
920
1204
  validate(@migrations)
921
1205
 
922
- Base.connection.initialize_schema_migrations_table
1206
+ @schema_migration.create_table
1207
+ ActiveRecord::InternalMetadata.create_table
923
1208
  end
924
1209
 
925
1210
  def current_version
@@ -932,32 +1217,18 @@ module ActiveRecord
932
1217
  alias :current :current_migration
933
1218
 
934
1219
  def run
935
- migration = migrations.detect { |m| m.version == @target_version }
936
- raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
937
- unless (up? && migrated.include?(migration.version.to_i)) || (down? && !migrated.include?(migration.version.to_i))
938
- begin
939
- execute_migration_in_transaction(migration, @direction)
940
- rescue => e
941
- canceled_msg = use_transaction?(migration) ? ", this migration was canceled" : ""
942
- raise StandardError, "An error has occurred#{canceled_msg}:\n\n#{e}", e.backtrace
943
- end
1220
+ if use_advisory_lock?
1221
+ with_advisory_lock { run_without_lock }
1222
+ else
1223
+ run_without_lock
944
1224
  end
945
1225
  end
946
1226
 
947
1227
  def migrate
948
- if !target && @target_version && @target_version > 0
949
- raise UnknownMigrationVersionError.new(@target_version)
950
- end
951
-
952
- runnable.each do |migration|
953
- Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
954
-
955
- begin
956
- execute_migration_in_transaction(migration, @direction)
957
- rescue => e
958
- canceled_msg = use_transaction?(migration) ? "this and " : ""
959
- raise StandardError, "An error has occurred, #{canceled_msg}all later migrations canceled:\n\n#{e}", e.backtrace
960
- end
1228
+ if use_advisory_lock?
1229
+ with_advisory_lock { migrate_without_lock }
1230
+ else
1231
+ migrate_without_lock
961
1232
  end
962
1233
  end
963
1234
 
@@ -982,70 +1253,145 @@ module ActiveRecord
982
1253
  end
983
1254
 
984
1255
  def migrated
985
- @migrated_versions ||= Set.new(self.class.get_all_versions)
1256
+ @migrated_versions || load_migrated
986
1257
  end
987
1258
 
988
- private
989
- def ran?(migration)
990
- migrated.include?(migration.version.to_i)
1259
+ def load_migrated
1260
+ @migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
991
1261
  end
992
1262
 
993
- def execute_migration_in_transaction(migration, direction)
994
- ddl_transaction(migration) do
995
- migration.migrate(direction)
996
- 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
997
1272
  end
998
- end
999
1273
 
1000
- def target
1001
- migrations.detect { |m| m.version == @target_version }
1002
- 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
1003
1279
 
1004
- def finish
1005
- migrations.index(target) || migrations.size - 1
1006
- end
1280
+ result = runnable.each do |migration|
1281
+ execute_migration_in_transaction(migration, @direction)
1282
+ end
1007
1283
 
1008
- def start
1009
- up? ? 0 : (migrations.index(current) || 0)
1010
- end
1284
+ record_environment
1285
+ result
1286
+ end
1011
1287
 
1012
- def validate(migrations)
1013
- name ,= migrations.group_by(&:name).find { |_,v| v.length > 1 }
1014
- 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
1015
1293
 
1016
- version ,= migrations.group_by(&:version).find { |_,v| v.length > 1 }
1017
- raise DuplicateMigrationVersionError.new(version) if version
1018
- end
1294
+ def ran?(migration)
1295
+ migrated.include?(migration.version.to_i)
1296
+ end
1019
1297
 
1020
- def record_version_state_after_migrating(version)
1021
- if down?
1022
- migrated.delete(version)
1023
- ActiveRecord::SchemaMigration.where(:version => version.to_s).delete_all
1024
- else
1025
- migrated << version
1026
- 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
1027
1301
  end
1028
- end
1029
1302
 
1030
- def up?
1031
- @direction == :up
1032
- 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)
1033
1306
 
1034
- def down?
1035
- @direction == :down
1036
- end
1307
+ Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
1037
1308
 
1038
- # Wrap the migration in a transaction only if supported by the adapter.
1039
- def ddl_transaction(migration)
1040
- if use_transaction?(migration)
1041
- Base.transaction { yield }
1042
- 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
1043
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
1044
1389
  end
1045
- end
1046
1390
 
1047
- def use_transaction?(migration)
1048
- !migration.disable_ddl_transaction && Base.connection.supports_ddl_transactions?
1049
- 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
1050
1396
  end
1051
1397
  end