activerecord 5.0.6 → 6.0.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 (358) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +638 -2023
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +8 -6
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record/aggregations.rb +249 -246
  8. data/lib/active_record/association_relation.rb +24 -13
  9. data/lib/active_record/associations/alias_tracker.rb +24 -33
  10. data/lib/active_record/associations/association.rb +119 -56
  11. data/lib/active_record/associations/association_scope.rb +94 -94
  12. data/lib/active_record/associations/belongs_to_association.rb +58 -42
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  14. data/lib/active_record/associations/builder/association.rb +18 -25
  15. data/lib/active_record/associations/builder/belongs_to.rb +43 -54
  16. data/lib/active_record/associations/builder/collection_association.rb +7 -18
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -61
  18. data/lib/active_record/associations/builder/has_many.rb +4 -0
  19. data/lib/active_record/associations/builder/has_one.rb +37 -1
  20. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  21. data/lib/active_record/associations/collection_association.rb +80 -252
  22. data/lib/active_record/associations/collection_proxy.rb +158 -121
  23. data/lib/active_record/associations/foreign_association.rb +9 -0
  24. data/lib/active_record/associations/has_many_association.rb +23 -29
  25. data/lib/active_record/associations/has_many_through_association.rb +58 -44
  26. data/lib/active_record/associations/has_one_association.rb +59 -54
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +38 -90
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  31. data/lib/active_record/associations/join_dependency.rb +134 -176
  32. data/lib/active_record/associations/preloader/association.rb +84 -125
  33. data/lib/active_record/associations/preloader/through_association.rb +82 -75
  34. data/lib/active_record/associations/preloader.rb +90 -102
  35. data/lib/active_record/associations/singular_association.rb +12 -45
  36. data/lib/active_record/associations/through_association.rb +26 -14
  37. data/lib/active_record/associations.rb +1603 -1592
  38. data/lib/active_record/attribute_assignment.rb +54 -60
  39. data/lib/active_record/attribute_decorators.rb +38 -15
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -7
  41. data/lib/active_record/attribute_methods/dirty.rb +179 -109
  42. data/lib/active_record/attribute_methods/primary_key.rb +86 -91
  43. data/lib/active_record/attribute_methods/query.rb +4 -3
  44. data/lib/active_record/attribute_methods/read.rb +21 -49
  45. data/lib/active_record/attribute_methods/serialization.rb +30 -7
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -64
  47. data/lib/active_record/attribute_methods/write.rb +35 -33
  48. data/lib/active_record/attribute_methods.rb +66 -106
  49. data/lib/active_record/attributes.rb +38 -24
  50. data/lib/active_record/autosave_association.rb +53 -32
  51. data/lib/active_record/base.rb +27 -24
  52. data/lib/active_record/callbacks.rb +63 -33
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +11 -11
  55. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +553 -321
  56. data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
  57. data/lib/active_record/connection_adapters/abstract/database_statements.rb +213 -94
  58. data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -28
  59. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
  60. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  61. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -27
  62. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +207 -126
  63. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  64. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +369 -199
  65. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
  66. data/lib/active_record/connection_adapters/abstract_adapter.rb +363 -202
  67. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -551
  68. data/lib/active_record/connection_adapters/column.rb +41 -13
  69. data/lib/active_record/connection_adapters/connection_specification.rb +172 -138
  70. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
  71. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  72. data/lib/active_record/connection_adapters/mysql/database_statements.rb +143 -49
  73. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -22
  74. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  75. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +50 -45
  76. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
  77. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  78. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  79. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
  80. data/lib/active_record/connection_adapters/mysql2_adapter.rb +49 -30
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +22 -7
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +60 -54
  83. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -10
  85. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -17
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  98. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +31 -9
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -30
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +9 -4
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +35 -32
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +380 -300
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +10 -6
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +382 -275
  116. data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
  118. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +74 -19
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +254 -262
  126. data/lib/active_record/connection_adapters/statement_pool.rb +9 -7
  127. data/lib/active_record/connection_handling.rb +159 -40
  128. data/lib/active_record/core.rb +202 -162
  129. data/lib/active_record/counter_cache.rb +57 -28
  130. data/lib/active_record/database_configurations/database_config.rb +37 -0
  131. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  132. data/lib/active_record/database_configurations/url_config.rb +79 -0
  133. data/lib/active_record/database_configurations.rb +233 -0
  134. data/lib/active_record/define_callbacks.rb +22 -0
  135. data/lib/active_record/dynamic_matchers.rb +87 -86
  136. data/lib/active_record/enum.rb +60 -23
  137. data/lib/active_record/errors.rb +114 -18
  138. data/lib/active_record/explain.rb +4 -3
  139. data/lib/active_record/explain_registry.rb +3 -1
  140. data/lib/active_record/explain_subscriber.rb +9 -4
  141. data/lib/active_record/fixture_set/file.rb +13 -8
  142. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  143. data/lib/active_record/fixture_set/render_context.rb +17 -0
  144. data/lib/active_record/fixture_set/table_row.rb +153 -0
  145. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  146. data/lib/active_record/fixtures.rb +195 -502
  147. data/lib/active_record/gem_version.rb +4 -2
  148. data/lib/active_record/inheritance.rb +151 -97
  149. data/lib/active_record/insert_all.rb +179 -0
  150. data/lib/active_record/integration.rb +116 -25
  151. data/lib/active_record/internal_metadata.rb +15 -18
  152. data/lib/active_record/legacy_yaml_adapter.rb +4 -2
  153. data/lib/active_record/locking/optimistic.rb +78 -87
  154. data/lib/active_record/locking/pessimistic.rb +18 -6
  155. data/lib/active_record/log_subscriber.rb +48 -29
  156. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  157. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/migration/command_recorder.rb +143 -97
  160. data/lib/active_record/migration/compatibility.rb +174 -56
  161. data/lib/active_record/migration/join_table.rb +8 -6
  162. data/lib/active_record/migration.rb +367 -300
  163. data/lib/active_record/model_schema.rb +145 -139
  164. data/lib/active_record/nested_attributes.rb +214 -201
  165. data/lib/active_record/no_touching.rb +10 -1
  166. data/lib/active_record/null_relation.rb +13 -34
  167. data/lib/active_record/persistence.rb +442 -72
  168. data/lib/active_record/query_cache.rb +15 -14
  169. data/lib/active_record/querying.rb +36 -23
  170. data/lib/active_record/railtie.rb +128 -36
  171. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  172. data/lib/active_record/railties/console_sandbox.rb +2 -0
  173. data/lib/active_record/railties/controller_runtime.rb +34 -33
  174. data/lib/active_record/railties/databases.rake +309 -177
  175. data/lib/active_record/readonly_attributes.rb +5 -4
  176. data/lib/active_record/reflection.rb +211 -249
  177. data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
  178. data/lib/active_record/relation/batches.rb +99 -52
  179. data/lib/active_record/relation/calculations.rb +211 -172
  180. data/lib/active_record/relation/delegation.rb +67 -65
  181. data/lib/active_record/relation/finder_methods.rb +208 -247
  182. data/lib/active_record/relation/from_clause.rb +2 -8
  183. data/lib/active_record/relation/merger.rb +78 -61
  184. data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
  185. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  186. data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
  187. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  188. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  189. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  190. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  191. data/lib/active_record/relation/predicate_builder.rb +86 -104
  192. data/lib/active_record/relation/query_attribute.rb +33 -2
  193. data/lib/active_record/relation/query_methods.rb +458 -329
  194. data/lib/active_record/relation/record_fetch_warning.rb +5 -3
  195. data/lib/active_record/relation/spawn_methods.rb +8 -7
  196. data/lib/active_record/relation/where_clause.rb +111 -95
  197. data/lib/active_record/relation/where_clause_factory.rb +6 -11
  198. data/lib/active_record/relation.rb +429 -318
  199. data/lib/active_record/result.rb +69 -39
  200. data/lib/active_record/runtime_registry.rb +5 -3
  201. data/lib/active_record/sanitization.rb +83 -99
  202. data/lib/active_record/schema.rb +7 -14
  203. data/lib/active_record/schema_dumper.rb +71 -69
  204. data/lib/active_record/schema_migration.rb +15 -5
  205. data/lib/active_record/scoping/default.rb +93 -95
  206. data/lib/active_record/scoping/named.rb +45 -25
  207. data/lib/active_record/scoping.rb +20 -19
  208. data/lib/active_record/secure_token.rb +4 -2
  209. data/lib/active_record/serialization.rb +2 -0
  210. data/lib/active_record/statement_cache.rb +63 -28
  211. data/lib/active_record/store.rb +121 -41
  212. data/lib/active_record/suppressor.rb +4 -1
  213. data/lib/active_record/table_metadata.rb +26 -20
  214. data/lib/active_record/tasks/database_tasks.rb +276 -85
  215. data/lib/active_record/tasks/mysql_database_tasks.rb +54 -90
  216. data/lib/active_record/tasks/postgresql_database_tasks.rb +78 -47
  217. data/lib/active_record/tasks/sqlite_database_tasks.rb +34 -16
  218. data/lib/active_record/test_databases.rb +23 -0
  219. data/lib/active_record/test_fixtures.rb +224 -0
  220. data/lib/active_record/timestamp.rb +70 -35
  221. data/lib/active_record/touch_later.rb +7 -4
  222. data/lib/active_record/transactions.rb +133 -149
  223. data/lib/active_record/translation.rb +3 -1
  224. data/lib/active_record/type/adapter_specific_registry.rb +44 -45
  225. data/lib/active_record/type/date.rb +2 -0
  226. data/lib/active_record/type/date_time.rb +2 -0
  227. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  228. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  229. data/lib/active_record/type/internal/timezone.rb +2 -0
  230. data/lib/active_record/type/json.rb +30 -0
  231. data/lib/active_record/type/serialized.rb +16 -8
  232. data/lib/active_record/type/text.rb +11 -0
  233. data/lib/active_record/type/time.rb +2 -1
  234. data/lib/active_record/type/type_map.rb +13 -15
  235. data/lib/active_record/type/unsigned_integer.rb +17 -0
  236. data/lib/active_record/type.rb +23 -17
  237. data/lib/active_record/type_caster/connection.rb +17 -12
  238. data/lib/active_record/type_caster/map.rb +5 -4
  239. data/lib/active_record/type_caster.rb +4 -2
  240. data/lib/active_record/validations/absence.rb +2 -0
  241. data/lib/active_record/validations/associated.rb +3 -1
  242. data/lib/active_record/validations/length.rb +2 -0
  243. data/lib/active_record/validations/presence.rb +4 -2
  244. data/lib/active_record/validations/uniqueness.rb +29 -42
  245. data/lib/active_record/validations.rb +7 -4
  246. data/lib/active_record/version.rb +3 -1
  247. data/lib/active_record.rb +36 -22
  248. data/lib/arel/alias_predication.rb +9 -0
  249. data/lib/arel/attributes/attribute.rb +37 -0
  250. data/lib/arel/attributes.rb +22 -0
  251. data/lib/arel/collectors/bind.rb +24 -0
  252. data/lib/arel/collectors/composite.rb +31 -0
  253. data/lib/arel/collectors/plain_string.rb +20 -0
  254. data/lib/arel/collectors/sql_string.rb +20 -0
  255. data/lib/arel/collectors/substitute_binds.rb +28 -0
  256. data/lib/arel/crud.rb +42 -0
  257. data/lib/arel/delete_manager.rb +18 -0
  258. data/lib/arel/errors.rb +9 -0
  259. data/lib/arel/expressions.rb +29 -0
  260. data/lib/arel/factory_methods.rb +49 -0
  261. data/lib/arel/insert_manager.rb +49 -0
  262. data/lib/arel/math.rb +45 -0
  263. data/lib/arel/nodes/and.rb +32 -0
  264. data/lib/arel/nodes/ascending.rb +23 -0
  265. data/lib/arel/nodes/binary.rb +52 -0
  266. data/lib/arel/nodes/bind_param.rb +36 -0
  267. data/lib/arel/nodes/case.rb +55 -0
  268. data/lib/arel/nodes/casted.rb +50 -0
  269. data/lib/arel/nodes/comment.rb +29 -0
  270. data/lib/arel/nodes/count.rb +12 -0
  271. data/lib/arel/nodes/delete_statement.rb +45 -0
  272. data/lib/arel/nodes/descending.rb +23 -0
  273. data/lib/arel/nodes/equality.rb +18 -0
  274. data/lib/arel/nodes/extract.rb +24 -0
  275. data/lib/arel/nodes/false.rb +16 -0
  276. data/lib/arel/nodes/full_outer_join.rb +8 -0
  277. data/lib/arel/nodes/function.rb +44 -0
  278. data/lib/arel/nodes/grouping.rb +8 -0
  279. data/lib/arel/nodes/in.rb +8 -0
  280. data/lib/arel/nodes/infix_operation.rb +80 -0
  281. data/lib/arel/nodes/inner_join.rb +8 -0
  282. data/lib/arel/nodes/insert_statement.rb +37 -0
  283. data/lib/arel/nodes/join_source.rb +20 -0
  284. data/lib/arel/nodes/matches.rb +18 -0
  285. data/lib/arel/nodes/named_function.rb +23 -0
  286. data/lib/arel/nodes/node.rb +50 -0
  287. data/lib/arel/nodes/node_expression.rb +13 -0
  288. data/lib/arel/nodes/outer_join.rb +8 -0
  289. data/lib/arel/nodes/over.rb +15 -0
  290. data/lib/arel/nodes/regexp.rb +16 -0
  291. data/lib/arel/nodes/right_outer_join.rb +8 -0
  292. data/lib/arel/nodes/select_core.rb +67 -0
  293. data/lib/arel/nodes/select_statement.rb +41 -0
  294. data/lib/arel/nodes/sql_literal.rb +16 -0
  295. data/lib/arel/nodes/string_join.rb +11 -0
  296. data/lib/arel/nodes/table_alias.rb +27 -0
  297. data/lib/arel/nodes/terminal.rb +16 -0
  298. data/lib/arel/nodes/true.rb +16 -0
  299. data/lib/arel/nodes/unary.rb +45 -0
  300. data/lib/arel/nodes/unary_operation.rb +20 -0
  301. data/lib/arel/nodes/unqualified_column.rb +22 -0
  302. data/lib/arel/nodes/update_statement.rb +41 -0
  303. data/lib/arel/nodes/values_list.rb +9 -0
  304. data/lib/arel/nodes/window.rb +126 -0
  305. data/lib/arel/nodes/with.rb +11 -0
  306. data/lib/arel/nodes.rb +68 -0
  307. data/lib/arel/order_predications.rb +13 -0
  308. data/lib/arel/predications.rb +257 -0
  309. data/lib/arel/select_manager.rb +271 -0
  310. data/lib/arel/table.rb +110 -0
  311. data/lib/arel/tree_manager.rb +72 -0
  312. data/lib/arel/update_manager.rb +34 -0
  313. data/lib/arel/visitors/depth_first.rb +204 -0
  314. data/lib/arel/visitors/dot.rb +297 -0
  315. data/lib/arel/visitors/ibm_db.rb +34 -0
  316. data/lib/arel/visitors/informix.rb +62 -0
  317. data/lib/arel/visitors/mssql.rb +157 -0
  318. data/lib/arel/visitors/mysql.rb +83 -0
  319. data/lib/arel/visitors/oracle.rb +159 -0
  320. data/lib/arel/visitors/oracle12.rb +66 -0
  321. data/lib/arel/visitors/postgresql.rb +110 -0
  322. data/lib/arel/visitors/sqlite.rb +39 -0
  323. data/lib/arel/visitors/to_sql.rb +889 -0
  324. data/lib/arel/visitors/visitor.rb +46 -0
  325. data/lib/arel/visitors/where_sql.rb +23 -0
  326. data/lib/arel/visitors.rb +20 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +58 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  330. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
  332. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
  334. data/lib/rails/generators/active_record/migration.rb +17 -2
  335. data/lib/rails/generators/active_record/model/model_generator.rb +9 -29
  336. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  337. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +133 -50
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  347. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  348. data/lib/active_record/attribute.rb +0 -213
  349. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  350. data/lib/active_record/attribute_set/builder.rb +0 -130
  351. data/lib/active_record/attribute_set.rb +0 -110
  352. data/lib/active_record/collection_cache_key.rb +0 -50
  353. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  354. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  355. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  356. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  357. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  358. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,9 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "benchmark"
1
4
  require "set"
2
5
  require "zlib"
3
6
  require "active_support/core_ext/module/attribute_accessors"
7
+ require "active_support/actionable_error"
4
8
 
5
9
  module ActiveRecord
6
- class MigrationError < ActiveRecordError#:nodoc:
10
+ class MigrationError < ActiveRecordError #:nodoc:
7
11
  def initialize(message = nil)
8
12
  message = "\n\n#{message}\n\n" if message
9
13
  super
@@ -20,7 +24,7 @@ module ActiveRecord
20
24
  # t.string :zipcode
21
25
  # end
22
26
  #
23
- # execute <<-SQL
27
+ # execute <<~SQL
24
28
  # ALTER TABLE distributors
25
29
  # ADD CONSTRAINT zipchk
26
30
  # CHECK (char_length(zipcode) = 5) NO INHERIT;
@@ -38,7 +42,7 @@ module ActiveRecord
38
42
  # t.string :zipcode
39
43
  # end
40
44
  #
41
- # execute <<-SQL
45
+ # execute <<~SQL
42
46
  # ALTER TABLE distributors
43
47
  # ADD CONSTRAINT zipchk
44
48
  # CHECK (char_length(zipcode) = 5) NO INHERIT;
@@ -46,7 +50,7 @@ module ActiveRecord
46
50
  # end
47
51
  #
48
52
  # def down
49
- # execute <<-SQL
53
+ # execute <<~SQL
50
54
  # ALTER TABLE distributors
51
55
  # DROP CONSTRAINT zipchk
52
56
  # SQL
@@ -65,7 +69,7 @@ module ActiveRecord
65
69
  #
66
70
  # reversible do |dir|
67
71
  # dir.up do
68
- # execute <<-SQL
72
+ # execute <<~SQL
69
73
  # ALTER TABLE distributors
70
74
  # ADD CONSTRAINT zipchk
71
75
  # CHECK (char_length(zipcode) = 5) NO INHERIT;
@@ -73,7 +77,7 @@ module ActiveRecord
73
77
  # end
74
78
  #
75
79
  # dir.down do
76
- # execute <<-SQL
80
+ # execute <<~SQL
77
81
  # ALTER TABLE distributors
78
82
  # DROP CONSTRAINT zipchk
79
83
  # SQL
@@ -84,7 +88,7 @@ module ActiveRecord
84
88
  class IrreversibleMigration < MigrationError
85
89
  end
86
90
 
87
- class DuplicateMigrationVersionError < MigrationError#:nodoc:
91
+ class DuplicateMigrationVersionError < MigrationError #:nodoc:
88
92
  def initialize(version = nil)
89
93
  if version
90
94
  super("Multiple migrations have the version number #{version}.")
@@ -94,7 +98,7 @@ module ActiveRecord
94
98
  end
95
99
  end
96
100
 
97
- class DuplicateMigrationNameError < MigrationError#:nodoc:
101
+ class DuplicateMigrationNameError < MigrationError #:nodoc:
98
102
  def initialize(name = nil)
99
103
  if name
100
104
  super("Multiple migrations have the name #{name}.")
@@ -114,7 +118,7 @@ module ActiveRecord
114
118
  end
115
119
  end
116
120
 
117
- class IllegalMigrationNameError < MigrationError#:nodoc:
121
+ class IllegalMigrationNameError < MigrationError #:nodoc:
118
122
  def initialize(name = nil)
119
123
  if name
120
124
  super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).")
@@ -124,12 +128,18 @@ module ActiveRecord
124
128
  end
125
129
  end
126
130
 
127
- 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
+
128
138
  def initialize(message = nil)
129
139
  if !message && defined?(Rails.env)
130
- super("Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate RAILS_ENV=#{::Rails.env}")
140
+ super("Migrations are pending. To resolve this issue, run:\n\n rails db:migrate RAILS_ENV=#{::Rails.env}")
131
141
  elsif !message
132
- super("Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate")
142
+ super("Migrations are pending. To resolve this issue, run:\n\n rails db:migrate")
133
143
  else
134
144
  super
135
145
  end
@@ -137,7 +147,8 @@ module ActiveRecord
137
147
  end
138
148
 
139
149
  class ConcurrentMigrationError < MigrationError #:nodoc:
140
- DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running.".freeze
150
+ DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
151
+ RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
141
152
 
142
153
  def initialize(message = DEFAULT_MESSAGE)
143
154
  super
@@ -146,7 +157,7 @@ module ActiveRecord
146
157
 
147
158
  class NoEnvironmentInSchemaError < MigrationError #:nodoc:
148
159
  def initialize
149
- msg = "Environment data not found in the schema. To resolve this issue, run: \n\n bin/rails db:environment:set"
160
+ msg = "Environment data not found in the schema. To resolve this issue, run: \n\n rails db:environment:set"
150
161
  if defined?(Rails.env)
151
162
  super("#{msg} RAILS_ENV=#{::Rails.env}")
152
163
  else
@@ -157,7 +168,7 @@ module ActiveRecord
157
168
 
158
169
  class ProtectedEnvironmentError < ActiveRecordError #:nodoc:
159
170
  def initialize(env = "production")
160
- msg = "You are attempting to run a destructive action against your '#{env}' database.\n"
171
+ msg = +"You are attempting to run a destructive action against your '#{env}' database.\n"
161
172
  msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
162
173
  msg << "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
163
174
  super(msg)
@@ -166,10 +177,10 @@ module ActiveRecord
166
177
 
167
178
  class EnvironmentMismatchError < ActiveRecordError
168
179
  def initialize(current: nil, stored: nil)
169
- msg = "You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
180
+ msg = +"You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
170
181
  msg << "You are running in `#{ current }` environment. "
171
182
  msg << "If you are sure you want to continue, first set the environment using:\n\n"
172
- msg << " bin/rails db:environment:set"
183
+ msg << " rails db:environment:set"
173
184
  if defined?(Rails.env)
174
185
  super("#{msg} RAILS_ENV=#{::Rails.env}\n\n")
175
186
  else
@@ -277,8 +288,10 @@ module ActiveRecord
277
288
  #
278
289
  # * <tt>change_column(table_name, column_name, type, options)</tt>: Changes
279
290
  # the column to a different type using the same parameters as add_column.
280
- # * <tt>change_column_default(table_name, column_name, default)</tt>: Sets a
281
- # default value for +column_name+ defined by +default+ on +table_name+.
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.
282
295
  # * <tt>change_column_null(table_name, column_name, null, default = nil)</tt>:
283
296
  # Sets or removes a +NOT NULL+ constraint on +column_name+. The +null+ flag
284
297
  # indicates whether the value can be +NULL+. See
@@ -302,7 +315,7 @@ module ActiveRecord
302
315
  # named +column_name+ from the table called +table_name+.
303
316
  # * <tt>remove_columns(table_name, *column_names)</tt>: Removes the given
304
317
  # columns from the table definition.
305
- # * <tt>remove_foreign_key(from_table, options_or_to_table)</tt>: Removes the
318
+ # * <tt>remove_foreign_key(from_table, to_table = nil, **options)</tt>: Removes the
306
319
  # given foreign key from the table called +table_name+.
307
320
  # * <tt>remove_index(table_name, column: column_names)</tt>: Removes the index
308
321
  # specified by +column_names+.
@@ -346,13 +359,13 @@ module ActiveRecord
346
359
  # <tt>rails db:migrate</tt>. This will update the database by running all of the
347
360
  # pending migrations, creating the <tt>schema_migrations</tt> table
348
361
  # (see "About the schema_migrations table" section below) if missing. It will also
349
- # 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
350
363
  # to match the structure of your database.
351
364
  #
352
365
  # To roll the database back to a previous migration version, use
353
- # <tt>rails 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
354
367
  # you wish to downgrade. Alternatively, you can also use the STEP option if you
355
- # wish to rollback last few migrations. <tt>rails db:migrate STEP=2</tt> will rollback
368
+ # wish to rollback last few migrations. <tt>rails db:rollback STEP=2</tt> will rollback
356
369
  # the latest two migrations.
357
370
  #
358
371
  # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
@@ -481,9 +494,9 @@ module ActiveRecord
481
494
  # This migration will create the horses table for you on the way up, and
482
495
  # automatically figure out how to drop the table on the way down.
483
496
  #
484
- # Some commands like +remove_column+ cannot be reversed. If you care to
485
- # define how to move up and down in these cases, you should define the +up+
486
- # 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.
487
500
  #
488
501
  # If a command cannot be reversed, an
489
502
  # <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
@@ -510,17 +523,20 @@ module ActiveRecord
510
523
  # Remember that you can still open your own transactions, even if you
511
524
  # are in a Migration with <tt>self.disable_ddl_transaction!</tt>.
512
525
  class Migration
513
- autoload :CommandRecorder, 'active_record/migration/command_recorder'
514
- autoload :Compatibility, 'active_record/migration/compatibility'
526
+ autoload :CommandRecorder, "active_record/migration/command_recorder"
527
+ autoload :Compatibility, "active_record/migration/compatibility"
515
528
 
516
529
  # This must be defined before the inherited hook, below
517
- class Current < Migration # :nodoc:
530
+ class Current < Migration #:nodoc:
518
531
  end
519
532
 
520
- def self.inherited(subclass) # :nodoc:
533
+ def self.inherited(subclass) #:nodoc:
521
534
  super
522
535
  if subclass.superclass == Migration
523
- subclass.include Compatibility::Legacy
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]"
524
540
  end
525
541
  end
526
542
 
@@ -532,7 +548,7 @@ module ActiveRecord
532
548
  ActiveRecord::VERSION::STRING.to_f
533
549
  end
534
550
 
535
- MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
551
+ MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ #:nodoc:
536
552
 
537
553
  # This class is used to verify that all migrations have been run before
538
554
  # loading a web page if <tt>config.active_record.migration_error</tt> is set to :page_load
@@ -543,57 +559,64 @@ module ActiveRecord
543
559
  end
544
560
 
545
561
  def call(env)
546
- if connection.supports_migrations?
547
- mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
548
- if @last_check < mtime
549
- ActiveRecord::Migration.check_pending!(connection)
550
- @last_check = mtime
551
- 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
552
566
  end
553
567
  @app.call(env)
554
568
  end
555
569
 
556
570
  private
557
571
 
558
- def connection
559
- ActiveRecord::Base.connection
560
- end
572
+ def connection
573
+ ActiveRecord::Base.connection
574
+ end
561
575
  end
562
576
 
563
577
  class << self
564
- attr_accessor :delegate # :nodoc:
565
- attr_accessor :disable_ddl_transaction # :nodoc:
578
+ attr_accessor :delegate #:nodoc:
579
+ attr_accessor :disable_ddl_transaction #:nodoc:
566
580
 
567
- def nearest_delegate # :nodoc:
581
+ def nearest_delegate #:nodoc:
568
582
  delegate || superclass.nearest_delegate
569
583
  end
570
584
 
571
585
  # Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending.
572
586
  def check_pending!(connection = Base.connection)
573
- raise ActiveRecord::PendingMigrationError if ActiveRecord::Migrator.needs_migration?(connection)
587
+ raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration?
574
588
  end
575
589
 
576
590
  def load_schema_if_pending!
577
- if ActiveRecord::Migrator.needs_migration? || !ActiveRecord::Migrator.any_migrations?
591
+ current_config = Base.connection_config
592
+ all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
593
+
594
+ needs_update = !all_configs.all? do |db_config|
595
+ Tasks::DatabaseTasks.schema_up_to_date?(db_config.config, ActiveRecord::Base.schema_format, nil, Rails.env, db_config.spec_name)
596
+ end
597
+
598
+ if needs_update
578
599
  # Roundtrip to Rake to allow plugins to hook into database initialization.
579
- FileUtils.cd Rails.root do
580
- current_config = Base.connection_config
600
+ root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
601
+ FileUtils.cd(root) do
581
602
  Base.clear_all_connections!
582
603
  system("bin/rails db:test:prepare")
583
- # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
584
- Base.establish_connection(current_config)
585
604
  end
586
- check_pending!
587
605
  end
606
+
607
+ # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
608
+ Base.establish_connection(current_config)
609
+
610
+ check_pending!
588
611
  end
589
612
 
590
- def maintain_test_schema! # :nodoc:
613
+ def maintain_test_schema! #:nodoc:
591
614
  if ActiveRecord::Base.maintain_test_schema
592
615
  suppress_messages { load_schema_if_pending! }
593
616
  end
594
617
  end
595
618
 
596
- def method_missing(name, *args, &block) # :nodoc:
619
+ def method_missing(name, *args, &block) #:nodoc:
597
620
  nearest_delegate.send(name, *args, &block)
598
621
  end
599
622
 
@@ -610,7 +633,7 @@ module ActiveRecord
610
633
  end
611
634
  end
612
635
 
613
- def disable_ddl_transaction # :nodoc:
636
+ def disable_ddl_transaction #:nodoc:
614
637
  self.class.disable_ddl_transaction
615
638
  end
616
639
 
@@ -670,15 +693,13 @@ module ActiveRecord
670
693
  if connection.respond_to? :revert
671
694
  connection.revert { yield }
672
695
  else
673
- recorder = CommandRecorder.new(connection)
696
+ recorder = command_recorder
674
697
  @connection = recorder
675
698
  suppress_messages do
676
699
  connection.revert { yield }
677
700
  end
678
701
  @connection = recorder.delegate
679
- recorder.commands.each do |cmd, args, block|
680
- send(cmd, *args, &block)
681
- end
702
+ recorder.replay(self)
682
703
  end
683
704
  end
684
705
  end
@@ -687,7 +708,7 @@ module ActiveRecord
687
708
  connection.respond_to?(:reverting) && connection.reverting
688
709
  end
689
710
 
690
- class ReversibleBlockHelper < Struct.new(:reverting) # :nodoc:
711
+ ReversibleBlockHelper = Struct.new(:reverting) do #:nodoc:
691
712
  def up
692
713
  yield unless reverting
693
714
  end
@@ -725,7 +746,25 @@ module ActiveRecord
725
746
  # end
726
747
  def reversible
727
748
  helper = ReversibleBlockHelper.new(reverting?)
728
- 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?
729
768
  end
730
769
 
731
770
  # Runs the given migration classes.
@@ -767,7 +806,7 @@ module ActiveRecord
767
806
  when :down then announce "reverting"
768
807
  end
769
808
 
770
- time = nil
809
+ time = nil
771
810
  ActiveRecord::Base.connection_pool.with_connection do |conn|
772
811
  time = Benchmark.measure do
773
812
  exec_migration(conn, direction)
@@ -795,7 +834,7 @@ module ActiveRecord
795
834
  @connection = nil
796
835
  end
797
836
 
798
- def write(text="")
837
+ def write(text = "")
799
838
  puts(text) if verbose
800
839
  end
801
840
 
@@ -805,10 +844,14 @@ module ActiveRecord
805
844
  write "== %s %s" % [text, "=" * length]
806
845
  end
807
846
 
808
- 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)
809
850
  write "#{subitem ? " ->" : "--"} #{message}"
810
851
  end
811
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.
812
855
  def say_with_time(message)
813
856
  say(message)
814
857
  result = nil
@@ -818,6 +861,7 @@ module ActiveRecord
818
861
  result
819
862
  end
820
863
 
864
+ # Takes a block as an argument and suppresses any output generated by the block.
821
865
  def suppress_messages
822
866
  save, self.verbose = verbose, false
823
867
  yield
@@ -830,7 +874,7 @@ module ActiveRecord
830
874
  end
831
875
 
832
876
  def method_missing(method, *arguments, &block)
833
- arg_list = arguments.map(&:inspect) * ', '
877
+ arg_list = arguments.map(&:inspect) * ", "
834
878
 
835
879
  say_with_time "#{method}(#{arg_list})" do
836
880
  unless connection.respond_to? :revert
@@ -849,26 +893,29 @@ module ActiveRecord
849
893
 
850
894
  def copy(destination, sources, options = {})
851
895
  copied = []
896
+ schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
852
897
 
853
898
  FileUtils.mkdir_p(destination) unless File.exist?(destination)
854
899
 
855
- destination_migrations = ActiveRecord::Migrator.migrations(destination)
900
+ destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
856
901
  last = destination_migrations.last
857
902
  sources.each do |scope, path|
858
- source_migrations = ActiveRecord::Migrator.migrations(path)
903
+ source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
859
904
 
860
905
  source_migrations.each do |migration|
861
906
  source = File.binread(migration.filename)
862
907
  inserted_comment = "# This migration comes from #{scope} (originally #{migration.version})\n"
863
- if /\A#.*\b(?:en)?coding:\s*\S+/ =~ source
908
+ magic_comments = +""
909
+ loop do
864
910
  # If we have a magic comment in the original migration,
865
911
  # insert our comment after the first newline(end of the magic comment line)
866
912
  # so the magic keep working.
867
913
  # Note that magic comments must be at the first line(except sh-bang).
868
- source[/\n/] = "\n#{inserted_comment}"
869
- else
870
- source = "#{inserted_comment}#{source}"
914
+ source.sub!(/\A(?:#.*\b(?:en)?coding:\s*\S+|#\s*frozen_string_literal:\s*(?:true|false)).*\n/) do |magic_comment|
915
+ magic_comments << magic_comment; ""
916
+ end || break
871
917
  end
918
+ source = "#{magic_comments}#{inserted_comment}#{source}"
872
919
 
873
920
  if duplicate = destination_migrations.detect { |m| m.name == migration.name }
874
921
  if options[:on_skip] && duplicate.scope != scope.to_s
@@ -922,19 +969,22 @@ module ActiveRecord
922
969
  end
923
970
 
924
971
  private
925
- def execute_block
926
- if connection.respond_to? :execute_block
927
- super # use normal delegation to record the block
928
- else
929
- yield
972
+ def execute_block
973
+ if connection.respond_to? :execute_block
974
+ super # use normal delegation to record the block
975
+ else
976
+ yield
977
+ end
978
+ end
979
+
980
+ def command_recorder
981
+ CommandRecorder.new(connection)
930
982
  end
931
- end
932
983
  end
933
984
 
934
985
  # MigrationProxy is used to defer loading of the actual migration classes
935
986
  # until they are needed
936
- class MigrationProxy < Struct.new(:name, :version, :filename, :scope)
937
-
987
+ MigrationProxy = Struct.new(:name, :version, :filename, :scope) do
938
988
  def initialize(name, version, filename, scope)
939
989
  super
940
990
  @migration = nil
@@ -960,7 +1010,6 @@ module ActiveRecord
960
1010
  require(File.expand_path(filename))
961
1011
  name.constantize.new(name, version)
962
1012
  end
963
-
964
1013
  end
965
1014
 
966
1015
  class NullMigration < MigrationProxy #:nodoc:
@@ -973,159 +1022,189 @@ module ActiveRecord
973
1022
  end
974
1023
  end
975
1024
 
976
- class Migrator#:nodoc:
977
- class << self
978
- attr_writer :migrations_paths
979
- alias :migrations_path= :migrations_paths=
980
-
981
- def migrate(migrations_paths, target_version = nil, &block)
982
- case
983
- when target_version.nil?
984
- up(migrations_paths, target_version, &block)
985
- when current_version == 0 && target_version == 0
986
- []
987
- when current_version > target_version
988
- down(migrations_paths, target_version, &block)
989
- else
990
- up(migrations_paths, target_version, &block)
991
- end
992
- end
1025
+ class MigrationContext #:nodoc:
1026
+ attr_reader :migrations_paths, :schema_migration
993
1027
 
994
- def rollback(migrations_paths, steps=1)
995
- move(:down, migrations_paths, steps)
996
- end
1028
+ def initialize(migrations_paths, schema_migration)
1029
+ @migrations_paths = migrations_paths
1030
+ @schema_migration = schema_migration
1031
+ end
997
1032
 
998
- def forward(migrations_paths, steps=1)
999
- 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)
1000
1043
  end
1044
+ end
1045
+
1046
+ def rollback(steps = 1)
1047
+ move(:down, steps)
1048
+ end
1001
1049
 
1002
- def up(migrations_paths, target_version = nil)
1003
- migrations = migrations(migrations_paths)
1004
- migrations.select! { |m| yield m } if block_given?
1050
+ def forward(steps = 1)
1051
+ move(:up, steps)
1052
+ end
1005
1053
 
1006
- 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
1007
1059
  end
1008
1060
 
1009
- def down(migrations_paths, target_version = nil)
1010
- migrations = migrations(migrations_paths)
1011
- migrations.select! { |m| yield m } if block_given?
1061
+ Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
1062
+ end
1012
1063
 
1013
- 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
1014
1069
  end
1015
1070
 
1016
- def run(direction, migrations_paths, target_version)
1017
- new(direction, migrations(migrations_paths), target_version).run
1018
- end
1071
+ Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
1072
+ end
1019
1073
 
1020
- def open(migrations_paths)
1021
- new(:up, migrations(migrations_paths), nil)
1022
- end
1074
+ def run(direction, target_version)
1075
+ Migrator.new(direction, migrations, schema_migration, target_version).run
1076
+ end
1023
1077
 
1024
- def schema_migrations_table_name
1025
- SchemaMigration.table_name
1026
- end
1078
+ def open
1079
+ Migrator.new(:up, migrations, schema_migration)
1080
+ end
1027
1081
 
1028
- def get_all_versions(connection = Base.connection)
1029
- ActiveSupport::Deprecation.silence do
1030
- if connection.table_exists?(schema_migrations_table_name)
1031
- SchemaMigration.all.map { |x| x.version.to_i }.sort
1032
- else
1033
- []
1034
- end
1035
- end
1082
+ def get_all_versions
1083
+ if schema_migration.table_exists?
1084
+ schema_migration.all_versions.map(&:to_i)
1085
+ else
1086
+ []
1036
1087
  end
1088
+ end
1037
1089
 
1038
- def current_version(connection = Base.connection)
1039
- get_all_versions(connection).max || 0
1040
- end
1090
+ def current_version
1091
+ get_all_versions.max || 0
1092
+ rescue ActiveRecord::NoDatabaseError
1093
+ end
1041
1094
 
1042
- def needs_migration?(connection = Base.connection)
1043
- (migrations(migrations_paths).collect(&:version) - get_all_versions(connection)).size > 0
1044
- end
1095
+ def needs_migration?
1096
+ (migrations.collect(&:version) - get_all_versions).size > 0
1097
+ end
1045
1098
 
1046
- def any_migrations?
1047
- migrations(migrations_paths).any?
1048
- end
1099
+ def any_migrations?
1100
+ migrations.any?
1101
+ end
1049
1102
 
1050
- def last_migration #:nodoc:
1051
- migrations(migrations_paths).last || NullMigration.new
1052
- end
1103
+ def last_migration #:nodoc:
1104
+ migrations.last || NullMigration.new
1105
+ end
1053
1106
 
1054
- def migrations_paths
1055
- @migrations_paths ||= ['db/migrate']
1056
- # just to not break things if someone uses: migrations_path = some_string
1057
- Array(@migrations_paths)
1058
- 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
1059
1113
 
1060
- def parse_migration_filename(filename) # :nodoc:
1061
- File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1114
+ MigrationProxy.new(name, version, file, scope)
1062
1115
  end
1063
1116
 
1064
- def migrations(paths)
1065
- paths = Array(paths)
1117
+ migrations.sort_by(&:version)
1118
+ end
1066
1119
 
1067
- migrations = migration_files(paths).map do |file|
1068
- version, name, scope = parse_migration_filename(file)
1069
- raise IllegalMigrationNameError.new(file) unless version
1070
- version = version.to_i
1071
- name = name.camelize
1120
+ def migrations_status
1121
+ db_list = schema_migration.normalized_versions
1072
1122
 
1073
- MigrationProxy.new(name, version, file, scope)
1074
- 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
1075
1130
 
1076
- migrations.sort_by(&:version)
1131
+ db_list.map! do |version|
1132
+ ["up", version, "********** NO FILE **********"]
1077
1133
  end
1078
1134
 
1079
- def migrations_status(paths)
1080
- paths = Array(paths)
1135
+ (db_list + file_list).sort_by { |_, version, _| version }
1136
+ end
1081
1137
 
1082
- db_list = ActiveRecord::SchemaMigration.normalized_versions
1138
+ def current_environment
1139
+ ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
1140
+ end
1083
1141
 
1084
- file_list = migration_files(paths).map do |file|
1085
- version, name, scope = parse_migration_filename(file)
1086
- raise IllegalMigrationNameError.new(file) unless version
1087
- version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
1088
- status = db_list.delete(version) ? "up" : "down"
1089
- [status, version, (name + scope).humanize]
1090
- end.compact
1142
+ def protected_environment?
1143
+ ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
1144
+ end
1091
1145
 
1092
- db_list.map! do |version|
1093
- ["up", version, "********** NO FILE **********"]
1094
- end
1146
+ def last_stored_environment
1147
+ return nil if current_version == 0
1148
+ raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1095
1149
 
1096
- (db_list + file_list).sort_by { |_, version, _| version }
1097
- end
1150
+ environment = ActiveRecord::InternalMetadata[:environment]
1151
+ raise NoEnvironmentInSchemaError unless environment
1152
+ environment
1153
+ end
1098
1154
 
1099
- def migration_files(paths)
1155
+ private
1156
+ def migration_files
1157
+ paths = Array(migrations_paths)
1100
1158
  Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
1101
1159
  end
1102
1160
 
1103
- private
1161
+ def parse_migration_filename(filename)
1162
+ File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1163
+ end
1104
1164
 
1105
- def move(direction, migrations_paths, steps)
1106
- migrator = new(direction, migrations(migrations_paths))
1107
- start_index = migrator.migrations.index(migrator.current_migration)
1165
+ def move(direction, steps)
1166
+ migrator = Migrator.new(direction, migrations, schema_migration)
1108
1167
 
1109
- if start_index
1110
- finish = migrator.migrations[start_index + steps]
1111
- version = finish ? finish.version : 0
1112
- send(direction, migrations_paths, version)
1168
+ if current_version != 0 && !migrator.current_migration
1169
+ raise UnknownMigrationVersionError.new(current_version)
1113
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
1114
1192
  end
1115
1193
  end
1116
1194
 
1117
- def initialize(direction, migrations, target_version = nil)
1118
- raise StandardError.new("This database does not yet support migrations") unless Base.connection.supports_migrations?
1195
+ self.migrations_paths = ["db/migrate"]
1119
1196
 
1197
+ def initialize(direction, migrations, schema_migration, target_version = nil)
1120
1198
  @direction = direction
1121
1199
  @target_version = target_version
1122
1200
  @migrated_versions = nil
1123
1201
  @migrations = migrations
1202
+ @schema_migration = schema_migration
1124
1203
 
1125
1204
  validate(@migrations)
1126
1205
 
1127
- Base.connection.initialize_schema_migrations_table
1128
- Base.connection.initialize_internal_metadata_table
1206
+ @schema_migration.create_table
1207
+ ActiveRecord::InternalMetadata.create_table
1129
1208
  end
1130
1209
 
1131
1210
  def current_version
@@ -1178,153 +1257,141 @@ module ActiveRecord
1178
1257
  end
1179
1258
 
1180
1259
  def load_migrated
1181
- @migrated_versions = Set.new(self.class.get_all_versions)
1260
+ @migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
1182
1261
  end
1183
1262
 
1184
1263
  private
1185
1264
 
1186
- # Used for running a specific migration.
1187
- def run_without_lock
1188
- migration = migrations.detect { |m| m.version == @target_version }
1189
- raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
1190
- result = execute_migration_in_transaction(migration, @direction)
1191
-
1192
- record_environment
1193
- result
1194
- end
1195
-
1196
- # Used for running multiple migrations up to or down to a certain value.
1197
- def migrate_without_lock
1198
- if invalid_target?
1199
- raise UnknownMigrationVersionError.new(@target_version)
1200
- end
1265
+ # Used for running a specific migration.
1266
+ def run_without_lock
1267
+ migration = migrations.detect { |m| m.version == @target_version }
1268
+ raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
1269
+ result = execute_migration_in_transaction(migration, @direction)
1201
1270
 
1202
- result = runnable.each do |migration|
1203
- execute_migration_in_transaction(migration, @direction)
1271
+ record_environment
1272
+ result
1204
1273
  end
1205
1274
 
1206
- record_environment
1207
- result
1208
- end
1209
-
1210
- # Stores the current environment in the database.
1211
- def record_environment
1212
- return if down?
1213
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
1214
- end
1215
-
1216
- def ran?(migration)
1217
- migrated.include?(migration.version.to_i)
1218
- end
1275
+ # Used for running multiple migrations up to or down to a certain value.
1276
+ def migrate_without_lock
1277
+ if invalid_target?
1278
+ raise UnknownMigrationVersionError.new(@target_version)
1279
+ end
1219
1280
 
1220
- # Return true if a valid version is not provided.
1221
- def invalid_target?
1222
- !target && @target_version && @target_version > 0
1223
- end
1281
+ result = runnable.each do |migration|
1282
+ execute_migration_in_transaction(migration, @direction)
1283
+ end
1224
1284
 
1225
- def execute_migration_in_transaction(migration, direction)
1226
- return if down? && !migrated.include?(migration.version.to_i)
1227
- return if up? && migrated.include?(migration.version.to_i)
1285
+ record_environment
1286
+ result
1287
+ end
1228
1288
 
1229
- Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
1289
+ # Stores the current environment in the database.
1290
+ def record_environment
1291
+ return if down?
1292
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
1293
+ end
1230
1294
 
1231
- ddl_transaction(migration) do
1232
- migration.migrate(direction)
1233
- record_version_state_after_migrating(migration.version)
1295
+ def ran?(migration)
1296
+ migrated.include?(migration.version.to_i)
1234
1297
  end
1235
- rescue => e
1236
- msg = "An error has occurred, "
1237
- msg << "this and " if use_transaction?(migration)
1238
- msg << "all later migrations canceled:\n\n#{e}"
1239
- raise StandardError, msg, e.backtrace
1240
- end
1241
1298
 
1242
- def target
1243
- migrations.detect { |m| m.version == @target_version }
1244
- end
1299
+ # Return true if a valid version is not provided.
1300
+ def invalid_target?
1301
+ @target_version && @target_version != 0 && !target
1302
+ end
1245
1303
 
1246
- def finish
1247
- migrations.index(target) || migrations.size - 1
1248
- end
1304
+ def execute_migration_in_transaction(migration, direction)
1305
+ return if down? && !migrated.include?(migration.version.to_i)
1306
+ return if up? && migrated.include?(migration.version.to_i)
1249
1307
 
1250
- def start
1251
- up? ? 0 : (migrations.index(current) || 0)
1252
- end
1308
+ Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
1253
1309
 
1254
- def validate(migrations)
1255
- name ,= migrations.group_by(&:name).find { |_,v| v.length > 1 }
1256
- raise DuplicateMigrationNameError.new(name) if name
1310
+ ddl_transaction(migration) do
1311
+ migration.migrate(direction)
1312
+ record_version_state_after_migrating(migration.version)
1313
+ end
1314
+ rescue => e
1315
+ msg = +"An error has occurred, "
1316
+ msg << "this and " if use_transaction?(migration)
1317
+ msg << "all later migrations canceled:\n\n#{e}"
1318
+ raise StandardError, msg, e.backtrace
1319
+ end
1257
1320
 
1258
- version ,= migrations.group_by(&:version).find { |_,v| v.length > 1 }
1259
- raise DuplicateMigrationVersionError.new(version) if version
1260
- end
1321
+ def target
1322
+ migrations.detect { |m| m.version == @target_version }
1323
+ end
1261
1324
 
1262
- def record_version_state_after_migrating(version)
1263
- if down?
1264
- migrated.delete(version)
1265
- ActiveRecord::SchemaMigration.where(:version => version.to_s).delete_all
1266
- else
1267
- migrated << version
1268
- ActiveRecord::SchemaMigration.create!(version: version.to_s)
1325
+ def finish
1326
+ migrations.index(target) || migrations.size - 1
1269
1327
  end
1270
- end
1271
1328
 
1272
- def self.last_stored_environment
1273
- return nil if current_version == 0
1274
- raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1329
+ def start
1330
+ up? ? 0 : (migrations.index(current) || 0)
1331
+ end
1275
1332
 
1276
- environment = ActiveRecord::InternalMetadata[:environment]
1277
- raise NoEnvironmentInSchemaError unless environment
1278
- environment
1279
- end
1333
+ def validate(migrations)
1334
+ name, = migrations.group_by(&:name).find { |_, v| v.length > 1 }
1335
+ raise DuplicateMigrationNameError.new(name) if name
1280
1336
 
1281
- def self.current_environment
1282
- ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
1283
- end
1337
+ version, = migrations.group_by(&:version).find { |_, v| v.length > 1 }
1338
+ raise DuplicateMigrationVersionError.new(version) if version
1339
+ end
1284
1340
 
1285
- def self.protected_environment?
1286
- ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
1287
- end
1341
+ def record_version_state_after_migrating(version)
1342
+ if down?
1343
+ migrated.delete(version)
1344
+ @schema_migration.delete_by(version: version.to_s)
1345
+ else
1346
+ migrated << version
1347
+ @schema_migration.create!(version: version.to_s)
1348
+ end
1349
+ end
1288
1350
 
1289
- def up?
1290
- @direction == :up
1291
- end
1351
+ def up?
1352
+ @direction == :up
1353
+ end
1292
1354
 
1293
- def down?
1294
- @direction == :down
1295
- end
1355
+ def down?
1356
+ @direction == :down
1357
+ end
1296
1358
 
1297
- # Wrap the migration in a transaction only if supported by the adapter.
1298
- def ddl_transaction(migration)
1299
- if use_transaction?(migration)
1300
- Base.transaction { yield }
1301
- else
1302
- yield
1359
+ # Wrap the migration in a transaction only if supported by the adapter.
1360
+ def ddl_transaction(migration)
1361
+ if use_transaction?(migration)
1362
+ Base.transaction { yield }
1363
+ else
1364
+ yield
1365
+ end
1303
1366
  end
1304
- end
1305
1367
 
1306
- def use_transaction?(migration)
1307
- !migration.disable_ddl_transaction && Base.connection.supports_ddl_transactions?
1308
- end
1368
+ def use_transaction?(migration)
1369
+ !migration.disable_ddl_transaction && Base.connection.supports_ddl_transactions?
1370
+ end
1309
1371
 
1310
- def use_advisory_lock?
1311
- Base.connection.supports_advisory_locks?
1312
- end
1372
+ def use_advisory_lock?
1373
+ Base.connection.advisory_locks_enabled?
1374
+ end
1313
1375
 
1314
- def with_advisory_lock
1315
- lock_id = generate_migrator_advisory_lock_id
1316
- got_lock = Base.connection.get_advisory_lock(lock_id)
1317
- raise ConcurrentMigrationError unless got_lock
1318
- load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1319
- yield
1320
- ensure
1321
- Base.connection.release_advisory_lock(lock_id) if got_lock
1322
- end
1376
+ def with_advisory_lock
1377
+ lock_id = generate_migrator_advisory_lock_id
1378
+ connection = Base.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
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
1389
+ end
1323
1390
 
1324
- MIGRATOR_SALT = 2053462845
1325
- def generate_migrator_advisory_lock_id
1326
- db_name_hash = Zlib.crc32(Base.connection.current_database)
1327
- MIGRATOR_SALT * db_name_hash
1328
- end
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
1329
1396
  end
1330
1397
  end