activerecord 5.0.7.2 → 6.0.3.4

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 (359) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +708 -2040
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +9 -7
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record.rb +37 -22
  8. data/lib/active_record/advisory_lock_base.rb +18 -0
  9. data/lib/active_record/aggregations.rb +249 -247
  10. data/lib/active_record/association_relation.rb +18 -14
  11. data/lib/active_record/associations.rb +1603 -1592
  12. data/lib/active_record/associations/alias_tracker.rb +24 -34
  13. data/lib/active_record/associations/association.rb +114 -55
  14. data/lib/active_record/associations/association_scope.rb +94 -94
  15. data/lib/active_record/associations/belongs_to_association.rb +58 -42
  16. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  17. data/lib/active_record/associations/builder/association.rb +18 -25
  18. data/lib/active_record/associations/builder/belongs_to.rb +43 -54
  19. data/lib/active_record/associations/builder/collection_association.rb +7 -18
  20. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +41 -62
  21. data/lib/active_record/associations/builder/has_many.rb +4 -0
  22. data/lib/active_record/associations/builder/has_one.rb +37 -1
  23. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  24. data/lib/active_record/associations/collection_association.rb +86 -254
  25. data/lib/active_record/associations/collection_proxy.rb +158 -122
  26. data/lib/active_record/associations/foreign_association.rb +9 -0
  27. data/lib/active_record/associations/has_many_association.rb +23 -30
  28. data/lib/active_record/associations/has_many_through_association.rb +58 -44
  29. data/lib/active_record/associations/has_one_association.rb +59 -54
  30. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  31. data/lib/active_record/associations/join_dependency.rb +143 -176
  32. data/lib/active_record/associations/join_dependency/join_association.rb +38 -87
  33. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  34. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  35. data/lib/active_record/associations/preloader.rb +90 -103
  36. data/lib/active_record/associations/preloader/association.rb +86 -100
  37. data/lib/active_record/associations/preloader/through_association.rb +77 -76
  38. data/lib/active_record/associations/singular_association.rb +12 -45
  39. data/lib/active_record/associations/through_association.rb +26 -14
  40. data/lib/active_record/attribute_assignment.rb +54 -61
  41. data/lib/active_record/attribute_decorators.rb +38 -17
  42. data/lib/active_record/attribute_methods.rb +66 -106
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -8
  44. data/lib/active_record/attribute_methods/dirty.rb +179 -109
  45. data/lib/active_record/attribute_methods/primary_key.rb +85 -92
  46. data/lib/active_record/attribute_methods/query.rb +4 -3
  47. data/lib/active_record/attribute_methods/read.rb +20 -49
  48. data/lib/active_record/attribute_methods/serialization.rb +29 -7
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -66
  50. data/lib/active_record/attribute_methods/write.rb +34 -33
  51. data/lib/active_record/attributes.rb +38 -25
  52. data/lib/active_record/autosave_association.rb +54 -35
  53. data/lib/active_record/base.rb +27 -24
  54. data/lib/active_record/callbacks.rb +64 -35
  55. data/lib/active_record/coders/json.rb +2 -0
  56. data/lib/active_record/coders/yaml_column.rb +11 -12
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +552 -323
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +215 -94
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -35
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -28
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +228 -147
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +400 -213
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -79
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -202
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +396 -562
  70. data/lib/active_record/connection_adapters/column.rb +41 -13
  71. data/lib/active_record/connection_adapters/connection_specification.rb +172 -139
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
  73. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +137 -49
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  80. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  81. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
  82. data/lib/active_record/connection_adapters/mysql2_adapter.rb +48 -30
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +19 -31
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -54
  85. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
  87. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  99. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  101. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -31
  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 +58 -54
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +8 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  109. data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
  110. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +20 -26
  111. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  113. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +378 -308
  115. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
  116. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
  117. data/lib/active_record/connection_adapters/postgresql_adapter.rb +383 -275
  118. data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
  119. data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
  120. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  121. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  122. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
  123. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
  124. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  127. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +259 -266
  128. data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
  129. data/lib/active_record/connection_handling.rb +143 -40
  130. data/lib/active_record/core.rb +201 -163
  131. data/lib/active_record/counter_cache.rb +60 -28
  132. data/lib/active_record/database_configurations.rb +233 -0
  133. data/lib/active_record/database_configurations/database_config.rb +37 -0
  134. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  135. data/lib/active_record/database_configurations/url_config.rb +78 -0
  136. data/lib/active_record/define_callbacks.rb +22 -0
  137. data/lib/active_record/dynamic_matchers.rb +87 -87
  138. data/lib/active_record/enum.rb +60 -23
  139. data/lib/active_record/errors.rb +114 -18
  140. data/lib/active_record/explain.rb +4 -4
  141. data/lib/active_record/explain_registry.rb +3 -1
  142. data/lib/active_record/explain_subscriber.rb +9 -4
  143. data/lib/active_record/fixture_set/file.rb +13 -8
  144. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  145. data/lib/active_record/fixture_set/render_context.rb +17 -0
  146. data/lib/active_record/fixture_set/table_row.rb +152 -0
  147. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  148. data/lib/active_record/fixtures.rb +194 -504
  149. data/lib/active_record/gem_version.rb +5 -3
  150. data/lib/active_record/inheritance.rb +150 -99
  151. data/lib/active_record/insert_all.rb +179 -0
  152. data/lib/active_record/integration.rb +116 -25
  153. data/lib/active_record/internal_metadata.rb +16 -19
  154. data/lib/active_record/legacy_yaml_adapter.rb +4 -2
  155. data/lib/active_record/locking/optimistic.rb +77 -87
  156. data/lib/active_record/locking/pessimistic.rb +18 -6
  157. data/lib/active_record/log_subscriber.rb +48 -29
  158. data/lib/active_record/middleware/database_selector.rb +74 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +369 -302
  162. data/lib/active_record/migration/command_recorder.rb +134 -100
  163. data/lib/active_record/migration/compatibility.rb +174 -56
  164. data/lib/active_record/migration/join_table.rb +8 -7
  165. data/lib/active_record/model_schema.rb +131 -127
  166. data/lib/active_record/nested_attributes.rb +213 -202
  167. data/lib/active_record/no_touching.rb +12 -3
  168. data/lib/active_record/null_relation.rb +12 -34
  169. data/lib/active_record/persistence.rb +446 -77
  170. data/lib/active_record/query_cache.rb +13 -12
  171. data/lib/active_record/querying.rb +37 -24
  172. data/lib/active_record/railtie.rb +128 -36
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +2 -0
  175. data/lib/active_record/railties/controller_runtime.rb +34 -33
  176. data/lib/active_record/railties/databases.rake +312 -177
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +214 -252
  179. data/lib/active_record/relation.rb +440 -318
  180. data/lib/active_record/relation/batches.rb +98 -52
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
  182. data/lib/active_record/relation/calculations.rb +212 -173
  183. data/lib/active_record/relation/delegation.rb +72 -69
  184. data/lib/active_record/relation/finder_methods.rb +207 -247
  185. data/lib/active_record/relation/from_clause.rb +6 -8
  186. data/lib/active_record/relation/merger.rb +78 -62
  187. data/lib/active_record/relation/predicate_builder.rb +83 -105
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  195. data/lib/active_record/relation/query_attribute.rb +33 -2
  196. data/lib/active_record/relation/query_methods.rb +476 -334
  197. data/lib/active_record/relation/record_fetch_warning.rb +5 -3
  198. data/lib/active_record/relation/spawn_methods.rb +8 -8
  199. data/lib/active_record/relation/where_clause.rb +111 -96
  200. data/lib/active_record/relation/where_clause_factory.rb +6 -11
  201. data/lib/active_record/result.rb +69 -40
  202. data/lib/active_record/runtime_registry.rb +5 -3
  203. data/lib/active_record/sanitization.rb +83 -99
  204. data/lib/active_record/schema.rb +7 -14
  205. data/lib/active_record/schema_dumper.rb +71 -69
  206. data/lib/active_record/schema_migration.rb +16 -6
  207. data/lib/active_record/scoping.rb +20 -20
  208. data/lib/active_record/scoping/default.rb +92 -95
  209. data/lib/active_record/scoping/named.rb +47 -27
  210. data/lib/active_record/secure_token.rb +4 -2
  211. data/lib/active_record/serialization.rb +2 -0
  212. data/lib/active_record/statement_cache.rb +63 -28
  213. data/lib/active_record/store.rb +121 -41
  214. data/lib/active_record/suppressor.rb +6 -3
  215. data/lib/active_record/table_metadata.rb +39 -18
  216. data/lib/active_record/tasks/database_tasks.rb +271 -81
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +54 -91
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +77 -47
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +33 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +225 -0
  222. data/lib/active_record/timestamp.rb +70 -36
  223. data/lib/active_record/touch_later.rb +8 -6
  224. data/lib/active_record/transactions.rb +141 -157
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type.rb +23 -18
  227. data/lib/active_record/type/adapter_specific_registry.rb +44 -48
  228. data/lib/active_record/type/date.rb +2 -0
  229. data/lib/active_record/type/date_time.rb +2 -0
  230. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  231. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  232. data/lib/active_record/type/internal/timezone.rb +2 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +16 -9
  235. data/lib/active_record/type/text.rb +11 -0
  236. data/lib/active_record/type/time.rb +2 -1
  237. data/lib/active_record/type/type_map.rb +14 -17
  238. data/lib/active_record/type/unsigned_integer.rb +16 -0
  239. data/lib/active_record/type_caster.rb +4 -2
  240. data/lib/active_record/type_caster/connection.rb +17 -12
  241. data/lib/active_record/type_caster/map.rb +5 -4
  242. data/lib/active_record/validations.rb +7 -5
  243. data/lib/active_record/validations/absence.rb +2 -0
  244. data/lib/active_record/validations/associated.rb +4 -3
  245. data/lib/active_record/validations/length.rb +2 -0
  246. data/lib/active_record/validations/presence.rb +4 -2
  247. data/lib/active_record/validations/uniqueness.rb +29 -42
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/arel.rb +62 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +256 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +203 -0
  317. data/lib/arel/visitors/dot.rb +296 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +156 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +158 -0
  323. data/lib/arel/visitors/oracle12.rb +65 -0
  324. data/lib/arel/visitors/postgresql.rb +109 -0
  325. data/lib/arel/visitors/sqlite.rb +38 -0
  326. data/lib/arel/visitors/to_sql.rb +888 -0
  327. data/lib/arel/visitors/visitor.rb +45 -0
  328. data/lib/arel/visitors/where_sql.rb +22 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +7 -5
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  332. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  333. data/lib/rails/generators/active_record/migration.rb +17 -3
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
  335. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
  336. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
  337. data/lib/rails/generators/active_record/model/model_generator.rb +9 -30
  338. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  339. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  340. metadata +137 -52
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  344. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  345. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  348. data/lib/active_record/attribute.rb +0 -213
  349. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  350. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  351. data/lib/active_record/attribute_set.rb +0 -110
  352. data/lib/active_record/attribute_set/builder.rb +0 -132
  353. data/lib/active_record/collection_cache_key.rb +0 -50
  354. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  355. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  356. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  357. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  358. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  359. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,21 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class TableMetadata # :nodoc:
3
- delegate :foreign_type, :foreign_key, to: :association, prefix: true
4
- delegate :association_primary_key, to: :association
5
+ delegate :foreign_type, :foreign_key, :join_primary_key, :join_foreign_key, to: :association, prefix: true
5
6
 
6
- def initialize(klass, arel_table, association = nil)
7
+ def initialize(klass, arel_table, association = nil, types = klass)
7
8
  @klass = klass
9
+ @types = types
8
10
  @arel_table = arel_table
9
11
  @association = association
10
12
  end
11
13
 
12
14
  def resolve_column_aliases(hash)
13
- # This method is a hot spot, so for now, use Hash[] to dup the hash.
14
- # https://bugs.ruby-lang.org/issues/7166
15
- new_hash = Hash[hash]
16
- hash.each do |key, _|
17
- if (key.is_a?(Symbol)) && klass.attribute_alias?(key)
18
- new_hash[klass.attribute_alias(key)] = new_hash.delete(key)
15
+ new_hash = hash.dup
16
+ hash.each_key do |key|
17
+ if key.is_a?(Symbol) && new_key = klass.attribute_aliases[key.to_s]
18
+ new_hash[new_key] = new_hash.delete(key)
19
19
  end
20
20
  end
21
21
  new_hash
@@ -30,11 +30,11 @@ module ActiveRecord
30
30
  end
31
31
 
32
32
  def type(column_name)
33
- if klass
34
- klass.type_for_attribute(column_name.to_s)
35
- else
36
- Type::Value.new
37
- end
33
+ types.type_for_attribute(column_name)
34
+ end
35
+
36
+ def has_column?(column_name)
37
+ klass && klass.columns_hash.key?(column_name.to_s)
38
38
  end
39
39
 
40
40
  def associated_with?(association_name)
@@ -45,25 +45,46 @@ module ActiveRecord
45
45
  association = klass._reflect_on_association(table_name) || klass._reflect_on_association(table_name.to_s.singularize)
46
46
 
47
47
  if !association && table_name == arel_table.name
48
- return self
48
+ self
49
49
  elsif association && !association.polymorphic?
50
50
  association_klass = association.klass
51
51
  arel_table = association_klass.arel_table.alias(table_name)
52
+ TableMetadata.new(association_klass, arel_table, association)
52
53
  else
53
54
  type_caster = TypeCaster::Connection.new(klass, table_name)
54
- association_klass = nil
55
55
  arel_table = Arel::Table.new(table_name, type_caster: type_caster)
56
+ TableMetadata.new(nil, arel_table, association, type_caster)
56
57
  end
58
+ end
57
59
 
58
- TableMetadata.new(association_klass, arel_table, association)
60
+ def associated_predicate_builder(table_name)
61
+ associated_table(table_name).predicate_builder
59
62
  end
60
63
 
61
64
  def polymorphic_association?
62
65
  association && association.polymorphic?
63
66
  end
64
67
 
68
+ def aggregated_with?(aggregation_name)
69
+ klass && reflect_on_aggregation(aggregation_name)
70
+ end
71
+
72
+ def reflect_on_aggregation(aggregation_name)
73
+ klass.reflect_on_aggregation(aggregation_name)
74
+ end
75
+
65
76
  protected
77
+ def predicate_builder
78
+ if klass
79
+ predicate_builder = klass.predicate_builder.dup
80
+ predicate_builder.instance_variable_set(:@table, self)
81
+ predicate_builder
82
+ else
83
+ PredicateBuilder.new(self)
84
+ end
85
+ end
66
86
 
67
- attr_reader :klass, :arel_table, :association
87
+ private
88
+ attr_reader :klass, :types, :arel_table, :association
68
89
  end
69
90
  end
@@ -1,4 +1,6 @@
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:
@@ -8,7 +10,7 @@ module ActiveRecord
8
10
  # ActiveRecord::Tasks::DatabaseTasks is a utility class, which encapsulates
9
11
  # logic behind common tasks used to manage database and migrations.
10
12
  #
11
- # The tasks defined here are used with Rake tasks provided by Active Record.
13
+ # The tasks defined here are used with Rails commands provided by Active Record.
12
14
  #
13
15
  # In order to use DatabaseTasks, a few config values need to be set. All the needed
14
16
  # config values are set by Rails already, so it's necessary to do it only if you
@@ -35,19 +37,29 @@ module ActiveRecord
35
37
  #
36
38
  # DatabaseTasks.create_current('production')
37
39
  module DatabaseTasks
40
+ ##
41
+ # :singleton-method:
42
+ # Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:structure:dump
43
+ mattr_accessor :structure_dump_flags, instance_accessor: false
44
+
45
+ ##
46
+ # :singleton-method:
47
+ # Extra flags passed to database CLI tool when calling db:structure:load
48
+ mattr_accessor :structure_load_flags, instance_accessor: false
49
+
38
50
  extend self
39
51
 
40
52
  attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
41
53
  attr_accessor :database_configuration
42
54
 
43
- LOCAL_HOSTS = ['127.0.0.1', 'localhost']
55
+ LOCAL_HOSTS = ["127.0.0.1", "localhost"]
44
56
 
45
57
  def check_protected_environments!
46
- unless ENV['DISABLE_DATABASE_ENVIRONMENT_CHECK']
47
- current = ActiveRecord::Migrator.current_environment
48
- stored = ActiveRecord::Migrator.last_stored_environment
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
49
61
 
50
- if ActiveRecord::Migrator.protected_environment?
62
+ if ActiveRecord::Base.connection.migration_context.protected_environment?
51
63
  raise ActiveRecord::ProtectedEnvironmentError.new(stored)
52
64
  end
53
65
 
@@ -63,24 +75,24 @@ module ActiveRecord
63
75
  @tasks[pattern] = task
64
76
  end
65
77
 
66
- register_task(/mysql/, ActiveRecord::Tasks::MySQLDatabaseTasks)
67
- register_task(/postgresql/, ActiveRecord::Tasks::PostgreSQLDatabaseTasks)
68
- 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")
69
81
 
70
82
  def db_dir
71
83
  @db_dir ||= Rails.application.config.paths["db"].first
72
84
  end
73
85
 
74
86
  def migrations_paths
75
- @migrations_paths ||= Rails.application.paths['db/migrate'].to_a
87
+ @migrations_paths ||= Rails.application.paths["db/migrate"].to_a
76
88
  end
77
89
 
78
90
  def fixtures_path
79
- @fixtures_path ||= if ENV['FIXTURES_PATH']
80
- File.join(root, ENV['FIXTURES_PATH'])
81
- else
82
- File.join(root, 'test', 'fixtures')
83
- 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
84
96
  end
85
97
 
86
98
  def root
@@ -91,28 +103,33 @@ module ActiveRecord
91
103
  @env ||= Rails.env
92
104
  end
93
105
 
106
+ def spec
107
+ @spec ||= "primary"
108
+ end
109
+
94
110
  def seed_loader
95
111
  @seed_loader ||= Rails.application
96
112
  end
97
113
 
98
114
  def current_config(options = {})
99
- options.reverse_merge! :env => env
115
+ options.reverse_merge! env: env
116
+ options[:spec] ||= "primary"
100
117
  if options.has_key?(:config)
101
118
  @current_config = options[:config]
102
119
  else
103
- @current_config ||= ActiveRecord::Base.configurations[options[:env]]
120
+ @current_config ||= ActiveRecord::Base.configurations.configs_for(env_name: options[:env], spec_name: options[:spec]).config
104
121
  end
105
122
  end
106
123
 
107
124
  def create(*arguments)
108
125
  configuration = arguments.first
109
- class_for_adapter(configuration['adapter']).new(*arguments).create
110
- $stdout.puts "Created database '#{configuration['database']}'"
126
+ class_for_adapter(configuration["adapter"]).new(*arguments).create
127
+ $stdout.puts "Created database '#{configuration['database']}'" if verbose?
111
128
  rescue DatabaseAlreadyExists
112
- $stderr.puts "Database '#{configuration['database']}' already exists"
129
+ $stderr.puts "Database '#{configuration['database']}' already exists" if verbose?
113
130
  rescue Exception => error
114
131
  $stderr.puts error
115
- $stderr.puts "Couldn't create database for #{configuration.inspect}"
132
+ $stderr.puts "Couldn't create '#{configuration['database']}' database. Please check your configuration."
116
133
  raise
117
134
  end
118
135
 
@@ -120,12 +137,51 @@ module ActiveRecord
120
137
  old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
121
138
  each_local_configuration { |configuration| create configuration }
122
139
  if old_pool
123
- ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec)
140
+ ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec.to_hash)
124
141
  end
125
142
  end
126
143
 
127
- def create_current(environment = env)
128
- each_current_configuration(environment) { |configuration|
144
+ def setup_initial_database_yaml
145
+ return {} unless defined?(Rails)
146
+
147
+ begin
148
+ Rails.application.config.load_database_yaml
149
+ rescue
150
+ $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."
151
+
152
+ {}
153
+ end
154
+ end
155
+
156
+ def for_each(databases)
157
+ return {} unless defined?(Rails)
158
+
159
+ database_configs = ActiveRecord::DatabaseConfigurations.new(databases).configs_for(env_name: Rails.env)
160
+
161
+ # if this is a single database application we don't want tasks for each primary database
162
+ return if database_configs.count == 1
163
+
164
+ database_configs.each do |db_config|
165
+ yield db_config.spec_name
166
+ end
167
+ end
168
+
169
+ def raise_for_multi_db(environment = env, command:)
170
+ db_configs = ActiveRecord::Base.configurations.configs_for(env_name: environment)
171
+
172
+ if db_configs.count > 1
173
+ dbs_list = []
174
+
175
+ db_configs.each do |db|
176
+ dbs_list << "#{command}:#{db.spec_name}"
177
+ end
178
+
179
+ 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}."
180
+ end
181
+ end
182
+
183
+ def create_current(environment = env, spec_name = nil)
184
+ each_current_configuration(environment, spec_name) { |configuration|
129
185
  create configuration
130
186
  }
131
187
  ActiveRecord::Base.establish_connection(environment.to_sym)
@@ -133,8 +189,8 @@ module ActiveRecord
133
189
 
134
190
  def drop(*arguments)
135
191
  configuration = arguments.first
136
- class_for_adapter(configuration['adapter']).new(*arguments).drop
137
- $stdout.puts "Dropped database '#{configuration['database']}'"
192
+ class_for_adapter(configuration["adapter"]).new(*arguments).drop
193
+ $stdout.puts "Dropped database '#{configuration['database']}'" if verbose?
138
194
  rescue ActiveRecord::NoDatabaseError
139
195
  $stderr.puts "Database '#{configuration['database']}' does not exist"
140
196
  rescue Exception => error
@@ -153,41 +209,86 @@ module ActiveRecord
153
209
  }
154
210
  end
155
211
 
212
+ def truncate_tables(configuration)
213
+ ActiveRecord::Base.connected_to(database: { truncation: configuration }) do
214
+ conn = ActiveRecord::Base.connection
215
+ table_names = conn.tables
216
+ table_names -= [
217
+ conn.schema_migration.table_name,
218
+ InternalMetadata.table_name
219
+ ]
220
+
221
+ ActiveRecord::Base.connection.truncate_tables(*table_names)
222
+ end
223
+ end
224
+ private :truncate_tables
225
+
226
+ def truncate_all(environment = env)
227
+ ActiveRecord::Base.configurations.configs_for(env_name: environment).each do |db_config|
228
+ truncate_tables db_config.config
229
+ end
230
+ end
231
+
156
232
  def migrate
157
- raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
233
+ check_target_version
158
234
 
159
- verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
160
- version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
161
- scope = ENV['SCOPE']
162
- verbose_was, Migration.verbose = Migration.verbose, verbose
163
- Migrator.migrate(migrations_paths, version) do |migration|
235
+ scope = ENV["SCOPE"]
236
+ verbose_was, Migration.verbose = Migration.verbose, verbose?
237
+
238
+ Base.connection.migration_context.migrate(target_version) do |migration|
164
239
  scope.blank? || scope == migration.scope
165
240
  end
241
+
166
242
  ActiveRecord::Base.clear_cache!
167
243
  ensure
168
244
  Migration.verbose = verbose_was
169
245
  end
170
246
 
171
- def charset_current(environment = env)
172
- charset ActiveRecord::Base.configurations[environment]
247
+ def migrate_status
248
+ unless ActiveRecord::Base.connection.schema_migration.table_exists?
249
+ Kernel.abort "Schema migrations table does not exist yet."
250
+ end
251
+
252
+ # output
253
+ puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
254
+ puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
255
+ puts "-" * 50
256
+ ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
257
+ puts "#{status.center(8)} #{version.ljust(14)} #{name}"
258
+ end
259
+ puts
260
+ end
261
+
262
+ def check_target_version
263
+ if target_version && !(Migration::MigrationFilenameRegexp.match?(ENV["VERSION"]) || /\A\d+\z/.match?(ENV["VERSION"]))
264
+ raise "Invalid format of target version: `VERSION=#{ENV['VERSION']}`"
265
+ end
266
+ end
267
+
268
+ def target_version
269
+ ENV["VERSION"].to_i if ENV["VERSION"] && !ENV["VERSION"].empty?
270
+ end
271
+
272
+ def charset_current(environment = env, specification_name = spec)
273
+ charset ActiveRecord::Base.configurations.configs_for(env_name: environment, spec_name: specification_name).config
173
274
  end
174
275
 
175
276
  def charset(*arguments)
176
277
  configuration = arguments.first
177
- class_for_adapter(configuration['adapter']).new(*arguments).charset
278
+ class_for_adapter(configuration["adapter"]).new(*arguments).charset
178
279
  end
179
280
 
180
- def collation_current(environment = env)
181
- collation ActiveRecord::Base.configurations[environment]
281
+ def collation_current(environment = env, specification_name = spec)
282
+ collation ActiveRecord::Base.configurations.configs_for(env_name: environment, spec_name: specification_name).config
182
283
  end
183
284
 
184
285
  def collation(*arguments)
185
286
  configuration = arguments.first
186
- class_for_adapter(configuration['adapter']).new(*arguments).collation
287
+ class_for_adapter(configuration["adapter"]).new(*arguments).collation
187
288
  end
188
289
 
189
290
  def purge(configuration)
190
- class_for_adapter(configuration['adapter']).new(configuration).purge
291
+ class_for_adapter(configuration["adapter"]).new(configuration).purge
191
292
  end
192
293
 
193
294
  def purge_all
@@ -206,18 +307,19 @@ module ActiveRecord
206
307
  def structure_dump(*arguments)
207
308
  configuration = arguments.first
208
309
  filename = arguments.delete_at 1
209
- class_for_adapter(configuration['adapter']).new(*arguments).structure_dump(filename)
310
+ class_for_adapter(configuration["adapter"]).new(*arguments).structure_dump(filename, structure_dump_flags)
210
311
  end
211
312
 
212
313
  def structure_load(*arguments)
213
314
  configuration = arguments.first
214
315
  filename = arguments.delete_at 1
215
- class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename)
316
+ class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename, structure_load_flags)
216
317
  end
217
318
 
218
- def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env) # :nodoc:
219
- file ||= schema_file(format)
319
+ def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary") # :nodoc:
320
+ file ||= dump_filename(spec_name, format)
220
321
 
322
+ verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
221
323
  check_schema_file(file)
222
324
  ActiveRecord::Base.establish_connection(configuration)
223
325
 
@@ -231,35 +333,103 @@ module ActiveRecord
231
333
  end
232
334
  ActiveRecord::InternalMetadata.create_table
233
335
  ActiveRecord::InternalMetadata[:environment] = environment
336
+ ActiveRecord::InternalMetadata[:schema_sha1] = schema_sha1(file)
337
+ ensure
338
+ Migration.verbose = verbose_was
234
339
  end
235
340
 
236
- def load_schema_for(*args)
237
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
238
- This method was renamed to `#load_schema` and will be removed in the future.
239
- Use `#load_schema` instead.
240
- MSG
241
- load_schema(*args)
341
+ def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary")
342
+ file ||= dump_filename(spec_name, format)
343
+
344
+ return true unless File.exist?(file)
345
+
346
+ ActiveRecord::Base.establish_connection(configuration)
347
+ return false unless ActiveRecord::InternalMetadata.table_exists?
348
+ ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
349
+ end
350
+
351
+ def reconstruct_from_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary") # :nodoc:
352
+ file ||= dump_filename(spec_name, format)
353
+
354
+ check_schema_file(file)
355
+
356
+ ActiveRecord::Base.establish_connection(configuration)
357
+
358
+ if schema_up_to_date?(configuration, format, file, environment, spec_name)
359
+ truncate_tables(configuration)
360
+ else
361
+ purge(configuration)
362
+ load_schema(configuration, format, file, environment, spec_name)
363
+ end
364
+ rescue ActiveRecord::NoDatabaseError
365
+ create(configuration)
366
+ load_schema(configuration, format, file, environment, spec_name)
367
+ end
368
+
369
+ def dump_schema(configuration, format = ActiveRecord::Base.schema_format, spec_name = "primary") # :nodoc:
370
+ require "active_record/schema_dumper"
371
+ filename = dump_filename(spec_name, format)
372
+ connection = ActiveRecord::Base.connection
373
+
374
+ case format
375
+ when :ruby
376
+ File.open(filename, "w:utf-8") do |file|
377
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
378
+ end
379
+ when :sql
380
+ structure_dump(configuration, filename)
381
+ if connection.schema_migration.table_exists?
382
+ File.open(filename, "a") do |f|
383
+ f.puts connection.dump_schema_information
384
+ f.print "\n"
385
+ end
386
+ end
387
+ end
242
388
  end
243
389
 
244
390
  def schema_file(format = ActiveRecord::Base.schema_format)
391
+ File.join(db_dir, schema_file_type(format))
392
+ end
393
+
394
+ def schema_file_type(format = ActiveRecord::Base.schema_format)
245
395
  case format
246
396
  when :ruby
247
- File.join(db_dir, "schema.rb")
397
+ "schema.rb"
248
398
  when :sql
249
- File.join(db_dir, "structure.sql")
399
+ "structure.sql"
400
+ end
401
+ end
402
+
403
+ def dump_filename(namespace, format = ActiveRecord::Base.schema_format)
404
+ filename = if namespace == "primary"
405
+ schema_file_type(format)
406
+ else
407
+ "#{namespace}_#{schema_file_type(format)}"
408
+ end
409
+
410
+ ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
411
+ end
412
+
413
+ def cache_dump_filename(namespace)
414
+ filename = if namespace == "primary"
415
+ "schema_cache.yml"
416
+ else
417
+ "#{namespace}_schema_cache.yml"
250
418
  end
419
+
420
+ ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
251
421
  end
252
422
 
253
423
  def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
254
- each_current_configuration(environment) { |configuration, configuration_environment|
255
- load_schema configuration, format, file, configuration_environment
424
+ each_current_configuration(environment) { |configuration, spec_name, env|
425
+ load_schema(configuration, format, file, env, spec_name)
256
426
  }
257
427
  ActiveRecord::Base.establish_connection(environment.to_sym)
258
428
  end
259
429
 
260
430
  def check_schema_file(filename)
261
431
  unless File.exist?(filename)
262
- message = %{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}
432
+ message = +%{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}
263
433
  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)
264
434
  Kernel.abort message
265
435
  end
@@ -269,48 +439,68 @@ module ActiveRecord
269
439
  if seed_loader
270
440
  seed_loader.load_seed
271
441
  else
272
- raise "You tried to load seed data, but no seed loader is specified. Please specify seed " +
273
- "loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" +
442
+ raise "You tried to load seed data, but no seed loader is specified. Please specify seed " \
443
+ "loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" \
274
444
  "Seed loader should respond to load_seed method"
275
445
  end
276
446
  end
277
447
 
448
+ # Dumps the schema cache in YAML format for the connection into the file
449
+ #
450
+ # ==== Examples:
451
+ # ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
452
+ def dump_schema_cache(conn, filename)
453
+ conn.schema_cache.clear!
454
+ conn.data_sources.each { |table| conn.schema_cache.add(table) }
455
+ open(filename, "wb") { |f| f.write(YAML.dump(conn.schema_cache)) }
456
+ end
457
+
278
458
  private
459
+ def verbose?
460
+ ENV["VERBOSE"] ? ENV["VERBOSE"] != "false" : true
461
+ end
279
462
 
280
- def class_for_adapter(adapter)
281
- key = @tasks.keys.detect { |pattern| adapter[pattern] }
282
- unless key
283
- raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
463
+ def class_for_adapter(adapter)
464
+ _key, task = @tasks.each_pair.detect { |pattern, _task| adapter[pattern] }
465
+ unless task
466
+ raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
467
+ end
468
+ task.is_a?(String) ? task.constantize : task
284
469
  end
285
- @tasks[key]
286
- end
287
470
 
288
- def each_current_configuration(environment)
289
- environments = [environment]
290
- environments << 'test' if environment == 'development'
471
+ def each_current_configuration(environment, spec_name = nil)
472
+ environments = [environment]
473
+ environments << "test" if environment == "development"
291
474
 
292
- ActiveRecord::Base.configurations.slice(*environments).each do |configuration_environment, configuration|
293
- next unless configuration["database"]
475
+ environments.each do |env|
476
+ ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
477
+ next if spec_name && spec_name != db_config.spec_name
294
478
 
295
- yield configuration, configuration_environment
479
+ yield db_config.config, db_config.spec_name, env
480
+ end
481
+ end
296
482
  end
297
- end
298
483
 
299
- def each_local_configuration
300
- ActiveRecord::Base.configurations.each_value do |configuration|
301
- next unless configuration['database']
484
+ def each_local_configuration
485
+ ActiveRecord::Base.configurations.configs_for.each do |db_config|
486
+ configuration = db_config.config
487
+ next unless configuration["database"]
302
488
 
303
- if local_database?(configuration)
304
- yield configuration
305
- else
306
- $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
489
+ if local_database?(configuration)
490
+ yield configuration
491
+ else
492
+ $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
493
+ end
307
494
  end
308
495
  end
309
- end
310
496
 
311
- def local_database?(configuration)
312
- configuration['host'].blank? || LOCAL_HOSTS.include?(configuration['host'])
313
- end
497
+ def local_database?(configuration)
498
+ configuration["host"].blank? || LOCAL_HOSTS.include?(configuration["host"])
499
+ end
500
+
501
+ def schema_sha1(file)
502
+ Digest::SHA1.hexdigest(File.read(file))
503
+ end
314
504
  end
315
505
  end
316
506
  end