activerecord 5.0.7.2 → 6.1.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (363) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +829 -2015
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +11 -9
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record.rb +37 -29
  8. data/lib/active_record/aggregations.rb +249 -247
  9. data/lib/active_record/association_relation.rb +30 -18
  10. data/lib/active_record/associations.rb +1714 -1596
  11. data/lib/active_record/associations/alias_tracker.rb +36 -42
  12. data/lib/active_record/associations/association.rb +143 -68
  13. data/lib/active_record/associations/association_scope.rb +98 -94
  14. data/lib/active_record/associations/belongs_to_association.rb +76 -46
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  16. data/lib/active_record/associations/builder/association.rb +27 -28
  17. data/lib/active_record/associations/builder/belongs_to.rb +52 -60
  18. data/lib/active_record/associations/builder/collection_association.rb +12 -22
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +40 -62
  20. data/lib/active_record/associations/builder/has_many.rb +10 -2
  21. data/lib/active_record/associations/builder/has_one.rb +35 -2
  22. data/lib/active_record/associations/builder/singular_association.rb +5 -1
  23. data/lib/active_record/associations/collection_association.rb +104 -259
  24. data/lib/active_record/associations/collection_proxy.rb +169 -125
  25. data/lib/active_record/associations/foreign_association.rb +22 -0
  26. data/lib/active_record/associations/has_many_association.rb +46 -31
  27. data/lib/active_record/associations/has_many_through_association.rb +66 -46
  28. data/lib/active_record/associations/has_one_association.rb +71 -52
  29. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  30. data/lib/active_record/associations/join_dependency.rb +169 -180
  31. data/lib/active_record/associations/join_dependency/join_association.rb +53 -79
  32. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  33. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  34. data/lib/active_record/associations/preloader.rb +97 -104
  35. data/lib/active_record/associations/preloader/association.rb +109 -97
  36. data/lib/active_record/associations/preloader/through_association.rb +77 -76
  37. data/lib/active_record/associations/singular_association.rb +12 -45
  38. data/lib/active_record/associations/through_association.rb +27 -15
  39. data/lib/active_record/attribute_assignment.rb +55 -60
  40. data/lib/active_record/attribute_methods.rb +111 -141
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -9
  42. data/lib/active_record/attribute_methods/dirty.rb +172 -112
  43. data/lib/active_record/attribute_methods/primary_key.rb +88 -91
  44. data/lib/active_record/attribute_methods/query.rb +6 -8
  45. data/lib/active_record/attribute_methods/read.rb +18 -50
  46. data/lib/active_record/attribute_methods/serialization.rb +38 -10
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -66
  48. data/lib/active_record/attribute_methods/write.rb +25 -32
  49. data/lib/active_record/attributes.rb +69 -31
  50. data/lib/active_record/autosave_association.rb +102 -66
  51. data/lib/active_record/base.rb +16 -25
  52. data/lib/active_record/callbacks.rb +202 -43
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +11 -12
  55. data/lib/active_record/connection_adapters.rb +50 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +661 -375
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +14 -38
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +269 -105
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +54 -35
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +137 -93
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +155 -113
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -162
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +591 -259
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +229 -91
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +392 -244
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +457 -582
  69. data/lib/active_record/connection_adapters/column.rb +55 -13
  70. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  71. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +135 -49
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +79 -49
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +66 -56
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +20 -12
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +74 -37
  82. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  83. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  84. data/lib/active_record/connection_adapters/postgresql/column.rb +39 -28
  85. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +70 -101
  86. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  87. data/lib/active_record/connection_adapters/postgresql/oid.rb +26 -21
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  90. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -6
  93. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -4
  95. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  96. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
  98. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  104. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
  106. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
  107. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  109. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  110. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  112. data/lib/active_record/connection_adapters/postgresql/quoting.rb +98 -38
  113. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +21 -27
  114. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  116. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
  117. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +426 -324
  118. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +32 -23
  119. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
  120. data/lib/active_record/connection_adapters/postgresql_adapter.rb +418 -293
  121. data/lib/active_record/connection_adapters/schema_cache.rb +135 -18
  122. data/lib/active_record/connection_adapters/sql_type_metadata.rb +22 -7
  123. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
  124. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  125. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
  126. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -6
  127. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  128. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  129. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  130. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +282 -290
  131. data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
  132. data/lib/active_record/connection_handling.rb +287 -45
  133. data/lib/active_record/core.rb +385 -181
  134. data/lib/active_record/counter_cache.rb +60 -28
  135. data/lib/active_record/database_configurations.rb +272 -0
  136. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  137. data/lib/active_record/database_configurations/database_config.rb +80 -0
  138. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  139. data/lib/active_record/database_configurations/url_config.rb +53 -0
  140. data/lib/active_record/delegated_type.rb +209 -0
  141. data/lib/active_record/destroy_association_async_job.rb +36 -0
  142. data/lib/active_record/dynamic_matchers.rb +87 -87
  143. data/lib/active_record/enum.rb +122 -47
  144. data/lib/active_record/errors.rb +153 -22
  145. data/lib/active_record/explain.rb +13 -8
  146. data/lib/active_record/explain_registry.rb +3 -1
  147. data/lib/active_record/explain_subscriber.rb +9 -4
  148. data/lib/active_record/fixture_set/file.rb +20 -22
  149. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  150. data/lib/active_record/fixture_set/render_context.rb +17 -0
  151. data/lib/active_record/fixture_set/table_row.rb +152 -0
  152. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  153. data/lib/active_record/fixtures.rb +246 -507
  154. data/lib/active_record/gem_version.rb +6 -4
  155. data/lib/active_record/inheritance.rb +168 -95
  156. data/lib/active_record/insert_all.rb +208 -0
  157. data/lib/active_record/integration.rb +114 -25
  158. data/lib/active_record/internal_metadata.rb +30 -24
  159. data/lib/active_record/legacy_yaml_adapter.rb +11 -5
  160. data/lib/active_record/locking/optimistic.rb +81 -85
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +68 -31
  163. data/lib/active_record/middleware/database_selector.rb +77 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  166. data/lib/active_record/migration.rb +439 -342
  167. data/lib/active_record/migration/command_recorder.rb +152 -98
  168. data/lib/active_record/migration/compatibility.rb +229 -60
  169. data/lib/active_record/migration/join_table.rb +8 -7
  170. data/lib/active_record/model_schema.rb +230 -122
  171. data/lib/active_record/nested_attributes.rb +213 -203
  172. data/lib/active_record/no_touching.rb +11 -2
  173. data/lib/active_record/null_relation.rb +12 -34
  174. data/lib/active_record/persistence.rb +471 -97
  175. data/lib/active_record/query_cache.rb +23 -12
  176. data/lib/active_record/querying.rb +43 -25
  177. data/lib/active_record/railtie.rb +155 -43
  178. data/lib/active_record/railties/console_sandbox.rb +2 -0
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +507 -195
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +245 -269
  183. data/lib/active_record/relation.rb +475 -324
  184. data/lib/active_record/relation/batches.rb +125 -72
  185. data/lib/active_record/relation/batches/batch_enumerator.rb +28 -10
  186. data/lib/active_record/relation/calculations.rb +267 -171
  187. data/lib/active_record/relation/delegation.rb +73 -69
  188. data/lib/active_record/relation/finder_methods.rb +238 -248
  189. data/lib/active_record/relation/from_clause.rb +7 -9
  190. data/lib/active_record/relation/merger.rb +95 -77
  191. data/lib/active_record/relation/predicate_builder.rb +109 -110
  192. data/lib/active_record/relation/predicate_builder/array_handler.rb +22 -17
  193. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  194. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  195. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +55 -0
  196. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  197. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  198. data/lib/active_record/relation/query_attribute.rb +33 -2
  199. data/lib/active_record/relation/query_methods.rb +654 -374
  200. data/lib/active_record/relation/record_fetch_warning.rb +8 -6
  201. data/lib/active_record/relation/spawn_methods.rb +15 -14
  202. data/lib/active_record/relation/where_clause.rb +171 -109
  203. data/lib/active_record/result.rb +88 -51
  204. data/lib/active_record/runtime_registry.rb +5 -3
  205. data/lib/active_record/sanitization.rb +73 -100
  206. data/lib/active_record/schema.rb +7 -14
  207. data/lib/active_record/schema_dumper.rb +101 -69
  208. data/lib/active_record/schema_migration.rb +16 -12
  209. data/lib/active_record/scoping.rb +20 -20
  210. data/lib/active_record/scoping/default.rb +92 -95
  211. data/lib/active_record/scoping/named.rb +39 -30
  212. data/lib/active_record/secure_token.rb +19 -9
  213. data/lib/active_record/serialization.rb +7 -3
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +80 -29
  216. data/lib/active_record/store.rb +122 -42
  217. data/lib/active_record/suppressor.rb +6 -3
  218. data/lib/active_record/table_metadata.rb +51 -39
  219. data/lib/active_record/tasks/database_tasks.rb +332 -115
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +66 -104
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -56
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +40 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +246 -0
  225. data/lib/active_record/timestamp.rb +70 -38
  226. data/lib/active_record/touch_later.rb +26 -24
  227. data/lib/active_record/transactions.rb +121 -184
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type.rb +29 -17
  230. data/lib/active_record/type/adapter_specific_registry.rb +44 -48
  231. data/lib/active_record/type/date.rb +2 -0
  232. data/lib/active_record/type/date_time.rb +2 -0
  233. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  234. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  235. data/lib/active_record/type/internal/timezone.rb +2 -0
  236. data/lib/active_record/type/json.rb +30 -0
  237. data/lib/active_record/type/serialized.rb +20 -9
  238. data/lib/active_record/type/text.rb +11 -0
  239. data/lib/active_record/type/time.rb +12 -1
  240. data/lib/active_record/type/type_map.rb +14 -17
  241. data/lib/active_record/type/unsigned_integer.rb +16 -0
  242. data/lib/active_record/type_caster.rb +4 -2
  243. data/lib/active_record/type_caster/connection.rb +17 -13
  244. data/lib/active_record/type_caster/map.rb +10 -6
  245. data/lib/active_record/validations.rb +8 -5
  246. data/lib/active_record/validations/absence.rb +2 -0
  247. data/lib/active_record/validations/associated.rb +4 -3
  248. data/lib/active_record/validations/length.rb +2 -0
  249. data/lib/active_record/validations/numericality.rb +35 -0
  250. data/lib/active_record/validations/presence.rb +4 -2
  251. data/lib/active_record/validations/uniqueness.rb +52 -45
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/arel.rb +54 -0
  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.rb +70 -0
  269. data/lib/arel/nodes/and.rb +32 -0
  270. data/lib/arel/nodes/ascending.rb +23 -0
  271. data/lib/arel/nodes/binary.rb +126 -0
  272. data/lib/arel/nodes/bind_param.rb +44 -0
  273. data/lib/arel/nodes/case.rb +55 -0
  274. data/lib/arel/nodes/casted.rb +62 -0
  275. data/lib/arel/nodes/comment.rb +29 -0
  276. data/lib/arel/nodes/count.rb +12 -0
  277. data/lib/arel/nodes/delete_statement.rb +45 -0
  278. data/lib/arel/nodes/descending.rb +23 -0
  279. data/lib/arel/nodes/equality.rb +15 -0
  280. data/lib/arel/nodes/extract.rb +24 -0
  281. data/lib/arel/nodes/false.rb +16 -0
  282. data/lib/arel/nodes/full_outer_join.rb +8 -0
  283. data/lib/arel/nodes/function.rb +44 -0
  284. data/lib/arel/nodes/grouping.rb +11 -0
  285. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  286. data/lib/arel/nodes/in.rb +15 -0
  287. data/lib/arel/nodes/infix_operation.rb +92 -0
  288. data/lib/arel/nodes/inner_join.rb +8 -0
  289. data/lib/arel/nodes/insert_statement.rb +37 -0
  290. data/lib/arel/nodes/join_source.rb +20 -0
  291. data/lib/arel/nodes/matches.rb +18 -0
  292. data/lib/arel/nodes/named_function.rb +23 -0
  293. data/lib/arel/nodes/node.rb +51 -0
  294. data/lib/arel/nodes/node_expression.rb +13 -0
  295. data/lib/arel/nodes/ordering.rb +27 -0
  296. data/lib/arel/nodes/outer_join.rb +8 -0
  297. data/lib/arel/nodes/over.rb +15 -0
  298. data/lib/arel/nodes/regexp.rb +16 -0
  299. data/lib/arel/nodes/right_outer_join.rb +8 -0
  300. data/lib/arel/nodes/select_core.rb +67 -0
  301. data/lib/arel/nodes/select_statement.rb +41 -0
  302. data/lib/arel/nodes/sql_literal.rb +19 -0
  303. data/lib/arel/nodes/string_join.rb +11 -0
  304. data/lib/arel/nodes/table_alias.rb +31 -0
  305. data/lib/arel/nodes/terminal.rb +16 -0
  306. data/lib/arel/nodes/true.rb +16 -0
  307. data/lib/arel/nodes/unary.rb +44 -0
  308. data/lib/arel/nodes/unary_operation.rb +20 -0
  309. data/lib/arel/nodes/unqualified_column.rb +22 -0
  310. data/lib/arel/nodes/update_statement.rb +41 -0
  311. data/lib/arel/nodes/values_list.rb +9 -0
  312. data/lib/arel/nodes/window.rb +126 -0
  313. data/lib/arel/nodes/with.rb +11 -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.rb +13 -0
  321. data/lib/arel/visitors/dot.rb +308 -0
  322. data/lib/arel/visitors/mysql.rb +93 -0
  323. data/lib/arel/visitors/postgresql.rb +120 -0
  324. data/lib/arel/visitors/sqlite.rb +38 -0
  325. data/lib/arel/visitors/to_sql.rb +899 -0
  326. data/lib/arel/visitors/visitor.rb +45 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/rails/generators/active_record.rb +7 -5
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  331. data/lib/rails/generators/active_record/migration.rb +22 -3
  332. data/lib/rails/generators/active_record/migration/migration_generator.rb +38 -35
  333. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +3 -1
  334. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +7 -5
  335. data/lib/rails/generators/active_record/model/model_generator.rb +41 -25
  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 → model.rb.tt} +10 -1
  338. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  339. metadata +141 -57
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  347. data/lib/active_record/attribute.rb +0 -213
  348. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  349. data/lib/active_record/attribute_decorators.rb +0 -67
  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/connection_specification.rb +0 -263
  355. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -22
  356. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  357. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  358. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  359. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -17
  360. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  361. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  362. data/lib/active_record/relation/where_clause_factory.rb +0 -38
  363. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # ActiveRecord::Suppressor prevents the receiver from being saved during
3
5
  # a given block.
@@ -30,18 +32,19 @@ module ActiveRecord
30
32
 
31
33
  module ClassMethods
32
34
  def suppress(&block)
35
+ previous_state = SuppressorRegistry.suppressed[name]
33
36
  SuppressorRegistry.suppressed[name] = true
34
37
  yield
35
38
  ensure
36
- SuppressorRegistry.suppressed[name] = false
39
+ SuppressorRegistry.suppressed[name] = previous_state
37
40
  end
38
41
  end
39
42
 
40
- def save(*) # :nodoc:
43
+ def save(**) # :nodoc:
41
44
  SuppressorRegistry.suppressed[self.class.name] ? true : super
42
45
  end
43
46
 
44
- def save!(*) # :nodoc:
47
+ def save!(**) # :nodoc:
45
48
  SuppressorRegistry.suppressed[self.class.name] ? true : super
46
49
  end
47
50
  end
@@ -1,69 +1,81 @@
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 :join_primary_key, :join_foreign_key, :join_foreign_type, to: :reflection
5
6
 
6
- def initialize(klass, arel_table, association = nil)
7
+ def initialize(klass, arel_table, reflection = nil)
7
8
  @klass = klass
8
9
  @arel_table = arel_table
9
- @association = association
10
+ @reflection = reflection
10
11
  end
11
12
 
12
- 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)
19
- end
20
- end
21
- new_hash
13
+ def primary_key
14
+ klass&.primary_key
22
15
  end
23
16
 
24
- def arel_attribute(column_name)
25
- if klass
26
- klass.arel_attribute(column_name, arel_table)
27
- else
28
- arel_table[column_name]
29
- end
17
+ def type(column_name)
18
+ arel_table.type_for_attribute(column_name)
30
19
  end
31
20
 
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
21
+ def has_column?(column_name)
22
+ klass&.columns_hash.key?(column_name)
38
23
  end
39
24
 
40
- def associated_with?(association_name)
41
- klass && klass._reflect_on_association(association_name)
25
+ def associated_with?(table_name)
26
+ klass&._reflect_on_association(table_name) || klass&._reflect_on_association(table_name.singularize)
42
27
  end
43
28
 
44
29
  def associated_table(table_name)
45
- association = klass._reflect_on_association(table_name) || klass._reflect_on_association(table_name.to_s.singularize)
30
+ reflection = klass._reflect_on_association(table_name) || klass._reflect_on_association(table_name.singularize)
46
31
 
47
- if !association && table_name == arel_table.name
32
+ if !reflection && table_name == arel_table.name
48
33
  return self
49
- elsif association && !association.polymorphic?
50
- association_klass = association.klass
51
- arel_table = association_klass.arel_table.alias(table_name)
34
+ end
35
+
36
+ if reflection
37
+ association_klass = reflection.klass unless reflection.polymorphic?
38
+ elsif block_given?
39
+ association_klass = yield table_name
40
+ end
41
+
42
+ if association_klass
43
+ arel_table = association_klass.arel_table
44
+ arel_table = arel_table.alias(table_name) if arel_table.name != table_name
45
+ TableMetadata.new(association_klass, arel_table, reflection)
52
46
  else
53
47
  type_caster = TypeCaster::Connection.new(klass, table_name)
54
- association_klass = nil
55
48
  arel_table = Arel::Table.new(table_name, type_caster: type_caster)
49
+ TableMetadata.new(nil, arel_table, reflection)
56
50
  end
57
-
58
- TableMetadata.new(association_klass, arel_table, association)
59
51
  end
60
52
 
61
53
  def polymorphic_association?
62
- association && association.polymorphic?
54
+ reflection&.polymorphic?
55
+ end
56
+
57
+ def through_association?
58
+ reflection&.through_reflection?
59
+ end
60
+
61
+ def reflect_on_aggregation(aggregation_name)
62
+ klass&.reflect_on_aggregation(aggregation_name)
63
+ end
64
+ alias :aggregated_with? :reflect_on_aggregation
65
+
66
+ def predicate_builder
67
+ if klass
68
+ predicate_builder = klass.predicate_builder.dup
69
+ predicate_builder.instance_variable_set(:@table, self)
70
+ predicate_builder
71
+ else
72
+ PredicateBuilder.new(self)
73
+ end
63
74
  end
64
75
 
65
- protected
76
+ attr_reader :arel_table
66
77
 
67
- attr_reader :klass, :arel_table, :association
78
+ private
79
+ attr_reader :klass, :reflection
68
80
  end
69
81
  end
@@ -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
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
@@ -35,19 +36,30 @@ 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"]
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,175 +103,343 @@ module ActiveRecord
91
103
  @env ||= Rails.env
92
104
  end
93
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
+
94
115
  def seed_loader
95
116
  @seed_loader ||= Rails.application
96
117
  end
97
118
 
98
119
  def current_config(options = {})
99
- options.reverse_merge! :env => env
100
120
  if options.has_key?(:config)
101
121
  @current_config = options[:config]
102
122
  else
103
- @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
104
127
  end
105
128
  end
129
+ deprecate :current_config
106
130
 
107
- def create(*arguments)
108
- configuration = arguments.first
109
- class_for_adapter(configuration['adapter']).new(*arguments).create
110
- $stdout.puts "Created database '#{configuration['database']}'"
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?
111
135
  rescue DatabaseAlreadyExists
112
- $stderr.puts "Database '#{configuration['database']}' already exists"
136
+ $stderr.puts "Database '#{db_config.database}' already exists" if verbose?
113
137
  rescue Exception => error
114
138
  $stderr.puts error
115
- $stderr.puts "Couldn't create database for #{configuration.inspect}"
139
+ $stderr.puts "Couldn't create '#{db_config.database}' database. Please check your configuration."
116
140
  raise
117
141
  end
118
142
 
119
143
  def create_all
120
144
  old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
121
- each_local_configuration { |configuration| create configuration }
145
+ each_local_configuration { |db_config| create(db_config) }
122
146
  if old_pool
123
- ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec)
147
+ ActiveRecord::Base.connection_handler.establish_connection(old_pool.db_config)
148
+ end
149
+ end
150
+
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}."
124
189
  end
125
190
  end
126
191
 
127
- def create_current(environment = env)
128
- each_current_configuration(environment) { |configuration|
129
- create configuration
130
- }
192
+ def create_current(environment = env, name = nil)
193
+ each_current_configuration(environment, name) { |db_config| create(db_config) }
131
194
  ActiveRecord::Base.establish_connection(environment.to_sym)
132
195
  end
133
196
 
134
- def drop(*arguments)
135
- configuration = arguments.first
136
- class_for_adapter(configuration['adapter']).new(*arguments).drop
137
- $stdout.puts "Dropped database '#{configuration['database']}'"
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?
138
201
  rescue ActiveRecord::NoDatabaseError
139
- $stderr.puts "Database '#{configuration['database']}' does not exist"
202
+ $stderr.puts "Database '#{db_config.database}' does not exist"
140
203
  rescue Exception => error
141
204
  $stderr.puts error
142
- $stderr.puts "Couldn't drop database '#{configuration['database']}'"
205
+ $stderr.puts "Couldn't drop database '#{db_config.database}'"
143
206
  raise
144
207
  end
145
208
 
146
209
  def drop_all
147
- each_local_configuration { |configuration| drop configuration }
210
+ each_local_configuration { |db_config| drop(db_config) }
148
211
  end
149
212
 
150
213
  def drop_current(environment = env)
151
- each_current_configuration(environment) { |configuration|
152
- drop configuration
153
- }
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
154
229
  end
155
230
 
156
231
  def migrate
157
- raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
232
+ check_target_version
233
+
234
+ scope = ENV["SCOPE"]
235
+ verbose_was, Migration.verbose = Migration.verbose, verbose?
158
236
 
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|
237
+ Base.connection.migration_context.migrate(target_version) do |migration|
164
238
  scope.blank? || scope == migration.scope
165
239
  end
240
+
166
241
  ActiveRecord::Base.clear_cache!
167
242
  ensure
168
243
  Migration.verbose = verbose_was
169
244
  end
170
245
 
171
- def charset_current(environment = env)
172
- 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
173
259
  end
174
260
 
175
- def charset(*arguments)
176
- configuration = arguments.first
177
- class_for_adapter(configuration['adapter']).new(*arguments).charset
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
178
265
  end
179
266
 
180
- def collation_current(environment = env)
181
- collation ActiveRecord::Base.configurations[environment]
267
+ def target_version
268
+ ENV["VERSION"].to_i if ENV["VERSION"] && !ENV["VERSION"].empty?
182
269
  end
183
270
 
184
- def collation(*arguments)
185
- configuration = arguments.first
186
- class_for_adapter(configuration['adapter']).new(*arguments).collation
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)
274
+ end
275
+
276
+ def charset(configuration, *arguments)
277
+ db_config = resolve_configuration(configuration)
278
+ database_adapter_for(db_config, *arguments).charset
279
+ end
280
+
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
187
289
  end
188
290
 
189
291
  def purge(configuration)
190
- class_for_adapter(configuration['adapter']).new(configuration).purge
292
+ db_config = resolve_configuration(configuration)
293
+ database_adapter_for(db_config).purge
191
294
  end
192
295
 
193
296
  def purge_all
194
- each_local_configuration { |configuration|
195
- purge configuration
196
- }
297
+ each_local_configuration { |db_config| purge(db_config) }
197
298
  end
198
299
 
199
300
  def purge_current(environment = env)
200
- each_current_configuration(environment) { |configuration|
201
- purge configuration
202
- }
301
+ each_current_configuration(environment) { |db_config| purge(db_config) }
203
302
  ActiveRecord::Base.establish_connection(environment.to_sym)
204
303
  end
205
304
 
206
- def structure_dump(*arguments)
207
- configuration = arguments.first
208
- filename = arguments.delete_at 1
209
- 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)
210
309
  end
211
310
 
212
- def structure_load(*arguments)
213
- configuration = arguments.first
214
- filename = arguments.delete_at 1
215
- class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename)
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)
216
315
  end
217
316
 
218
- def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env) # :nodoc:
219
- file ||= schema_file(format)
317
+ def load_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
318
+ file ||= dump_filename(db_config.name, format)
220
319
 
320
+ verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
221
321
  check_schema_file(file)
222
- ActiveRecord::Base.establish_connection(configuration)
322
+ ActiveRecord::Base.establish_connection(db_config)
223
323
 
224
324
  case format
225
325
  when :ruby
226
326
  load(file)
227
327
  when :sql
228
- structure_load(configuration, file)
328
+ structure_load(db_config, file)
229
329
  else
230
330
  raise ArgumentError, "unknown format #{format.inspect}"
231
331
  end
232
332
  ActiveRecord::InternalMetadata.create_table
233
- ActiveRecord::InternalMetadata[:environment] = environment
333
+ ActiveRecord::InternalMetadata[:environment] = db_config.env_name
334
+ ActiveRecord::InternalMetadata[:schema_sha1] = schema_sha1(file)
335
+ ensure
336
+ Migration.verbose = verbose_was
234
337
  end
235
338
 
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)
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 6.2.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)
358
+ end
359
+
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)
366
+
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)
376
+ end
377
+
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)
384
+ case format
385
+ when :ruby
386
+ File.open(filename, "w:utf-8") do |file|
387
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
388
+ end
389
+ when :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
397
+ end
242
398
  end
243
399
 
244
400
  def schema_file(format = ActiveRecord::Base.schema_format)
401
+ File.join(db_dir, schema_file_type(format))
402
+ end
403
+
404
+ def schema_file_type(format = ActiveRecord::Base.schema_format)
245
405
  case format
246
406
  when :ruby
247
- File.join(db_dir, "schema.rb")
407
+ "schema.rb"
248
408
  when :sql
249
- File.join(db_dir, "structure.sql")
409
+ "structure.sql"
250
410
  end
251
411
  end
252
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)
416
+ else
417
+ "#{db_config_name}_#{schema_file_type(format)}"
418
+ end
419
+
420
+ ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
421
+ end
422
+
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"
428
+ end
429
+
430
+ schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
431
+ end
432
+
253
433
  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
256
- }
434
+ each_current_configuration(environment) do |db_config|
435
+ load_schema(db_config, format, file)
436
+ end
257
437
  ActiveRecord::Base.establish_connection(environment.to_sym)
258
438
  end
259
439
 
260
440
  def check_schema_file(filename)
261
441
  unless File.exist?(filename)
262
- message = %{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}
442
+ message = +%{#{filename} doesn't exist yet. Run `bin/rails db:migrate` to create it, then try again.}
263
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)
264
444
  Kernel.abort message
265
445
  end
@@ -269,48 +449,85 @@ module ActiveRecord
269
449
  if seed_loader
270
450
  seed_loader.load_seed
271
451
  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" +
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" \
274
454
  "Seed loader should respond to load_seed method"
275
455
  end
276
456
  end
277
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
+
278
470
  private
471
+ def resolve_configuration(configuration)
472
+ Base.configurations.resolve(configuration)
473
+ end
279
474
 
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"
475
+ def verbose?
476
+ ENV["VERBOSE"] ? ENV["VERBOSE"] != "false" : true
284
477
  end
285
- @tasks[key]
286
- end
287
478
 
288
- def each_current_configuration(environment)
289
- environments = [environment]
290
- environments << 'test' if environment == 'development'
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?
291
485
 
292
- ActiveRecord::Base.configurations.slice(*environments).each do |configuration_environment, configuration|
293
- next unless configuration["database"]
486
+ config = converted ? db_config : db_config.configuration_hash
487
+ klass.new(config, *arguments)
488
+ end
294
489
 
295
- yield configuration, configuration_environment
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
296
496
  end
297
- end
298
497
 
299
- def each_local_configuration
300
- ActiveRecord::Base.configurations.each_value do |configuration|
301
- 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"]
501
+
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
302
505
 
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."
506
+ yield db_config
507
+ end
307
508
  end
308
509
  end
309
- end
310
510
 
311
- def local_database?(configuration)
312
- configuration['host'].blank? || LOCAL_HOSTS.include?(configuration['host'])
313
- 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
314
531
  end
315
532
  end
316
533
  end