activerecord 5.2.8 → 7.0.2

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 (364) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1393 -587
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +7 -5
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +10 -9
  7. data/lib/active_record/association_relation.rb +22 -12
  8. data/lib/active_record/associations/alias_tracker.rb +19 -16
  9. data/lib/active_record/associations/association.rb +122 -47
  10. data/lib/active_record/associations/association_scope.rb +24 -24
  11. data/lib/active_record/associations/belongs_to_association.rb +67 -49
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -7
  13. data/lib/active_record/associations/builder/association.rb +52 -23
  14. data/lib/active_record/associations/builder/belongs_to.rb +44 -61
  15. data/lib/active_record/associations/builder/collection_association.rb +17 -19
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
  17. data/lib/active_record/associations/builder/has_many.rb +10 -3
  18. data/lib/active_record/associations/builder/has_one.rb +35 -3
  19. data/lib/active_record/associations/builder/singular_association.rb +5 -3
  20. data/lib/active_record/associations/collection_association.rb +59 -50
  21. data/lib/active_record/associations/collection_proxy.rb +32 -23
  22. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  23. data/lib/active_record/associations/foreign_association.rb +20 -0
  24. data/lib/active_record/associations/has_many_association.rb +27 -14
  25. data/lib/active_record/associations/has_many_through_association.rb +26 -19
  26. data/lib/active_record/associations/has_one_association.rb +52 -37
  27. data/lib/active_record/associations/has_one_through_association.rb +6 -6
  28. data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
  29. data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
  30. data/lib/active_record/associations/join_dependency.rb +97 -62
  31. data/lib/active_record/associations/preloader/association.rb +220 -60
  32. data/lib/active_record/associations/preloader/batch.rb +48 -0
  33. data/lib/active_record/associations/preloader/branch.rb +147 -0
  34. data/lib/active_record/associations/preloader/through_association.rb +85 -40
  35. data/lib/active_record/associations/preloader.rb +44 -105
  36. data/lib/active_record/associations/singular_association.rb +9 -17
  37. data/lib/active_record/associations/through_association.rb +4 -4
  38. data/lib/active_record/associations.rb +207 -66
  39. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  40. data/lib/active_record/attribute_assignment.rb +17 -19
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +19 -8
  42. data/lib/active_record/attribute_methods/dirty.rb +141 -47
  43. data/lib/active_record/attribute_methods/primary_key.rb +22 -27
  44. data/lib/active_record/attribute_methods/query.rb +6 -10
  45. data/lib/active_record/attribute_methods/read.rb +15 -55
  46. data/lib/active_record/attribute_methods/serialization.rb +77 -18
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +16 -18
  48. data/lib/active_record/attribute_methods/write.rb +18 -37
  49. data/lib/active_record/attribute_methods.rb +90 -153
  50. data/lib/active_record/attributes.rb +38 -12
  51. data/lib/active_record/autosave_association.rb +50 -50
  52. data/lib/active_record/base.rb +23 -18
  53. data/lib/active_record/callbacks.rb +159 -44
  54. data/lib/active_record/coders/yaml_column.rb +12 -3
  55. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
  57. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
  58. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +92 -464
  59. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -51
  60. data/lib/active_record/connection_adapters/abstract/database_statements.rb +209 -164
  61. data/lib/active_record/connection_adapters/abstract/query_cache.rb +38 -22
  62. data/lib/active_record/connection_adapters/abstract/quoting.rb +103 -82
  63. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  64. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +140 -110
  65. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -94
  66. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +16 -5
  67. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +456 -159
  68. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -162
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +311 -327
  71. data/lib/active_record/connection_adapters/column.rb +33 -11
  72. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  73. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  74. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  75. data/lib/active_record/connection_adapters/mysql/database_statements.rb +113 -45
  76. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  77. data/lib/active_record/connection_adapters/mysql/quoting.rb +71 -5
  78. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
  79. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
  80. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +25 -8
  81. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +143 -19
  82. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
  83. data/lib/active_record/connection_adapters/mysql2_adapter.rb +63 -22
  84. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  85. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  86. data/lib/active_record/connection_adapters/postgresql/column.rb +53 -28
  87. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +56 -63
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +54 -16
  95. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +26 -12
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -52
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -2
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +39 -4
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +128 -91
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -1
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +149 -113
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +386 -182
  116. data/lib/active_record/connection_adapters/schema_cache.rb +161 -22
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
  118. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +152 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +65 -18
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  121. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +92 -26
  122. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +251 -204
  123. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  124. data/lib/active_record/connection_adapters.rb +53 -0
  125. data/lib/active_record/connection_handling.rb +292 -38
  126. data/lib/active_record/core.rb +385 -158
  127. data/lib/active_record/counter_cache.rb +8 -30
  128. data/lib/active_record/database_configurations/connection_url_resolver.rb +100 -0
  129. data/lib/active_record/database_configurations/database_config.rb +83 -0
  130. data/lib/active_record/database_configurations/hash_config.rb +154 -0
  131. data/lib/active_record/database_configurations/url_config.rb +53 -0
  132. data/lib/active_record/database_configurations.rb +256 -0
  133. data/lib/active_record/delegated_type.rb +250 -0
  134. data/lib/active_record/destroy_association_async_job.rb +36 -0
  135. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  136. data/lib/active_record/dynamic_matchers.rb +4 -5
  137. data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
  138. data/lib/active_record/encryption/cipher.rb +53 -0
  139. data/lib/active_record/encryption/config.rb +44 -0
  140. data/lib/active_record/encryption/configurable.rb +61 -0
  141. data/lib/active_record/encryption/context.rb +35 -0
  142. data/lib/active_record/encryption/contexts.rb +72 -0
  143. data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
  144. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  145. data/lib/active_record/encryption/encryptable_record.rb +208 -0
  146. data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
  147. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  148. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  149. data/lib/active_record/encryption/encryptor.rb +155 -0
  150. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  151. data/lib/active_record/encryption/errors.rb +15 -0
  152. data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
  153. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  154. data/lib/active_record/encryption/key.rb +28 -0
  155. data/lib/active_record/encryption/key_generator.rb +42 -0
  156. data/lib/active_record/encryption/key_provider.rb +46 -0
  157. data/lib/active_record/encryption/message.rb +33 -0
  158. data/lib/active_record/encryption/message_serializer.rb +90 -0
  159. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  160. data/lib/active_record/encryption/properties.rb +76 -0
  161. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  162. data/lib/active_record/encryption/scheme.rb +99 -0
  163. data/lib/active_record/encryption.rb +55 -0
  164. data/lib/active_record/enum.rb +130 -51
  165. data/lib/active_record/errors.rb +129 -23
  166. data/lib/active_record/explain.rb +10 -6
  167. data/lib/active_record/explain_registry.rb +11 -6
  168. data/lib/active_record/explain_subscriber.rb +1 -1
  169. data/lib/active_record/fixture_set/file.rb +22 -15
  170. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  171. data/lib/active_record/fixture_set/render_context.rb +17 -0
  172. data/lib/active_record/fixture_set/table_row.rb +187 -0
  173. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  174. data/lib/active_record/fixtures.rb +206 -490
  175. data/lib/active_record/future_result.rb +139 -0
  176. data/lib/active_record/gem_version.rb +3 -3
  177. data/lib/active_record/inheritance.rb +104 -37
  178. data/lib/active_record/insert_all.rb +278 -0
  179. data/lib/active_record/integration.rb +69 -18
  180. data/lib/active_record/internal_metadata.rb +24 -9
  181. data/lib/active_record/legacy_yaml_adapter.rb +3 -36
  182. data/lib/active_record/locking/optimistic.rb +41 -26
  183. data/lib/active_record/locking/pessimistic.rb +18 -8
  184. data/lib/active_record/log_subscriber.rb +46 -35
  185. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  186. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  187. data/lib/active_record/middleware/database_selector.rb +82 -0
  188. data/lib/active_record/middleware/shard_selector.rb +60 -0
  189. data/lib/active_record/migration/command_recorder.rb +96 -44
  190. data/lib/active_record/migration/compatibility.rb +246 -64
  191. data/lib/active_record/migration/join_table.rb +1 -2
  192. data/lib/active_record/migration.rb +266 -187
  193. data/lib/active_record/model_schema.rb +165 -52
  194. data/lib/active_record/nested_attributes.rb +17 -19
  195. data/lib/active_record/no_touching.rb +11 -4
  196. data/lib/active_record/null_relation.rb +2 -7
  197. data/lib/active_record/persistence.rb +467 -92
  198. data/lib/active_record/query_cache.rb +21 -4
  199. data/lib/active_record/query_logs.rb +138 -0
  200. data/lib/active_record/querying.rb +51 -24
  201. data/lib/active_record/railtie.rb +224 -57
  202. data/lib/active_record/railties/console_sandbox.rb +2 -4
  203. data/lib/active_record/railties/controller_runtime.rb +31 -36
  204. data/lib/active_record/railties/databases.rake +369 -101
  205. data/lib/active_record/readonly_attributes.rb +15 -0
  206. data/lib/active_record/reflection.rb +170 -137
  207. data/lib/active_record/relation/batches/batch_enumerator.rb +44 -14
  208. data/lib/active_record/relation/batches.rb +46 -37
  209. data/lib/active_record/relation/calculations.rb +168 -96
  210. data/lib/active_record/relation/delegation.rb +37 -52
  211. data/lib/active_record/relation/finder_methods.rb +79 -58
  212. data/lib/active_record/relation/from_clause.rb +5 -1
  213. data/lib/active_record/relation/merger.rb +50 -51
  214. data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
  215. data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
  216. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  217. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
  218. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  219. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  220. data/lib/active_record/relation/predicate_builder.rb +58 -46
  221. data/lib/active_record/relation/query_attribute.rb +9 -10
  222. data/lib/active_record/relation/query_methods.rb +685 -208
  223. data/lib/active_record/relation/record_fetch_warning.rb +9 -11
  224. data/lib/active_record/relation/spawn_methods.rb +10 -10
  225. data/lib/active_record/relation/where_clause.rb +108 -64
  226. data/lib/active_record/relation.rb +515 -151
  227. data/lib/active_record/result.rb +78 -42
  228. data/lib/active_record/runtime_registry.rb +9 -13
  229. data/lib/active_record/sanitization.rb +29 -44
  230. data/lib/active_record/schema.rb +37 -31
  231. data/lib/active_record/schema_dumper.rb +74 -23
  232. data/lib/active_record/schema_migration.rb +7 -9
  233. data/lib/active_record/scoping/default.rb +62 -17
  234. data/lib/active_record/scoping/named.rb +17 -32
  235. data/lib/active_record/scoping.rb +70 -41
  236. data/lib/active_record/secure_token.rb +16 -8
  237. data/lib/active_record/serialization.rb +6 -4
  238. data/lib/active_record/signed_id.rb +116 -0
  239. data/lib/active_record/statement_cache.rb +49 -6
  240. data/lib/active_record/store.rb +88 -9
  241. data/lib/active_record/suppressor.rb +13 -17
  242. data/lib/active_record/table_metadata.rb +42 -43
  243. data/lib/active_record/tasks/database_tasks.rb +352 -94
  244. data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
  245. data/lib/active_record/tasks/postgresql_database_tasks.rb +41 -39
  246. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
  247. data/lib/active_record/test_databases.rb +24 -0
  248. data/lib/active_record/test_fixtures.rb +287 -0
  249. data/lib/active_record/timestamp.rb +44 -34
  250. data/lib/active_record/touch_later.rb +23 -22
  251. data/lib/active_record/transactions.rb +67 -128
  252. data/lib/active_record/translation.rb +3 -3
  253. data/lib/active_record/type/adapter_specific_registry.rb +34 -19
  254. data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
  255. data/lib/active_record/type/internal/timezone.rb +2 -2
  256. data/lib/active_record/type/serialized.rb +7 -4
  257. data/lib/active_record/type/time.rb +10 -0
  258. data/lib/active_record/type/type_map.rb +17 -21
  259. data/lib/active_record/type/unsigned_integer.rb +0 -1
  260. data/lib/active_record/type.rb +9 -5
  261. data/lib/active_record/type_caster/connection.rb +15 -15
  262. data/lib/active_record/type_caster/map.rb +8 -8
  263. data/lib/active_record/validations/associated.rb +2 -3
  264. data/lib/active_record/validations/numericality.rb +35 -0
  265. data/lib/active_record/validations/uniqueness.rb +39 -31
  266. data/lib/active_record/validations.rb +4 -3
  267. data/lib/active_record.rb +209 -32
  268. data/lib/arel/alias_predication.rb +9 -0
  269. data/lib/arel/attributes/attribute.rb +33 -0
  270. data/lib/arel/collectors/bind.rb +29 -0
  271. data/lib/arel/collectors/composite.rb +39 -0
  272. data/lib/arel/collectors/plain_string.rb +20 -0
  273. data/lib/arel/collectors/sql_string.rb +27 -0
  274. data/lib/arel/collectors/substitute_binds.rb +35 -0
  275. data/lib/arel/crud.rb +48 -0
  276. data/lib/arel/delete_manager.rb +32 -0
  277. data/lib/arel/errors.rb +9 -0
  278. data/lib/arel/expressions.rb +29 -0
  279. data/lib/arel/factory_methods.rb +49 -0
  280. data/lib/arel/filter_predications.rb +9 -0
  281. data/lib/arel/insert_manager.rb +48 -0
  282. data/lib/arel/math.rb +45 -0
  283. data/lib/arel/nodes/and.rb +32 -0
  284. data/lib/arel/nodes/ascending.rb +23 -0
  285. data/lib/arel/nodes/binary.rb +126 -0
  286. data/lib/arel/nodes/bind_param.rb +44 -0
  287. data/lib/arel/nodes/case.rb +55 -0
  288. data/lib/arel/nodes/casted.rb +62 -0
  289. data/lib/arel/nodes/comment.rb +29 -0
  290. data/lib/arel/nodes/count.rb +12 -0
  291. data/lib/arel/nodes/delete_statement.rb +44 -0
  292. data/lib/arel/nodes/descending.rb +23 -0
  293. data/lib/arel/nodes/equality.rb +15 -0
  294. data/lib/arel/nodes/extract.rb +24 -0
  295. data/lib/arel/nodes/false.rb +16 -0
  296. data/lib/arel/nodes/filter.rb +10 -0
  297. data/lib/arel/nodes/full_outer_join.rb +8 -0
  298. data/lib/arel/nodes/function.rb +45 -0
  299. data/lib/arel/nodes/grouping.rb +11 -0
  300. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  301. data/lib/arel/nodes/in.rb +15 -0
  302. data/lib/arel/nodes/infix_operation.rb +92 -0
  303. data/lib/arel/nodes/inner_join.rb +8 -0
  304. data/lib/arel/nodes/insert_statement.rb +37 -0
  305. data/lib/arel/nodes/join_source.rb +20 -0
  306. data/lib/arel/nodes/matches.rb +18 -0
  307. data/lib/arel/nodes/named_function.rb +23 -0
  308. data/lib/arel/nodes/node.rb +51 -0
  309. data/lib/arel/nodes/node_expression.rb +13 -0
  310. data/lib/arel/nodes/ordering.rb +27 -0
  311. data/lib/arel/nodes/outer_join.rb +8 -0
  312. data/lib/arel/nodes/over.rb +15 -0
  313. data/lib/arel/nodes/regexp.rb +16 -0
  314. data/lib/arel/nodes/right_outer_join.rb +8 -0
  315. data/lib/arel/nodes/select_core.rb +67 -0
  316. data/lib/arel/nodes/select_statement.rb +41 -0
  317. data/lib/arel/nodes/sql_literal.rb +19 -0
  318. data/lib/arel/nodes/string_join.rb +11 -0
  319. data/lib/arel/nodes/table_alias.rb +31 -0
  320. data/lib/arel/nodes/terminal.rb +16 -0
  321. data/lib/arel/nodes/true.rb +16 -0
  322. data/lib/arel/nodes/unary.rb +44 -0
  323. data/lib/arel/nodes/unary_operation.rb +20 -0
  324. data/lib/arel/nodes/unqualified_column.rb +22 -0
  325. data/lib/arel/nodes/update_statement.rb +46 -0
  326. data/lib/arel/nodes/values_list.rb +9 -0
  327. data/lib/arel/nodes/window.rb +126 -0
  328. data/lib/arel/nodes/with.rb +11 -0
  329. data/lib/arel/nodes.rb +71 -0
  330. data/lib/arel/order_predications.rb +13 -0
  331. data/lib/arel/predications.rb +258 -0
  332. data/lib/arel/select_manager.rb +276 -0
  333. data/lib/arel/table.rb +117 -0
  334. data/lib/arel/tree_manager.rb +60 -0
  335. data/lib/arel/update_manager.rb +48 -0
  336. data/lib/arel/visitors/dot.rb +298 -0
  337. data/lib/arel/visitors/mysql.rb +99 -0
  338. data/lib/arel/visitors/postgresql.rb +110 -0
  339. data/lib/arel/visitors/sqlite.rb +38 -0
  340. data/lib/arel/visitors/to_sql.rb +955 -0
  341. data/lib/arel/visitors/visitor.rb +45 -0
  342. data/lib/arel/visitors.rb +13 -0
  343. data/lib/arel/window_predications.rb +9 -0
  344. data/lib/arel.rb +55 -0
  345. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  346. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  347. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
  348. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
  349. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
  350. data/lib/rails/generators/active_record/migration.rb +19 -2
  351. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  352. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  353. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  354. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  355. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  356. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  357. metadata +162 -32
  358. data/lib/active_record/attribute_decorators.rb +0 -90
  359. data/lib/active_record/collection_cache_key.rb +0 -53
  360. data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
  361. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
  362. data/lib/active_record/define_callbacks.rb +0 -22
  363. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
  364. data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_record/database_configurations"
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
@@ -37,17 +38,24 @@ module ActiveRecord
37
38
  module DatabaseTasks
38
39
  ##
39
40
  # :singleton-method:
40
- # Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:structure:dump
41
+ # Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:schema:dump
42
+ # It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
43
+ # Example:
44
+ # ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
45
+ # mysql2: ['--no-defaults', '--skip-add-drop-table'],
46
+ # postgres: '--no-tablespaces'
47
+ # }
41
48
  mattr_accessor :structure_dump_flags, instance_accessor: false
42
49
 
43
50
  ##
44
51
  # :singleton-method:
45
- # Extra flags passed to database CLI tool when calling db:structure:load
52
+ # Extra flags passed to database CLI tool when calling db:schema:load
53
+ # It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
46
54
  mattr_accessor :structure_load_flags, instance_accessor: false
47
55
 
48
56
  extend self
49
57
 
50
- attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
58
+ attr_writer :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
51
59
  attr_accessor :database_configuration
52
60
 
53
61
  LOCAL_HOSTS = ["127.0.0.1", "localhost"]
@@ -101,82 +109,201 @@ module ActiveRecord
101
109
  @env ||= Rails.env
102
110
  end
103
111
 
104
- def seed_loader
105
- @seed_loader ||= Rails.application
112
+ def name
113
+ @name ||= "primary"
106
114
  end
107
115
 
108
- def current_config(options = {})
109
- options.reverse_merge! env: env
110
- if options.has_key?(:config)
111
- @current_config = options[:config]
112
- else
113
- @current_config ||= ActiveRecord::Base.configurations[options[:env]]
114
- end
116
+ def seed_loader
117
+ @seed_loader ||= Rails.application
115
118
  end
116
119
 
117
- def create(*arguments)
118
- configuration = arguments.first
119
- class_for_adapter(configuration["adapter"]).new(*arguments).create
120
- $stdout.puts "Created database '#{configuration['database']}'"
120
+ def create(configuration, *arguments)
121
+ db_config = resolve_configuration(configuration)
122
+ database_adapter_for(db_config, *arguments).create
123
+ $stdout.puts "Created database '#{db_config.database}'" if verbose?
121
124
  rescue DatabaseAlreadyExists
122
- $stderr.puts "Database '#{configuration['database']}' already exists"
125
+ $stderr.puts "Database '#{db_config.database}' already exists" if verbose?
123
126
  rescue Exception => error
124
127
  $stderr.puts error
125
- $stderr.puts "Couldn't create '#{configuration['database']}' database. Please check your configuration."
128
+ $stderr.puts "Couldn't create '#{db_config.database}' database. Please check your configuration."
126
129
  raise
127
130
  end
128
131
 
129
132
  def create_all
130
133
  old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
131
- each_local_configuration { |configuration| create configuration }
134
+ each_local_configuration { |db_config| create(db_config) }
132
135
  if old_pool
133
- ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec.to_hash)
136
+ ActiveRecord::Base.connection_handler.establish_connection(old_pool.db_config)
137
+ end
138
+ end
139
+
140
+ def setup_initial_database_yaml
141
+ return {} unless defined?(Rails)
142
+
143
+ begin
144
+ Rails.application.config.load_database_yaml
145
+ rescue
146
+ unless ActiveRecord.suppress_multiple_database_warning
147
+ $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."
148
+ end
149
+
150
+ {}
151
+ end
152
+ end
153
+
154
+ def for_each(databases)
155
+ return {} unless defined?(Rails)
156
+
157
+ database_configs = ActiveRecord::DatabaseConfigurations.new(databases).configs_for(env_name: Rails.env)
158
+
159
+ # if this is a single database application we don't want tasks for each primary database
160
+ return if database_configs.count == 1
161
+
162
+ database_configs.each do |db_config|
163
+ next unless db_config.database_tasks?
164
+
165
+ yield db_config.name
134
166
  end
135
167
  end
136
168
 
137
- def create_current(environment = env)
138
- each_current_configuration(environment) { |configuration|
139
- create configuration
140
- }
169
+ def raise_for_multi_db(environment = env, command:)
170
+ db_configs = 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.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, name = nil)
184
+ each_current_configuration(environment, name) { |db_config| create(db_config) }
141
185
  ActiveRecord::Base.establish_connection(environment.to_sym)
142
186
  end
143
187
 
144
- def drop(*arguments)
145
- configuration = arguments.first
146
- class_for_adapter(configuration["adapter"]).new(*arguments).drop
147
- $stdout.puts "Dropped database '#{configuration['database']}'"
188
+ def prepare_all
189
+ seed = false
190
+
191
+ configs_for(env_name: env).each do |db_config|
192
+ ActiveRecord::Base.establish_connection(db_config)
193
+
194
+ # Skipped when no database
195
+ migrate
196
+
197
+ if ActiveRecord.dump_schema_after_migration
198
+ dump_schema(db_config, ActiveRecord.schema_format)
199
+ end
200
+ rescue ActiveRecord::NoDatabaseError
201
+ create_current(db_config.env_name, db_config.name)
202
+
203
+ if File.exist?(schema_dump_path(db_config))
204
+ load_schema(
205
+ db_config,
206
+ ActiveRecord.schema_format,
207
+ nil
208
+ )
209
+ else
210
+ migrate
211
+ end
212
+
213
+ seed = true
214
+ end
215
+
216
+ ActiveRecord::Base.establish_connection
217
+ load_seed if seed
218
+ end
219
+
220
+ def drop(configuration, *arguments)
221
+ db_config = resolve_configuration(configuration)
222
+ database_adapter_for(db_config, *arguments).drop
223
+ $stdout.puts "Dropped database '#{db_config.database}'" if verbose?
148
224
  rescue ActiveRecord::NoDatabaseError
149
- $stderr.puts "Database '#{configuration['database']}' does not exist"
225
+ $stderr.puts "Database '#{db_config.database}' does not exist"
150
226
  rescue Exception => error
151
227
  $stderr.puts error
152
- $stderr.puts "Couldn't drop database '#{configuration['database']}'"
228
+ $stderr.puts "Couldn't drop database '#{db_config.database}'"
153
229
  raise
154
230
  end
155
231
 
156
232
  def drop_all
157
- each_local_configuration { |configuration| drop configuration }
233
+ each_local_configuration { |db_config| drop(db_config) }
158
234
  end
159
235
 
160
236
  def drop_current(environment = env)
161
- each_current_configuration(environment) { |configuration|
162
- drop configuration
163
- }
237
+ each_current_configuration(environment) { |db_config| drop(db_config) }
164
238
  end
165
239
 
166
- def migrate
240
+ def truncate_tables(db_config)
241
+ ActiveRecord::Base.establish_connection(db_config)
242
+
243
+ connection = ActiveRecord::Base.connection
244
+ connection.truncate_tables(*connection.tables)
245
+ end
246
+ private :truncate_tables
247
+
248
+ def truncate_all(environment = env)
249
+ configs_for(env_name: environment).each do |db_config|
250
+ truncate_tables(db_config)
251
+ end
252
+ end
253
+
254
+ def migrate(version = nil)
167
255
  check_target_version
168
256
 
169
- verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] != "false" : true
170
257
  scope = ENV["SCOPE"]
171
- verbose_was, Migration.verbose = Migration.verbose, verbose
258
+ verbose_was, Migration.verbose = Migration.verbose, verbose?
259
+
172
260
  Base.connection.migration_context.migrate(target_version) do |migration|
173
- scope.blank? || scope == migration.scope
261
+ if version.blank?
262
+ scope.blank? || scope == migration.scope
263
+ else
264
+ migration.version == version
265
+ end
266
+ end.tap do |migrations_ran|
267
+ Migration.write("No migrations ran. (using #{scope} scope)") if scope.present? && migrations_ran.empty?
174
268
  end
269
+
175
270
  ActiveRecord::Base.clear_cache!
176
271
  ensure
177
272
  Migration.verbose = verbose_was
178
273
  end
179
274
 
275
+ def db_configs_with_versions(db_configs) # :nodoc:
276
+ db_configs_with_versions = Hash.new { |h, k| h[k] = [] }
277
+
278
+ db_configs.each do |db_config|
279
+ ActiveRecord::Base.establish_connection(db_config)
280
+ versions_to_run = ActiveRecord::Base.connection.migration_context.pending_migration_versions
281
+ target_version = ActiveRecord::Tasks::DatabaseTasks.target_version
282
+
283
+ versions_to_run.each do |version|
284
+ next if target_version && target_version != version
285
+ db_configs_with_versions[version] << db_config
286
+ end
287
+ end
288
+
289
+ db_configs_with_versions
290
+ end
291
+
292
+ def migrate_status
293
+ unless ActiveRecord::Base.connection.schema_migration.table_exists?
294
+ Kernel.abort "Schema migrations table does not exist yet."
295
+ end
296
+
297
+ # output
298
+ puts "\ndatabase: #{ActiveRecord::Base.connection_db_config.database}\n\n"
299
+ puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
300
+ puts "-" * 50
301
+ ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
302
+ puts "#{status.center(8)} #{version.ljust(14)} #{name}"
303
+ end
304
+ puts
305
+ end
306
+
180
307
  def check_target_version
181
308
  if target_version && !(Migration::MigrationFilenameRegexp.match?(ENV["VERSION"]) || /\A\d+\z/.match?(ENV["VERSION"]))
182
309
  raise "Invalid format of target version: `VERSION=#{ENV['VERSION']}`"
@@ -187,90 +314,174 @@ module ActiveRecord
187
314
  ENV["VERSION"].to_i if ENV["VERSION"] && !ENV["VERSION"].empty?
188
315
  end
189
316
 
190
- def charset_current(environment = env)
191
- charset ActiveRecord::Base.configurations[environment]
317
+ def charset_current(env_name = env, db_name = name)
318
+ db_config = configs_for(env_name: env_name, name: db_name)
319
+ charset(db_config)
192
320
  end
193
321
 
194
- def charset(*arguments)
195
- configuration = arguments.first
196
- class_for_adapter(configuration["adapter"]).new(*arguments).charset
322
+ def charset(configuration, *arguments)
323
+ db_config = resolve_configuration(configuration)
324
+ database_adapter_for(db_config, *arguments).charset
197
325
  end
198
326
 
199
- def collation_current(environment = env)
200
- collation ActiveRecord::Base.configurations[environment]
327
+ def collation_current(env_name = env, db_name = name)
328
+ db_config = configs_for(env_name: env_name, name: db_name)
329
+ collation(db_config)
201
330
  end
202
331
 
203
- def collation(*arguments)
204
- configuration = arguments.first
205
- class_for_adapter(configuration["adapter"]).new(*arguments).collation
332
+ def collation(configuration, *arguments)
333
+ db_config = resolve_configuration(configuration)
334
+ database_adapter_for(db_config, *arguments).collation
206
335
  end
207
336
 
208
337
  def purge(configuration)
209
- class_for_adapter(configuration["adapter"]).new(configuration).purge
338
+ db_config = resolve_configuration(configuration)
339
+ database_adapter_for(db_config).purge
210
340
  end
211
341
 
212
342
  def purge_all
213
- each_local_configuration { |configuration|
214
- purge configuration
215
- }
343
+ each_local_configuration { |db_config| purge(db_config) }
216
344
  end
217
345
 
218
346
  def purge_current(environment = env)
219
- each_current_configuration(environment) { |configuration|
220
- purge configuration
221
- }
347
+ each_current_configuration(environment) { |db_config| purge(db_config) }
222
348
  ActiveRecord::Base.establish_connection(environment.to_sym)
223
349
  end
224
350
 
225
- def structure_dump(*arguments)
226
- configuration = arguments.first
227
- filename = arguments.delete_at 1
228
- class_for_adapter(configuration["adapter"]).new(*arguments).structure_dump(filename, structure_dump_flags)
351
+ def structure_dump(configuration, *arguments)
352
+ db_config = resolve_configuration(configuration)
353
+ filename = arguments.delete_at(0)
354
+ flags = structure_dump_flags_for(db_config.adapter)
355
+ database_adapter_for(db_config, *arguments).structure_dump(filename, flags)
229
356
  end
230
357
 
231
- def structure_load(*arguments)
232
- configuration = arguments.first
233
- filename = arguments.delete_at 1
234
- class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename, structure_load_flags)
358
+ def structure_load(configuration, *arguments)
359
+ db_config = resolve_configuration(configuration)
360
+ filename = arguments.delete_at(0)
361
+ flags = structure_load_flags_for(db_config.adapter)
362
+ database_adapter_for(db_config, *arguments).structure_load(filename, flags)
235
363
  end
236
364
 
237
- def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env) # :nodoc:
238
- file ||= schema_file(format)
365
+ def load_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
366
+ file ||= schema_dump_path(db_config, format)
239
367
 
368
+ verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
240
369
  check_schema_file(file)
241
- ActiveRecord::Base.establish_connection(configuration)
370
+ ActiveRecord::Base.establish_connection(db_config)
242
371
 
243
372
  case format
244
373
  when :ruby
245
374
  load(file)
246
375
  when :sql
247
- structure_load(configuration, file)
376
+ structure_load(db_config, file)
248
377
  else
249
378
  raise ArgumentError, "unknown format #{format.inspect}"
250
379
  end
251
380
  ActiveRecord::InternalMetadata.create_table
252
- ActiveRecord::InternalMetadata[:environment] = environment
381
+ ActiveRecord::InternalMetadata[:environment] = db_config.env_name
382
+ ActiveRecord::InternalMetadata[:schema_sha1] = schema_sha1(file)
383
+ ensure
384
+ Migration.verbose = verbose_was
385
+ end
386
+
387
+ def schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil)
388
+ db_config = resolve_configuration(configuration)
389
+
390
+ file ||= schema_dump_path(db_config)
391
+
392
+ return true unless File.exist?(file)
393
+
394
+ ActiveRecord::Base.establish_connection(db_config)
395
+
396
+ return false unless ActiveRecord::InternalMetadata.enabled?
397
+ return false unless ActiveRecord::InternalMetadata.table_exists?
398
+
399
+ ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
253
400
  end
254
401
 
255
- def schema_file(format = ActiveRecord::Base.schema_format)
402
+ def reconstruct_from_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
403
+ file ||= schema_dump_path(db_config, format)
404
+
405
+ check_schema_file(file)
406
+
407
+ ActiveRecord::Base.establish_connection(db_config)
408
+
409
+ if schema_up_to_date?(db_config, format, file)
410
+ truncate_tables(db_config)
411
+ else
412
+ purge(db_config)
413
+ load_schema(db_config, format, file)
414
+ end
415
+ rescue ActiveRecord::NoDatabaseError
416
+ create(db_config)
417
+ load_schema(db_config, format, file)
418
+ end
419
+
420
+ def dump_schema(db_config, format = ActiveRecord.schema_format) # :nodoc:
421
+ require "active_record/schema_dumper"
422
+ filename = schema_dump_path(db_config, format)
423
+ connection = ActiveRecord::Base.connection
424
+
425
+ FileUtils.mkdir_p(db_dir)
426
+ case format
427
+ when :ruby
428
+ File.open(filename, "w:utf-8") do |file|
429
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
430
+ end
431
+ when :sql
432
+ structure_dump(db_config, filename)
433
+ if connection.schema_migration.table_exists?
434
+ File.open(filename, "a") do |f|
435
+ f.puts connection.dump_schema_information
436
+ f.print "\n"
437
+ end
438
+ end
439
+ end
440
+ end
441
+
442
+ def schema_file_type(format = ActiveRecord.schema_format)
256
443
  case format
257
444
  when :ruby
258
- File.join(db_dir, "schema.rb")
445
+ "schema.rb"
259
446
  when :sql
260
- File.join(db_dir, "structure.sql")
447
+ "structure.sql"
448
+ end
449
+ end
450
+ deprecate :schema_file_type
451
+
452
+ def schema_dump_path(db_config, format = ActiveRecord.schema_format)
453
+ return ENV["SCHEMA"] if ENV["SCHEMA"]
454
+
455
+ filename = db_config.schema_dump(format)
456
+ return unless filename
457
+
458
+ if File.dirname(filename) == ActiveRecord::Tasks::DatabaseTasks.db_dir
459
+ filename
460
+ else
461
+ File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
261
462
  end
262
463
  end
263
464
 
264
- def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
265
- each_current_configuration(environment) { |configuration, configuration_environment|
266
- load_schema configuration, format, file, configuration_environment
267
- }
465
+ def cache_dump_filename(db_config_name, schema_cache_path: nil)
466
+ filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
467
+ "schema_cache.yml"
468
+ else
469
+ "#{db_config_name}_schema_cache.yml"
470
+ end
471
+
472
+ schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
473
+ end
474
+
475
+ def load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env)
476
+ each_current_configuration(environment) do |db_config|
477
+ load_schema(db_config, format, file)
478
+ end
268
479
  ActiveRecord::Base.establish_connection(environment.to_sym)
269
480
  end
270
481
 
271
482
  def check_schema_file(filename)
272
483
  unless File.exist?(filename)
273
- message = %{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}.dup
484
+ message = +%{#{filename} doesn't exist yet. Run `bin/rails db:migrate` to create it, then try again.}
274
485
  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)
275
486
  Kernel.abort message
276
487
  end
@@ -291,46 +502,93 @@ module ActiveRecord
291
502
  # ==== Examples:
292
503
  # ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
293
504
  def dump_schema_cache(conn, filename)
294
- conn.schema_cache.clear!
295
- conn.data_sources.each { |table| conn.schema_cache.add(table) }
296
- open(filename, "wb") { |f| f.write(YAML.dump(conn.schema_cache)) }
505
+ conn.schema_cache.dump_to(filename)
506
+ end
507
+
508
+ def clear_schema_cache(filename)
509
+ FileUtils.rm_f filename, verbose: false
297
510
  end
298
511
 
299
512
  private
513
+ def configs_for(**options)
514
+ Base.configurations.configs_for(**options)
515
+ end
516
+
517
+ def resolve_configuration(configuration)
518
+ Base.configurations.resolve(configuration)
519
+ end
520
+
521
+ def verbose?
522
+ ENV["VERBOSE"] ? ENV["VERBOSE"] != "false" : true
523
+ end
524
+
525
+ # Create a new instance for the specified db configuration object
526
+ # For classes that have been converted to use db_config objects, pass a
527
+ # `DatabaseConfig`, otherwise pass a `Hash`
528
+ def database_adapter_for(db_config, *arguments)
529
+ klass = class_for_adapter(db_config.adapter)
530
+ converted = klass.respond_to?(:using_database_configurations?) && klass.using_database_configurations?
531
+
532
+ config = converted ? db_config : db_config.configuration_hash
533
+ klass.new(config, *arguments)
534
+ end
300
535
 
301
536
  def class_for_adapter(adapter)
302
- _key, task = @tasks.each_pair.detect { |pattern, _task| adapter[pattern] }
537
+ _key, task = @tasks.reverse_each.detect { |pattern, _task| adapter[pattern] }
303
538
  unless task
304
539
  raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
305
540
  end
306
541
  task.is_a?(String) ? task.constantize : task
307
542
  end
308
543
 
309
- def each_current_configuration(environment)
544
+ def each_current_configuration(environment, name = nil)
310
545
  environments = [environment]
311
- environments << "test" if environment == "development"
546
+ environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
312
547
 
313
- ActiveRecord::Base.configurations.slice(*environments).each do |configuration_environment, configuration|
314
- next unless configuration["database"]
548
+ environments.each do |env|
549
+ configs_for(env_name: env).each do |db_config|
550
+ next if name && name != db_config.name
315
551
 
316
- yield configuration, configuration_environment
552
+ yield db_config
553
+ end
317
554
  end
318
555
  end
319
556
 
320
557
  def each_local_configuration
321
- ActiveRecord::Base.configurations.each_value do |configuration|
322
- next unless configuration["database"]
558
+ configs_for.each do |db_config|
559
+ next unless db_config.database
323
560
 
324
- if local_database?(configuration)
325
- yield configuration
561
+ if local_database?(db_config)
562
+ yield db_config
326
563
  else
327
- $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
564
+ $stderr.puts "This task only modifies local databases. #{db_config.database} is on a remote host."
328
565
  end
329
566
  end
330
567
  end
331
568
 
332
- def local_database?(configuration)
333
- configuration["host"].blank? || LOCAL_HOSTS.include?(configuration["host"])
569
+ def local_database?(db_config)
570
+ host = db_config.host
571
+ host.blank? || LOCAL_HOSTS.include?(host)
572
+ end
573
+
574
+ def schema_sha1(file)
575
+ OpenSSL::Digest::SHA1.hexdigest(File.read(file))
576
+ end
577
+
578
+ def structure_dump_flags_for(adapter)
579
+ if structure_dump_flags.is_a?(Hash)
580
+ structure_dump_flags[adapter.to_sym]
581
+ else
582
+ structure_dump_flags
583
+ end
584
+ end
585
+
586
+ def structure_load_flags_for(adapter)
587
+ if structure_load_flags.is_a?(Hash)
588
+ structure_load_flags[adapter.to_sym]
589
+ else
590
+ structure_load_flags
591
+ end
334
592
  end
335
593
  end
336
594
  end