activerecord 4.2.0 → 6.1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1221 -796
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +267 -249
  8. data/lib/active_record/association_relation.rb +45 -7
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +172 -67
  11. data/lib/active_record/associations/association_scope.rb +105 -129
  12. data/lib/active_record/associations/belongs_to_association.rb +85 -59
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -33
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +168 -279
  22. data/lib/active_record/associations/collection_proxy.rb +263 -155
  23. data/lib/active_record/associations/foreign_association.rb +33 -0
  24. data/lib/active_record/associations/has_many_association.rb +57 -84
  25. data/lib/active_record/associations/has_many_through_association.rb +70 -82
  26. data/lib/active_record/associations/has_one_association.rb +74 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +175 -164
  32. data/lib/active_record/associations/preloader/association.rb +107 -112
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +99 -96
  35. data/lib/active_record/associations/singular_association.rb +18 -45
  36. data/lib/active_record/associations/through_association.rb +49 -24
  37. data/lib/active_record/associations.rb +1845 -1597
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -138
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -36
  46. data/lib/active_record/attribute_methods/write.rb +25 -56
  47. data/lib/active_record/attribute_methods.rb +153 -162
  48. data/lib/active_record/attributes.rb +234 -70
  49. data/lib/active_record/autosave_association.rb +157 -69
  50. data/lib/active_record/base.rb +49 -50
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +46 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +271 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +78 -161
  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 +8 -6
  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/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +499 -293
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +595 -382
  119. data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -389
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +488 -243
  133. data/lib/active_record/counter_cache.rb +71 -50
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +273 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +212 -94
  143. data/lib/active_record/errors.rb +225 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +11 -6
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +273 -496
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +64 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +52 -0
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +103 -95
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +298 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +685 -309
  170. data/lib/active_record/model_schema.rb +420 -113
  171. data/lib/active_record/nested_attributes.rb +265 -216
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +574 -135
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +175 -54
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +533 -216
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +485 -310
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +326 -244
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +318 -256
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +99 -84
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +139 -96
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -409
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +23 -21
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -342
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -26
  209. data/lib/active_record/scoping/default.rb +96 -82
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +133 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +366 -129
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +291 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +181 -152
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -41
  231. data/lib/active_record/type/date_time.rb +4 -38
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +33 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +65 -48
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +44 -28
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -10
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +175 -65
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  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 -23
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  347. data/lib/active_record/attribute.rb +0 -149
  348. data/lib/active_record/attribute_decorators.rb +0 -66
  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/connection_specification.rb +0 -275
  352. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  353. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  354. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  355. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  356. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  357. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  358. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  359. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  360. data/lib/active_record/type/big_integer.rb +0 -13
  361. data/lib/active_record/type/binary.rb +0 -50
  362. data/lib/active_record/type/boolean.rb +0 -30
  363. data/lib/active_record/type/decimal.rb +0 -40
  364. data/lib/active_record/type/decorator.rb +0 -14
  365. data/lib/active_record/type/float.rb +0 -19
  366. data/lib/active_record/type/integer.rb +0 -55
  367. data/lib/active_record/type/mutable.rb +0 -16
  368. data/lib/active_record/type/numeric.rb +0 -36
  369. data/lib/active_record/type/string.rb +0 -36
  370. data/lib/active_record/type/time_value.rb +0 -38
  371. data/lib/active_record/type/value.rb +0 -101
  372. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  373. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  374. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,14 +1,15 @@
1
- require 'active_support/core_ext/string/filters'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/database_configurations"
2
4
 
3
5
  module ActiveRecord
4
6
  module Tasks # :nodoc:
5
- class DatabaseAlreadyExists < StandardError; end # :nodoc:
6
7
  class DatabaseNotSupported < StandardError; end # :nodoc:
7
8
 
8
- # <tt>ActiveRecord::Tasks::DatabaseTasks</tt> is a utility class, which encapsulates
9
+ # ActiveRecord::Tasks::DatabaseTasks is a utility class, which encapsulates
9
10
  # logic behind common tasks used to manage database and migrations.
10
11
  #
11
- # The tasks defined here are used with Rake tasks provided by Active Record.
12
+ # The tasks defined here are used with Rails commands provided by Active Record.
12
13
  #
13
14
  # In order to use DatabaseTasks, a few config values need to be set. All the needed
14
15
  # config values are set by Rails already, so it's necessary to do it only if you
@@ -18,15 +19,15 @@ module ActiveRecord
18
19
  #
19
20
  # The possible config values are:
20
21
  #
21
- # * +env+: current environment (like Rails.env).
22
- # * +database_configuration+: configuration of your databases (as in +config/database.yml+).
23
- # * +db_dir+: your +db+ directory.
24
- # * +fixtures_path+: a path to fixtures directory.
25
- # * +migrations_paths+: a list of paths to directories with migrations.
26
- # * +seed_loader+: an object which will load seeds, it needs to respond to the +load_seed+ method.
27
- # * +root+: a path to the root of the application.
22
+ # * +env+: current environment (like Rails.env).
23
+ # * +database_configuration+: configuration of your databases (as in +config/database.yml+).
24
+ # * +db_dir+: your +db+ directory.
25
+ # * +fixtures_path+: a path to fixtures directory.
26
+ # * +migrations_paths+: a list of paths to directories with migrations.
27
+ # * +seed_loader+: an object which will load seeds, it needs to respond to the +load_seed+ method.
28
+ # * +root+: a path to the root of the application.
28
29
  #
29
- # Example usage of +DatabaseTasks+ outside Rails could look as such:
30
+ # Example usage of DatabaseTasks outside Rails could look as such:
30
31
  #
31
32
  # include ActiveRecord::Tasks
32
33
  # DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
@@ -35,36 +36,63 @@ module ActiveRecord
35
36
  #
36
37
  # DatabaseTasks.create_current('production')
37
38
  module DatabaseTasks
39
+ ##
40
+ # :singleton-method:
41
+ # Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:schema:dump
42
+ mattr_accessor :structure_dump_flags, instance_accessor: false
43
+
44
+ ##
45
+ # :singleton-method:
46
+ # Extra flags passed to database CLI tool when calling db:schema:load
47
+ mattr_accessor :structure_load_flags, instance_accessor: false
48
+
38
49
  extend self
39
50
 
40
51
  attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
52
+ deprecate :current_config=
41
53
  attr_accessor :database_configuration
42
54
 
43
- LOCAL_HOSTS = ['127.0.0.1', 'localhost']
55
+ LOCAL_HOSTS = ["127.0.0.1", "localhost"]
56
+
57
+ def check_protected_environments!
58
+ unless ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]
59
+ current = ActiveRecord::Base.connection.migration_context.current_environment
60
+ stored = ActiveRecord::Base.connection.migration_context.last_stored_environment
61
+
62
+ if ActiveRecord::Base.connection.migration_context.protected_environment?
63
+ raise ActiveRecord::ProtectedEnvironmentError.new(stored)
64
+ end
65
+
66
+ if stored && stored != current
67
+ raise ActiveRecord::EnvironmentMismatchError.new(current: current, stored: stored)
68
+ end
69
+ end
70
+ rescue ActiveRecord::NoDatabaseError
71
+ end
44
72
 
45
73
  def register_task(pattern, task)
46
74
  @tasks ||= {}
47
75
  @tasks[pattern] = task
48
76
  end
49
77
 
50
- register_task(/mysql/, ActiveRecord::Tasks::MySQLDatabaseTasks)
51
- register_task(/postgresql/, ActiveRecord::Tasks::PostgreSQLDatabaseTasks)
52
- register_task(/sqlite/, ActiveRecord::Tasks::SQLiteDatabaseTasks)
78
+ register_task(/mysql/, "ActiveRecord::Tasks::MySQLDatabaseTasks")
79
+ register_task(/postgresql/, "ActiveRecord::Tasks::PostgreSQLDatabaseTasks")
80
+ register_task(/sqlite/, "ActiveRecord::Tasks::SQLiteDatabaseTasks")
53
81
 
54
82
  def db_dir
55
83
  @db_dir ||= Rails.application.config.paths["db"].first
56
84
  end
57
85
 
58
86
  def migrations_paths
59
- @migrations_paths ||= Rails.application.paths['db/migrate'].to_a
87
+ @migrations_paths ||= Rails.application.paths["db/migrate"].to_a
60
88
  end
61
89
 
62
90
  def fixtures_path
63
- @fixtures_path ||= if ENV['FIXTURES_PATH']
64
- File.join(root, ENV['FIXTURES_PATH'])
65
- else
66
- File.join(root, 'test', 'fixtures')
67
- end
91
+ @fixtures_path ||= if ENV["FIXTURES_PATH"]
92
+ File.join(root, ENV["FIXTURES_PATH"])
93
+ else
94
+ File.join(root, "test", "fixtures")
95
+ end
68
96
  end
69
97
 
70
98
  def root
@@ -75,172 +103,344 @@ module ActiveRecord
75
103
  @env ||= Rails.env
76
104
  end
77
105
 
106
+ def spec
107
+ @spec ||= "primary"
108
+ end
109
+ deprecate spec: "please use name instead"
110
+
111
+ def name
112
+ @name ||= "primary"
113
+ end
114
+
78
115
  def seed_loader
79
116
  @seed_loader ||= Rails.application
80
117
  end
81
118
 
82
119
  def current_config(options = {})
83
- options.reverse_merge! :env => env
84
120
  if options.has_key?(:config)
85
121
  @current_config = options[:config]
86
122
  else
87
- @current_config ||= ActiveRecord::Base.configurations[options[:env]]
123
+ env_name = options[:env] || env
124
+ name = options[:spec] || "primary"
125
+
126
+ @current_config ||= ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: name)&.configuration_hash
88
127
  end
89
128
  end
129
+ deprecate :current_config
90
130
 
91
- def create(*arguments)
92
- configuration = arguments.first
93
- class_for_adapter(configuration['adapter']).new(*arguments).create
131
+ def create(configuration, *arguments)
132
+ db_config = resolve_configuration(configuration)
133
+ database_adapter_for(db_config, *arguments).create
134
+ $stdout.puts "Created database '#{db_config.database}'" if verbose?
94
135
  rescue DatabaseAlreadyExists
95
- $stderr.puts "#{configuration['database']} already exists"
136
+ $stderr.puts "Database '#{db_config.database}' already exists" if verbose?
96
137
  rescue Exception => error
97
- $stderr.puts error, *(error.backtrace)
98
- $stderr.puts "Couldn't create database for #{configuration.inspect}"
138
+ $stderr.puts error
139
+ $stderr.puts "Couldn't create '#{db_config.database}' database. Please check your configuration."
140
+ raise
99
141
  end
100
142
 
101
143
  def create_all
102
- each_local_configuration { |configuration| create configuration }
144
+ old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
145
+ each_local_configuration { |db_config| create(db_config) }
146
+ if old_pool
147
+ ActiveRecord::Base.connection_handler.establish_connection(old_pool.db_config)
148
+ end
103
149
  end
104
150
 
105
- def create_current(environment = env)
106
- each_current_configuration(environment) { |configuration|
107
- create configuration
108
- }
151
+ def setup_initial_database_yaml
152
+ return {} unless defined?(Rails)
153
+
154
+ begin
155
+ Rails.application.config.load_database_yaml
156
+ rescue
157
+ unless ActiveRecord::Base.suppress_multiple_database_warning
158
+ $stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB."
159
+ end
160
+
161
+ {}
162
+ end
163
+ end
164
+
165
+ def for_each(databases)
166
+ return {} unless defined?(Rails)
167
+
168
+ database_configs = ActiveRecord::DatabaseConfigurations.new(databases).configs_for(env_name: Rails.env)
169
+
170
+ # if this is a single database application we don't want tasks for each primary database
171
+ return if database_configs.count == 1
172
+
173
+ database_configs.each do |db_config|
174
+ yield db_config.name
175
+ end
176
+ end
177
+
178
+ def raise_for_multi_db(environment = env, command:)
179
+ db_configs = ActiveRecord::Base.configurations.configs_for(env_name: environment)
180
+
181
+ if db_configs.count > 1
182
+ dbs_list = []
183
+
184
+ db_configs.each do |db|
185
+ dbs_list << "#{command}:#{db.name}"
186
+ end
187
+
188
+ raise "You're using a multiple database application. To use `#{command}` you must run the namespaced task with a VERSION. Available tasks are #{dbs_list.to_sentence}."
189
+ end
190
+ end
191
+
192
+ def create_current(environment = env, name = nil)
193
+ each_current_configuration(environment, name) { |db_config| create(db_config) }
109
194
  ActiveRecord::Base.establish_connection(environment.to_sym)
110
195
  end
111
196
 
112
- def drop(*arguments)
113
- configuration = arguments.first
114
- class_for_adapter(configuration['adapter']).new(*arguments).drop
197
+ def drop(configuration, *arguments)
198
+ db_config = resolve_configuration(configuration)
199
+ database_adapter_for(db_config, *arguments).drop
200
+ $stdout.puts "Dropped database '#{db_config.database}'" if verbose?
115
201
  rescue ActiveRecord::NoDatabaseError
116
- $stderr.puts "Database '#{configuration['database']}' does not exist"
202
+ $stderr.puts "Database '#{db_config.database}' does not exist"
117
203
  rescue Exception => error
118
- $stderr.puts error, *(error.backtrace)
119
- $stderr.puts "Couldn't drop #{configuration['database']}"
204
+ $stderr.puts error
205
+ $stderr.puts "Couldn't drop database '#{db_config.database}'"
206
+ raise
120
207
  end
121
208
 
122
209
  def drop_all
123
- each_local_configuration { |configuration| drop configuration }
210
+ each_local_configuration { |db_config| drop(db_config) }
124
211
  end
125
212
 
126
213
  def drop_current(environment = env)
127
- each_current_configuration(environment) { |configuration|
128
- drop configuration
129
- }
214
+ each_current_configuration(environment) { |db_config| drop(db_config) }
215
+ end
216
+
217
+ def truncate_tables(db_config)
218
+ ActiveRecord::Base.establish_connection(db_config)
219
+
220
+ connection = ActiveRecord::Base.connection
221
+ connection.truncate_tables(*connection.tables)
222
+ end
223
+ private :truncate_tables
224
+
225
+ def truncate_all(environment = env)
226
+ ActiveRecord::Base.configurations.configs_for(env_name: environment).each do |db_config|
227
+ truncate_tables(db_config)
228
+ end
130
229
  end
131
230
 
132
231
  def migrate
133
- verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
134
- version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
135
- scope = ENV['SCOPE']
136
- verbose_was, Migration.verbose = Migration.verbose, verbose
137
- Migrator.migrate(Migrator.migrations_paths, version) do |migration|
232
+ check_target_version
233
+
234
+ scope = ENV["SCOPE"]
235
+ verbose_was, Migration.verbose = Migration.verbose, verbose?
236
+
237
+ Base.connection.migration_context.migrate(target_version) do |migration|
138
238
  scope.blank? || scope == migration.scope
139
239
  end
240
+
241
+ ActiveRecord::Base.clear_cache!
140
242
  ensure
141
243
  Migration.verbose = verbose_was
142
244
  end
143
245
 
144
- def charset_current(environment = env)
145
- charset ActiveRecord::Base.configurations[environment]
246
+ def migrate_status
247
+ unless ActiveRecord::Base.connection.schema_migration.table_exists?
248
+ Kernel.abort "Schema migrations table does not exist yet."
249
+ end
250
+
251
+ # output
252
+ puts "\ndatabase: #{ActiveRecord::Base.connection_db_config.database}\n\n"
253
+ puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
254
+ puts "-" * 50
255
+ ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
256
+ puts "#{status.center(8)} #{version.ljust(14)} #{name}"
257
+ end
258
+ puts
259
+ end
260
+
261
+ def check_target_version
262
+ if target_version && !(Migration::MigrationFilenameRegexp.match?(ENV["VERSION"]) || /\A\d+\z/.match?(ENV["VERSION"]))
263
+ raise "Invalid format of target version: `VERSION=#{ENV['VERSION']}`"
264
+ end
265
+ end
266
+
267
+ def target_version
268
+ ENV["VERSION"].to_i if ENV["VERSION"] && !ENV["VERSION"].empty?
146
269
  end
147
270
 
148
- def charset(*arguments)
149
- configuration = arguments.first
150
- class_for_adapter(configuration['adapter']).new(*arguments).charset
271
+ def charset_current(env_name = env, db_name = name)
272
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: db_name)
273
+ charset(db_config)
151
274
  end
152
275
 
153
- def collation_current(environment = env)
154
- collation ActiveRecord::Base.configurations[environment]
276
+ def charset(configuration, *arguments)
277
+ db_config = resolve_configuration(configuration)
278
+ database_adapter_for(db_config, *arguments).charset
155
279
  end
156
280
 
157
- def collation(*arguments)
158
- configuration = arguments.first
159
- class_for_adapter(configuration['adapter']).new(*arguments).collation
281
+ def collation_current(env_name = env, db_name = name)
282
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: db_name)
283
+ collation(db_config)
284
+ end
285
+
286
+ def collation(configuration, *arguments)
287
+ db_config = resolve_configuration(configuration)
288
+ database_adapter_for(db_config, *arguments).collation
160
289
  end
161
290
 
162
291
  def purge(configuration)
163
- class_for_adapter(configuration['adapter']).new(configuration).purge
292
+ db_config = resolve_configuration(configuration)
293
+ database_adapter_for(db_config).purge
164
294
  end
165
295
 
166
296
  def purge_all
167
- each_local_configuration { |configuration|
168
- purge configuration
169
- }
297
+ each_local_configuration { |db_config| purge(db_config) }
170
298
  end
171
299
 
172
300
  def purge_current(environment = env)
173
- each_current_configuration(environment) { |configuration|
174
- purge configuration
175
- }
301
+ each_current_configuration(environment) { |db_config| purge(db_config) }
176
302
  ActiveRecord::Base.establish_connection(environment.to_sym)
177
303
  end
178
304
 
179
- def structure_dump(*arguments)
180
- configuration = arguments.first
181
- filename = arguments.delete_at 1
182
- class_for_adapter(configuration['adapter']).new(*arguments).structure_dump(filename)
305
+ def structure_dump(configuration, *arguments)
306
+ db_config = resolve_configuration(configuration)
307
+ filename = arguments.delete_at(0)
308
+ database_adapter_for(db_config, *arguments).structure_dump(filename, structure_dump_flags)
309
+ end
310
+
311
+ def structure_load(configuration, *arguments)
312
+ db_config = resolve_configuration(configuration)
313
+ filename = arguments.delete_at(0)
314
+ database_adapter_for(db_config, *arguments).structure_load(filename, structure_load_flags)
183
315
  end
184
316
 
185
- def structure_load(*arguments)
186
- configuration = arguments.first
187
- filename = arguments.delete_at 1
188
- class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename)
317
+ def load_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
318
+ file ||= dump_filename(db_config.name, format)
319
+
320
+ verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
321
+ check_schema_file(file)
322
+ ActiveRecord::Base.establish_connection(db_config)
323
+
324
+ case format
325
+ when :ruby
326
+ load(file)
327
+ when :sql
328
+ structure_load(db_config, file)
329
+ else
330
+ raise ArgumentError, "unknown format #{format.inspect}"
331
+ end
332
+ ActiveRecord::InternalMetadata.create_table
333
+ ActiveRecord::InternalMetadata[:environment] = db_config.env_name
334
+ ActiveRecord::InternalMetadata[:schema_sha1] = schema_sha1(file)
335
+ ensure
336
+ Migration.verbose = verbose_was
337
+ end
338
+
339
+ def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = nil, name = nil)
340
+ db_config = resolve_configuration(configuration)
341
+
342
+ if environment || name
343
+ ActiveSupport::Deprecation.warn("`environment` and `name` will be removed as parameters in 7.0.0, you may now pass an ActiveRecord::DatabaseConfigurations::DatabaseConfig as `configuration` instead.")
344
+ end
345
+
346
+ name ||= db_config.name
347
+
348
+ file ||= dump_filename(name, format)
349
+
350
+ return true unless File.exist?(file)
351
+
352
+ ActiveRecord::Base.establish_connection(db_config)
353
+
354
+ return false unless ActiveRecord::InternalMetadata.enabled?
355
+ return false unless ActiveRecord::InternalMetadata.table_exists?
356
+
357
+ ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
189
358
  end
190
359
 
191
- def load_schema(format = ActiveRecord::Base.schema_format, file = nil)
192
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
193
- This method will act on a specific connection in the future.
194
- To act on the current connection, use `load_schema_current` instead.
195
- MSG
360
+ def reconstruct_from_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
361
+ file ||= dump_filename(db_config.name, format)
362
+
363
+ check_schema_file(file)
364
+
365
+ ActiveRecord::Base.establish_connection(db_config)
196
366
 
197
- load_schema_current(format, file)
367
+ if schema_up_to_date?(db_config, format, file)
368
+ truncate_tables(db_config)
369
+ else
370
+ purge(db_config)
371
+ load_schema(db_config, format, file)
372
+ end
373
+ rescue ActiveRecord::NoDatabaseError
374
+ create(db_config)
375
+ load_schema(db_config, format, file)
198
376
  end
199
377
 
200
- def schema_file(format = ActiveSupport::Base.schema_format)
378
+ def dump_schema(db_config, format = ActiveRecord::Base.schema_format) # :nodoc:
379
+ require "active_record/schema_dumper"
380
+ filename = dump_filename(db_config.name, format)
381
+ connection = ActiveRecord::Base.connection
382
+
383
+ FileUtils.mkdir_p(db_dir)
201
384
  case format
202
385
  when :ruby
203
- File.join(db_dir, "schema.rb")
386
+ File.open(filename, "w:utf-8") do |file|
387
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
388
+ end
204
389
  when :sql
205
- File.join(db_dir, "structure.sql")
390
+ structure_dump(db_config, filename)
391
+ if connection.schema_migration.table_exists?
392
+ File.open(filename, "a") do |f|
393
+ f.puts connection.dump_schema_information
394
+ f.print "\n"
395
+ end
396
+ end
206
397
  end
207
398
  end
208
399
 
209
- # This method is the successor of +load_schema+. We should rename it
210
- # after +load_schema+ went through a deprecation cycle. (Rails > 4.2)
211
- def load_schema_for(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
212
- file ||= schema_file(format)
400
+ def schema_file(format = ActiveRecord::Base.schema_format)
401
+ File.join(db_dir, schema_file_type(format))
402
+ end
213
403
 
404
+ def schema_file_type(format = ActiveRecord::Base.schema_format)
214
405
  case format
215
406
  when :ruby
216
- check_schema_file(file)
217
- ActiveRecord::Base.establish_connection(configuration)
218
- load(file)
407
+ "schema.rb"
219
408
  when :sql
220
- check_schema_file(file)
221
- structure_load(configuration, file)
409
+ "structure.sql"
410
+ end
411
+ end
412
+
413
+ def dump_filename(db_config_name, format = ActiveRecord::Base.schema_format)
414
+ filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
415
+ schema_file_type(format)
222
416
  else
223
- raise ArgumentError, "unknown format #{format.inspect}"
417
+ "#{db_config_name}_#{schema_file_type(format)}"
224
418
  end
419
+
420
+ ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
225
421
  end
226
422
 
227
- def load_schema_current_if_exists(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
228
- if File.exist?(file || schema_file(format))
229
- load_schema_current(format, file, environment)
423
+ def cache_dump_filename(db_config_name, schema_cache_path: nil)
424
+ filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
425
+ "schema_cache.yml"
426
+ else
427
+ "#{db_config_name}_schema_cache.yml"
230
428
  end
429
+
430
+ schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
231
431
  end
232
432
 
233
433
  def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
234
- each_current_configuration(environment) { |configuration|
235
- load_schema_for configuration, format, file
236
- }
434
+ each_current_configuration(environment) do |db_config|
435
+ load_schema(db_config, format, file)
436
+ end
237
437
  ActiveRecord::Base.establish_connection(environment.to_sym)
238
438
  end
239
439
 
240
440
  def check_schema_file(filename)
241
441
  unless File.exist?(filename)
242
- message = %{#{filename} doesn't exist yet. Run `rake db:migrate` to create it, then try again.}
243
- message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails)
442
+ message = +%{#{filename} doesn't exist yet. Run `bin/rails db:migrate` to create it, then try again.}
443
+ message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails.root)
244
444
  Kernel.abort message
245
445
  end
246
446
  end
@@ -249,48 +449,85 @@ module ActiveRecord
249
449
  if seed_loader
250
450
  seed_loader.load_seed
251
451
  else
252
- raise "You tried to load seed data, but no seed loader is specified. Please specify seed " +
253
- "loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" +
452
+ raise "You tried to load seed data, but no seed loader is specified. Please specify seed " \
453
+ "loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" \
254
454
  "Seed loader should respond to load_seed method"
255
455
  end
256
456
  end
257
457
 
458
+ # Dumps the schema cache in YAML format for the connection into the file
459
+ #
460
+ # ==== Examples:
461
+ # ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
462
+ def dump_schema_cache(conn, filename)
463
+ conn.schema_cache.dump_to(filename)
464
+ end
465
+
466
+ def clear_schema_cache(filename)
467
+ FileUtils.rm_f filename, verbose: false
468
+ end
469
+
258
470
  private
471
+ def resolve_configuration(configuration)
472
+ Base.configurations.resolve(configuration)
473
+ end
259
474
 
260
- def class_for_adapter(adapter)
261
- key = @tasks.keys.detect { |pattern| adapter[pattern] }
262
- unless key
263
- raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
475
+ def verbose?
476
+ ENV["VERBOSE"] ? ENV["VERBOSE"] != "false" : true
264
477
  end
265
- @tasks[key]
266
- end
267
478
 
268
- def each_current_configuration(environment)
269
- environments = [environment]
270
- # add test environment only if no RAILS_ENV was specified.
271
- environments << 'test' if environment == 'development' && ENV['RAILS_ENV'].nil?
479
+ # Create a new instance for the specified db configuration object
480
+ # For classes that have been converted to use db_config objects, pass a
481
+ # `DatabaseConfig`, otherwise pass a `Hash`
482
+ def database_adapter_for(db_config, *arguments)
483
+ klass = class_for_adapter(db_config.adapter)
484
+ converted = klass.respond_to?(:using_database_configurations?) && klass.using_database_configurations?
272
485
 
273
- configurations = ActiveRecord::Base.configurations.values_at(*environments)
274
- configurations.compact.each do |configuration|
275
- yield configuration unless configuration['database'].blank?
486
+ config = converted ? db_config : db_config.configuration_hash
487
+ klass.new(config, *arguments)
488
+ end
489
+
490
+ def class_for_adapter(adapter)
491
+ _key, task = @tasks.each_pair.detect { |pattern, _task| adapter[pattern] }
492
+ unless task
493
+ raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
494
+ end
495
+ task.is_a?(String) ? task.constantize : task
276
496
  end
277
- end
278
497
 
279
- def each_local_configuration
280
- ActiveRecord::Base.configurations.each_value do |configuration|
281
- next unless configuration['database']
498
+ def each_current_configuration(environment, name = nil)
499
+ environments = [environment]
500
+ environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
282
501
 
283
- if local_database?(configuration)
284
- yield configuration
285
- else
286
- $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
502
+ environments.each do |env|
503
+ ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
504
+ next if name && name != db_config.name
505
+
506
+ yield db_config
507
+ end
287
508
  end
288
509
  end
289
- end
290
510
 
291
- def local_database?(configuration)
292
- configuration['host'].blank? || LOCAL_HOSTS.include?(configuration['host'])
293
- end
511
+ def each_local_configuration
512
+ ActiveRecord::Base.configurations.configs_for.each do |db_config|
513
+ next unless db_config.database
514
+
515
+ if local_database?(db_config)
516
+ yield db_config
517
+ else
518
+ $stderr.puts "This task only modifies local databases. #{db_config.database} is on a remote host."
519
+ end
520
+ end
521
+ end
522
+
523
+ def local_database?(db_config)
524
+ host = db_config.host
525
+ host.blank? || LOCAL_HOSTS.include?(host)
526
+ end
527
+
528
+ def schema_sha1(file)
529
+ Digest::SHA1.hexdigest(File.read(file))
530
+ end
294
531
  end
295
532
  end
296
533
  end