activerecord 4.2.9 → 6.1.4.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 (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +964 -1382
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +266 -251
  8. data/lib/active_record/association_relation.rb +40 -15
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +162 -69
  11. data/lib/active_record/associations/association_scope.rb +105 -130
  12. data/lib/active_record/associations/belongs_to_association.rb +83 -65
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -37
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +49 -66
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +148 -287
  22. data/lib/active_record/associations/collection_proxy.rb +252 -150
  23. data/lib/active_record/associations/foreign_association.rb +23 -1
  24. data/lib/active_record/associations/has_many_association.rb +56 -98
  25. data/lib/active_record/associations/has_many_through_association.rb +68 -89
  26. data/lib/active_record/associations/has_one_association.rb +73 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -81
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +174 -169
  32. data/lib/active_record/associations/preloader/association.rb +108 -115
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +97 -94
  35. data/lib/active_record/associations/singular_association.rb +18 -39
  36. data/lib/active_record/associations/through_association.rb +39 -19
  37. data/lib/active_record/associations.rb +1845 -1598
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +18 -10
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -148
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +55 -36
  46. data/lib/active_record/attribute_methods/write.rb +24 -55
  47. data/lib/active_record/attribute_methods.rb +149 -154
  48. data/lib/active_record/attributes.rb +234 -78
  49. data/lib/active_record/autosave_association.rb +133 -60
  50. data/lib/active_record/base.rb +46 -46
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +34 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -323
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +292 -124
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +177 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +8 -6
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +473 -255
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +869 -286
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +257 -91
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +483 -230
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +557 -640
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +194 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +80 -192
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +75 -160
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -58
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -19
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +145 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +496 -298
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +588 -375
  119. data/lib/active_record/connection_adapters/schema_cache.rb +167 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -373
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +458 -241
  133. data/lib/active_record/counter_cache.rb +70 -49
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +272 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +211 -92
  143. data/lib/active_record/errors.rb +224 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +10 -5
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +275 -500
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +62 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +27 -5
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +98 -92
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +295 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +673 -325
  170. data/lib/active_record/model_schema.rb +418 -113
  171. data/lib/active_record/nested_attributes.rb +263 -224
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +572 -136
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +170 -51
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +523 -199
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +454 -291
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +324 -249
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +316 -242
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +95 -103
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -26
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +136 -122
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -413
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +18 -20
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -343
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -23
  209. data/lib/active_record/scoping/default.rb +96 -83
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +128 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +364 -130
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +67 -113
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +86 -49
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +287 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +182 -163
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -45
  231. data/lib/active_record/type/date_time.rb +4 -49
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +27 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +63 -56
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +42 -29
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -4
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  339. data/lib/rails/generators/active_record.rb +7 -5
  340. metadata +172 -65
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  343. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  344. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  345. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  348. data/lib/active_record/attribute.rb +0 -163
  349. data/lib/active_record/attribute_decorators.rb +0 -66
  350. data/lib/active_record/attribute_set/builder.rb +0 -106
  351. data/lib/active_record/attribute_set.rb +0 -81
  352. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  353. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  354. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  355. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  356. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  357. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  358. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  359. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  360. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  361. data/lib/active_record/type/big_integer.rb +0 -13
  362. data/lib/active_record/type/binary.rb +0 -50
  363. data/lib/active_record/type/boolean.rb +0 -31
  364. data/lib/active_record/type/decimal.rb +0 -64
  365. data/lib/active_record/type/decorator.rb +0 -14
  366. data/lib/active_record/type/float.rb +0 -19
  367. data/lib/active_record/type/integer.rb +0 -59
  368. data/lib/active_record/type/mutable.rb +0 -16
  369. data/lib/active_record/type/numeric.rb +0 -36
  370. data/lib/active_record/type/string.rb +0 -40
  371. data/lib/active_record/type/time_value.rb +0 -38
  372. data/lib/active_record/type/value.rb +0 -110
  373. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
  374. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,214 +1,439 @@
1
- require 'active_record'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+ require "active_support/configuration_file"
5
+ require "active_support/deprecation"
6
+
7
+ databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
2
8
 
3
9
  db_namespace = namespace :db do
4
- task :load_config do
5
- ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration || {}
10
+ desc "Set the environment value for the database"
11
+ task "environment:set" => :load_config do
12
+ raise ActiveRecord::EnvironmentStorageError unless ActiveRecord::InternalMetadata.enabled?
13
+ ActiveRecord::InternalMetadata.create_table
14
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
15
+ end
16
+
17
+ task check_protected_environments: :load_config do
18
+ ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
19
+ end
20
+
21
+ task load_config: :environment do
22
+ if ActiveRecord::Base.configurations.empty?
23
+ ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration
24
+ end
25
+
6
26
  ActiveRecord::Migrator.migrations_paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
7
27
  end
8
28
 
9
29
  namespace :create do
10
- task :all => :load_config do
30
+ task all: :load_config do
11
31
  ActiveRecord::Tasks::DatabaseTasks.create_all
12
32
  end
33
+
34
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
35
+ desc "Create #{name} database for current environment"
36
+ task name => :load_config do
37
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
38
+ ActiveRecord::Tasks::DatabaseTasks.create(db_config)
39
+ end
40
+ end
13
41
  end
14
42
 
15
- desc 'Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config). Without RAILS_ENV it defaults to creating the development and test databases.'
16
- task :create => [:load_config] do
43
+ desc "Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config). Without RAILS_ENV or when RAILS_ENV is development, it defaults to creating the development and test databases, except when DATABASE_URL is present."
44
+ task create: [:load_config] do
17
45
  ActiveRecord::Tasks::DatabaseTasks.create_current
18
46
  end
19
47
 
20
48
  namespace :drop do
21
- task :all => :load_config do
49
+ task all: [:load_config, :check_protected_environments] do
22
50
  ActiveRecord::Tasks::DatabaseTasks.drop_all
23
51
  end
52
+
53
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
54
+ desc "Drop #{name} database for current environment"
55
+ task name => [:load_config, :check_protected_environments] do
56
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
57
+ ActiveRecord::Tasks::DatabaseTasks.drop(db_config)
58
+ end
59
+ end
24
60
  end
25
61
 
26
- desc 'Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV it defaults to dropping the development and test databases.'
27
- task :drop => [:load_config] do
62
+ desc "Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV or when RAILS_ENV is development, it defaults to dropping the development and test databases, except when DATABASE_URL is present."
63
+ task drop: [:load_config, :check_protected_environments] do
64
+ db_namespace["drop:_unsafe"].invoke
65
+ end
66
+
67
+ task "drop:_unsafe" => [:load_config] do
28
68
  ActiveRecord::Tasks::DatabaseTasks.drop_current
29
69
  end
30
70
 
31
71
  namespace :purge do
32
- task :all => :load_config do
72
+ task all: [:load_config, :check_protected_environments] do
33
73
  ActiveRecord::Tasks::DatabaseTasks.purge_all
34
74
  end
35
75
  end
36
76
 
37
- # desc "Empty the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV it defaults to purging the development and test databases."
38
- task :purge => [:load_config] do
77
+ # desc "Truncates tables of each database for current environment"
78
+ task truncate_all: [:load_config, :check_protected_environments] do
79
+ ActiveRecord::Tasks::DatabaseTasks.truncate_all
80
+ end
81
+
82
+ # desc "Empty the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:purge:all to purge all databases in the config). Without RAILS_ENV it defaults to purging the development and test databases, except when DATABASE_URL is present."
83
+ task purge: [:load_config, :check_protected_environments] do
39
84
  ActiveRecord::Tasks::DatabaseTasks.purge_current
40
85
  end
41
86
 
42
87
  desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
43
- task :migrate => [:environment, :load_config] do
44
- ActiveRecord::Tasks::DatabaseTasks.migrate
45
- db_namespace['_dump'].invoke
88
+ task migrate: :load_config do
89
+ original_db_config = ActiveRecord::Base.connection_db_config
90
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
91
+ ActiveRecord::Base.establish_connection(db_config)
92
+ ActiveRecord::Tasks::DatabaseTasks.migrate
93
+ end
94
+ db_namespace["_dump"].invoke
95
+ ensure
96
+ ActiveRecord::Base.establish_connection(original_db_config)
46
97
  end
47
98
 
48
99
  # IMPORTANT: This task won't dump the schema if ActiveRecord::Base.dump_schema_after_migration is set to false
49
100
  task :_dump do
50
101
  if ActiveRecord::Base.dump_schema_after_migration
51
- case ActiveRecord::Base.schema_format
52
- when :ruby then db_namespace["schema:dump"].invoke
53
- when :sql then db_namespace["structure:dump"].invoke
54
- else
55
- raise "unknown schema format #{ActiveRecord::Base.schema_format}"
56
- end
102
+ db_namespace["schema:dump"].invoke
57
103
  end
58
104
  # Allow this task to be called as many times as required. An example is the
59
105
  # migrate:redo task, which calls other two internally that depend on this one.
60
- db_namespace['_dump'].reenable
106
+ db_namespace["_dump"].reenable
107
+ end
108
+
109
+ namespace :_dump do
110
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
111
+ # IMPORTANT: This task won't dump the schema if ActiveRecord::Base.dump_schema_after_migration is set to false
112
+ task name do
113
+ if ActiveRecord::Base.dump_schema_after_migration
114
+ db_namespace["schema:dump:#{name}"].invoke
115
+ end
116
+ # Allow this task to be called as many times as required. An example is the
117
+ # migrate:redo task, which calls other two internally that depend on this one.
118
+ db_namespace["_dump:#{name}"].reenable
119
+ end
120
+ end
61
121
  end
62
122
 
63
123
  namespace :migrate do
64
- # desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
65
- task :redo => [:environment, :load_config] do
124
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
125
+ desc "Migrate #{name} database for current environment"
126
+ task name => :load_config do
127
+ original_db_config = ActiveRecord::Base.connection_db_config
128
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
129
+ ActiveRecord::Base.establish_connection(db_config)
130
+ ActiveRecord::Tasks::DatabaseTasks.migrate
131
+ db_namespace["_dump:#{name}"].invoke
132
+ ensure
133
+ ActiveRecord::Base.establish_connection(original_db_config)
134
+ end
135
+ end
136
+
137
+ desc "Rolls back the database one migration and re-migrates up (options: STEP=x, VERSION=x)."
138
+ task redo: :load_config do
139
+ ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:redo")
140
+
66
141
  raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
67
142
 
68
- if ENV['VERSION']
69
- db_namespace['migrate:down'].invoke
70
- db_namespace['migrate:up'].invoke
143
+ if ENV["VERSION"]
144
+ db_namespace["migrate:down"].invoke
145
+ db_namespace["migrate:up"].invoke
71
146
  else
72
- db_namespace['rollback'].invoke
73
- db_namespace['migrate'].invoke
147
+ db_namespace["rollback"].invoke
148
+ db_namespace["migrate"].invoke
149
+ end
150
+ end
151
+
152
+ namespace :redo do
153
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
154
+ desc "Rolls back #{name} database one migration and re-migrates up (options: STEP=x, VERSION=x)."
155
+ task name => :load_config do
156
+ raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
157
+
158
+ if ENV["VERSION"]
159
+ db_namespace["migrate:down:#{name}"].invoke
160
+ db_namespace["migrate:up:#{name}"].invoke
161
+ else
162
+ db_namespace["rollback:#{name}"].invoke
163
+ db_namespace["migrate:#{name}"].invoke
164
+ end
165
+ end
74
166
  end
75
167
  end
76
168
 
77
169
  # desc 'Resets your database using your migrations for the current environment'
78
- task :reset => ['db:drop', 'db:create', 'db:migrate']
170
+ task reset: ["db:drop", "db:create", "db:migrate"]
79
171
 
80
- # desc 'Runs the "up" for a given migration VERSION.'
81
- task :up => [:environment, :load_config] do
82
- raise "VERSION is required" if ENV["VERSION"] && ENV["VERSION"].empty?
172
+ desc 'Runs the "up" for a given migration VERSION.'
173
+ task up: :load_config do
174
+ ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:up")
83
175
 
84
- version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
85
- ActiveRecord::Migrator.run(:up, ActiveRecord::Migrator.migrations_paths, version)
86
- db_namespace['_dump'].invoke
176
+ raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
177
+
178
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
179
+
180
+ ActiveRecord::Base.connection.migration_context.run(
181
+ :up,
182
+ ActiveRecord::Tasks::DatabaseTasks.target_version
183
+ )
184
+ db_namespace["_dump"].invoke
185
+ end
186
+
187
+ namespace :up do
188
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
189
+ task name => :load_config do
190
+ raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
191
+
192
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
193
+
194
+ ActiveRecord::Base.establish_connection(db_config)
195
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
196
+ ActiveRecord::Base.connection.migration_context.run(
197
+ :up,
198
+ ActiveRecord::Tasks::DatabaseTasks.target_version
199
+ )
200
+
201
+ db_namespace["_dump"].invoke
202
+ end
203
+ end
204
+ end
205
+
206
+ desc 'Runs the "down" for a given migration VERSION.'
207
+ task down: :load_config do
208
+ ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:down")
209
+
210
+ raise "VERSION is required - To go down one migration, use db:rollback" if !ENV["VERSION"] || ENV["VERSION"].empty?
211
+
212
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
213
+
214
+ ActiveRecord::Base.connection.migration_context.run(
215
+ :down,
216
+ ActiveRecord::Tasks::DatabaseTasks.target_version
217
+ )
218
+ db_namespace["_dump"].invoke
219
+ end
220
+
221
+ namespace :down do
222
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
223
+ task name => :load_config do
224
+ raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
225
+
226
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
227
+
228
+ ActiveRecord::Base.establish_connection(db_config)
229
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
230
+ ActiveRecord::Base.connection.migration_context.run(
231
+ :down,
232
+ ActiveRecord::Tasks::DatabaseTasks.target_version
233
+ )
234
+
235
+ db_namespace["_dump"].invoke
236
+ end
237
+ end
87
238
  end
88
239
 
89
- # desc 'Runs the "down" for a given migration VERSION.'
90
- task :down => [:environment, :load_config] do
91
- raise "VERSION is required - To go down one migration, use db:rollback" if ENV["VERSION"] && ENV["VERSION"].empty?
92
- version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
93
- ActiveRecord::Migrator.run(:down, ActiveRecord::Migrator.migrations_paths, version)
94
- db_namespace['_dump'].invoke
240
+ desc "Display status of migrations"
241
+ task status: :load_config do
242
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
243
+ ActiveRecord::Base.establish_connection(db_config)
244
+ ActiveRecord::Tasks::DatabaseTasks.migrate_status
245
+ end
95
246
  end
96
247
 
97
- desc 'Display status of migrations'
98
- task :status => [:environment, :load_config] do
99
- unless ActiveRecord::SchemaMigration.table_exists?
100
- abort 'Schema migrations table does not exist yet.'
248
+ namespace :status do
249
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
250
+ desc "Display status of migrations for #{name} database"
251
+ task name => :load_config do
252
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
253
+ ActiveRecord::Base.establish_connection(db_config)
254
+ ActiveRecord::Tasks::DatabaseTasks.migrate_status
255
+ end
101
256
  end
257
+ end
258
+ end
259
+
260
+ namespace :rollback do
261
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
262
+ desc "Rollback #{name} database for current environment (specify steps w/ STEP=n)."
263
+ task name => :load_config do
264
+ step = ENV["STEP"] ? ENV["STEP"].to_i : 1
265
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
266
+
267
+ ActiveRecord::Base.establish_connection(db_config)
268
+ ActiveRecord::Base.connection.migration_context.rollback(step)
102
269
 
103
- # output
104
- puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
105
- puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
106
- puts "-" * 50
107
- paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
108
- ActiveRecord::Migrator.migrations_status(paths).each do |status, version, name|
109
- puts "#{status.center(8)} #{version.ljust(14)} #{name}"
270
+ db_namespace["_dump"].invoke
110
271
  end
111
- puts
112
272
  end
113
273
  end
114
274
 
115
- desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).'
116
- task :rollback => [:environment, :load_config] do
117
- step = ENV['STEP'] ? ENV['STEP'].to_i : 1
118
- ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step)
119
- db_namespace['_dump'].invoke
275
+ desc "Rolls the schema back to the previous version (specify steps w/ STEP=n)."
276
+ task rollback: :load_config do
277
+ ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:rollback")
278
+
279
+ step = ENV["STEP"] ? ENV["STEP"].to_i : 1
280
+
281
+ ActiveRecord::Base.connection.migration_context.rollback(step)
282
+
283
+ db_namespace["_dump"].invoke
120
284
  end
121
285
 
122
286
  # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
123
- task :forward => [:environment, :load_config] do
124
- step = ENV['STEP'] ? ENV['STEP'].to_i : 1
125
- ActiveRecord::Migrator.forward(ActiveRecord::Migrator.migrations_paths, step)
126
- db_namespace['_dump'].invoke
287
+ task forward: :load_config do
288
+ step = ENV["STEP"] ? ENV["STEP"].to_i : 1
289
+ ActiveRecord::Base.connection.migration_context.forward(step)
290
+ db_namespace["_dump"].invoke
127
291
  end
128
292
 
129
- # desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
130
- task :reset => [:environment, :load_config] do
131
- db_namespace["drop"].invoke
132
- db_namespace["setup"].invoke
133
- end
293
+ desc "Drops and recreates the database from db/schema.rb for the current environment and loads the seeds."
294
+ task reset: [ "db:drop", "db:setup" ]
134
295
 
135
296
  # desc "Retrieves the charset for the current environment's database"
136
- task :charset => [:environment, :load_config] do
297
+ task charset: :load_config do
137
298
  puts ActiveRecord::Tasks::DatabaseTasks.charset_current
138
299
  end
139
300
 
140
301
  # desc "Retrieves the collation for the current environment's database"
141
- task :collation => [:environment, :load_config] do
142
- begin
143
- puts ActiveRecord::Tasks::DatabaseTasks.collation_current
144
- rescue NoMethodError
145
- $stderr.puts 'Sorry, your database adapter is not supported yet. Feel free to submit a patch.'
146
- end
302
+ task collation: :load_config do
303
+ puts ActiveRecord::Tasks::DatabaseTasks.collation_current
304
+ rescue NoMethodError
305
+ $stderr.puts "Sorry, your database adapter is not supported yet. Feel free to submit a patch."
147
306
  end
148
307
 
149
- desc 'Retrieves the current schema version number'
150
- task :version => [:environment, :load_config] do
151
- puts "Current version: #{ActiveRecord::Migrator.current_version}"
308
+ desc "Retrieves the current schema version number"
309
+ task version: :load_config do
310
+ puts "Current version: #{ActiveRecord::Base.connection.migration_context.current_version}"
152
311
  end
153
312
 
154
313
  # desc "Raises an error if there are pending migrations"
155
- task :abort_if_pending_migrations => :environment do
156
- pending_migrations = ActiveRecord::Migrator.open(ActiveRecord::Migrator.migrations_paths).pending_migrations
314
+ task abort_if_pending_migrations: :load_config do
315
+ pending_migrations = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).flat_map do |db_config|
316
+ ActiveRecord::Base.establish_connection(db_config)
317
+
318
+ ActiveRecord::Base.connection.migration_context.open.pending_migrations
319
+ end
157
320
 
158
321
  if pending_migrations.any?
159
322
  puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
160
323
  pending_migrations.each do |pending_migration|
161
- puts ' %4d %s' % [pending_migration.version, pending_migration.name]
324
+ puts " %4d %s" % [pending_migration.version, pending_migration.name]
162
325
  end
163
- abort %{Run `rake db:migrate` to update your database then try again.}
326
+ abort %{Run `bin/rails db:migrate` to update your database then try again.}
164
327
  end
328
+ ensure
329
+ ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
165
330
  end
166
331
 
167
- desc 'Create the database, load the schema, and initialize with the seed data (use db:reset to also drop the database first)'
168
- task :setup => ['db:schema:load_if_ruby', 'db:structure:load_if_sql', :seed]
332
+ namespace :abort_if_pending_migrations do
333
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
334
+ # desc "Raises an error if there are pending migrations for #{name} database"
335
+ task name => :load_config do
336
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
337
+ ActiveRecord::Base.establish_connection(db_config)
169
338
 
170
- desc 'Load the seed data from db/seeds.rb'
171
- task :seed do
172
- db_namespace['abort_if_pending_migrations'].invoke
339
+ pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
340
+
341
+ if pending_migrations.any?
342
+ puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
343
+ pending_migrations.each do |pending_migration|
344
+ puts " %4d %s" % [pending_migration.version, pending_migration.name]
345
+ end
346
+ abort %{Run `bin/rails db:migrate:#{name}` to update your database then try again.}
347
+ end
348
+ end
349
+ end
350
+ end
351
+
352
+ desc "Creates the database, loads the schema, and initializes with the seed data (use db:reset to also drop the database first)"
353
+ task setup: ["db:create", :environment, "db:schema:load", :seed]
354
+
355
+ desc "Runs setup if database does not exist, or runs migrations if it does"
356
+ task prepare: :load_config do
357
+ seed = false
358
+
359
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
360
+ ActiveRecord::Base.establish_connection(db_config)
361
+
362
+ # Skipped when no database
363
+ ActiveRecord::Tasks::DatabaseTasks.migrate
364
+
365
+ if ActiveRecord::Base.dump_schema_after_migration
366
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, ActiveRecord::Base.schema_format)
367
+ end
368
+ rescue ActiveRecord::NoDatabaseError
369
+ config_name = db_config.name
370
+ ActiveRecord::Tasks::DatabaseTasks.create_current(db_config.env_name, config_name)
371
+
372
+ if File.exist?(ActiveRecord::Tasks::DatabaseTasks.dump_filename(config_name))
373
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(
374
+ db_config,
375
+ ActiveRecord::Base.schema_format,
376
+ nil
377
+ )
378
+ else
379
+ ActiveRecord::Tasks::DatabaseTasks.migrate
380
+ end
381
+
382
+ seed = true
383
+ end
384
+
385
+ ActiveRecord::Base.establish_connection
386
+ ActiveRecord::Tasks::DatabaseTasks.load_seed if seed
387
+ end
388
+
389
+ desc "Loads the seed data from db/seeds.rb"
390
+ task seed: :load_config do
391
+ db_namespace["abort_if_pending_migrations"].invoke
173
392
  ActiveRecord::Tasks::DatabaseTasks.load_seed
174
393
  end
175
394
 
395
+ namespace :seed do
396
+ desc "Truncates tables of each database for current environment and loads the seeds"
397
+ task replant: [:load_config, :truncate_all, :seed]
398
+ end
399
+
176
400
  namespace :fixtures do
177
- desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
178
- task :load => [:environment, :load_config] do
179
- require 'active_record/fixtures'
401
+ desc "Loads fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (e.g. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
402
+ task load: :load_config do
403
+ require "active_record/fixtures"
180
404
 
181
405
  base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
182
406
 
183
- fixtures_dir = if ENV['FIXTURES_DIR']
184
- File.join base_dir, ENV['FIXTURES_DIR']
185
- else
186
- base_dir
187
- end
407
+ fixtures_dir = if ENV["FIXTURES_DIR"]
408
+ File.join base_dir, ENV["FIXTURES_DIR"]
409
+ else
410
+ base_dir
411
+ end
188
412
 
189
- fixture_files = if ENV['FIXTURES']
190
- ENV['FIXTURES'].split(',')
191
- else
192
- # The use of String#[] here is to support namespaced fixtures
193
- Dir["#{fixtures_dir}/**/*.yml"].map {|f| f[(fixtures_dir.size + 1)..-5] }
194
- end
413
+ fixture_files = if ENV["FIXTURES"]
414
+ ENV["FIXTURES"].split(",")
415
+ else
416
+ files = Dir[File.join(fixtures_dir, "**/*.{yml}")]
417
+ files.reject! { |f| f.start_with?(File.join(fixtures_dir, "files")) }
418
+ files.map! { |f| f[fixtures_dir.to_s.size..-5].delete_prefix("/") }
419
+ end
195
420
 
196
421
  ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, fixture_files)
197
422
  end
198
423
 
199
- # desc "Search for a fixture given a LABEL or ID. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
200
- task :identify => [:environment, :load_config] do
201
- require 'active_record/fixtures'
424
+ # desc "Search for a fixture given a LABEL or ID. Specify an alternative path (e.g. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
425
+ task identify: :load_config do
426
+ require "active_record/fixtures"
202
427
 
203
- label, id = ENV['LABEL'], ENV['ID']
204
- raise 'LABEL or ID required' if label.blank? && id.blank?
428
+ label, id = ENV["LABEL"], ENV["ID"]
429
+ raise "LABEL or ID required" if label.blank? && id.blank?
205
430
 
206
431
  puts %Q(The fixture ID for "#{label}" is #{ActiveRecord::FixtureSet.identify(label)}.) if label
207
432
 
208
433
  base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
209
434
 
210
435
  Dir["#{base_dir}/**/*.yml"].each do |file|
211
- if data = YAML::load(ERB.new(IO.read(file)).result)
436
+ if data = ActiveSupport::ConfigurationFile.parse(file)
212
437
  data.each_key do |key|
213
438
  key_id = ActiveRecord::FixtureSet.identify(key)
214
439
 
@@ -222,134 +447,229 @@ db_namespace = namespace :db do
222
447
  end
223
448
 
224
449
  namespace :schema do
225
- desc 'Create a db/schema.rb file that is portable against any DB supported by AR'
226
- task :dump => [:environment, :load_config] do
227
- require 'active_record/schema_dumper'
228
- filename = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb')
229
- File.open(filename, "w:utf-8") do |file|
230
- ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
450
+ desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`)"
451
+ task dump: :load_config do
452
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
453
+ ActiveRecord::Base.establish_connection(db_config)
454
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config)
231
455
  end
232
- db_namespace['schema:dump'].reenable
456
+
457
+ db_namespace["schema:dump"].reenable
233
458
  end
234
459
 
235
- desc 'Load a schema.rb file into the database'
236
- task :load => [:environment, :load_config] do
237
- ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV['SCHEMA'])
460
+ desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the database"
461
+ task load: [:load_config, :check_protected_environments] do
462
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord::Base.schema_format, ENV["SCHEMA"])
238
463
  end
239
464
 
240
- task :load_if_ruby => ['db:create', :environment] do
465
+ task load_if_ruby: ["db:create", :environment] do
466
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
467
+ Using `bin/rails db:schema:load_if_ruby` is deprecated and will be removed in Rails 6.2.
468
+ Configure the format using `config.active_record.schema_format = :ruby` to use `schema.rb` and run `bin/rails db:schema:load` instead.
469
+ MSG
241
470
  db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :ruby
242
471
  end
243
472
 
244
- namespace :cache do
245
- desc 'Create a db/schema_cache.dump file.'
246
- task :dump => [:environment, :load_config] do
247
- con = ActiveRecord::Base.connection
248
- filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
249
-
250
- con.schema_cache.clear!
251
- con.tables.each { |table| con.schema_cache.add(table) }
252
- open(filename, 'wb') { |f| f.write(Marshal.dump(con.schema_cache)) }
473
+ namespace :dump do
474
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
475
+ desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) for #{name} database"
476
+ task name => :load_config do
477
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
478
+ ActiveRecord::Base.establish_connection(db_config)
479
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config)
480
+ db_namespace["schema:dump:#{name}"].reenable
481
+ end
253
482
  end
483
+ end
254
484
 
255
- desc 'Clear a db/schema_cache.dump file.'
256
- task :clear => [:environment, :load_config] do
257
- filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
258
- FileUtils.rm(filename) if File.exist?(filename)
485
+ namespace :load do
486
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
487
+ desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the #{name} database"
488
+ task name => :load_config do
489
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
490
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord::Base.schema_format, ENV["SCHEMA"])
491
+ end
259
492
  end
260
493
  end
261
494
 
262
- end
495
+ namespace :cache do
496
+ desc "Creates a db/schema_cache.yml file."
497
+ task dump: :load_config do
498
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
499
+ ActiveRecord::Base.establish_connection(db_config)
500
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
501
+ db_config.name,
502
+ schema_cache_path: db_config.schema_cache_path,
503
+ )
504
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(
505
+ ActiveRecord::Base.connection,
506
+ filename,
507
+ )
508
+ end
509
+ end
263
510
 
264
- namespace :structure do
265
- desc 'Dump the database structure to db/structure.sql. Specify another file with DB_STRUCTURE=db/my_structure.sql'
266
- task :dump => [:environment, :load_config] do
267
- filename = ENV['DB_STRUCTURE'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
268
- current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
269
- ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
270
-
271
- if ActiveRecord::Base.connection.supports_migrations? &&
272
- ActiveRecord::SchemaMigration.table_exists?
273
- File.open(filename, "a") do |f|
274
- f.puts ActiveRecord::Base.connection.dump_schema_information
275
- f.print "\n"
511
+ desc "Clears a db/schema_cache.yml file."
512
+ task clear: :load_config do
513
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
514
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
515
+ db_config.name,
516
+ schema_cache_path: db_config.schema_cache_path,
517
+ )
518
+ ActiveRecord::Tasks::DatabaseTasks.clear_schema_cache(
519
+ filename,
520
+ )
276
521
  end
277
522
  end
278
- db_namespace['structure:dump'].reenable
279
523
  end
524
+ end
280
525
 
281
- desc "Recreate the databases from the structure.sql file"
282
- task :load => [:load_config] do
283
- ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV['DB_STRUCTURE'])
526
+ namespace :structure do
527
+ desc "Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
528
+ task dump: :load_config do
529
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
530
+ Using `bin/rails db:structure:dump` is deprecated and will be removed in Rails 6.2.
531
+ Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump` instead.
532
+ MSG
533
+
534
+ db_namespace["schema:dump"].invoke
535
+ db_namespace["structure:dump"].reenable
284
536
  end
285
537
 
286
- task :load_if_sql => ['db:create', :environment] do
287
- db_namespace["structure:load"].invoke if ActiveRecord::Base.schema_format == :sql
538
+ desc "Recreates the databases from the structure.sql file"
539
+ task load: [:load_config, :check_protected_environments] do
540
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
541
+ Using `bin/rails db:structure:load` is deprecated and will be removed in Rails 6.2.
542
+ Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
543
+ MSG
544
+ db_namespace["schema:load"].invoke
288
545
  end
289
- end
290
-
291
- namespace :test do
292
546
 
293
- task :deprecated do
294
- Rake.application.top_level_tasks.grep(/^db:test:/).each do |task|
295
- $stderr.puts "WARNING: #{task} is deprecated. The Rails test helper now maintains " \
296
- "your test schema automatically, see the release notes for details."
297
- end
547
+ task load_if_sql: ["db:create", :environment] do
548
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
549
+ Using `bin/rails db:structure:load_if_sql` is deprecated and will be removed in Rails 6.2.
550
+ Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
551
+ MSG
552
+ db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :sql
298
553
  end
299
554
 
300
- # desc "Recreate the test database from the current schema"
301
- task :load => %w(db:test:purge) do
302
- case ActiveRecord::Base.schema_format
303
- when :ruby
304
- db_namespace["test:load_schema"].invoke
305
- when :sql
306
- db_namespace["test:load_structure"].invoke
555
+ namespace :dump do
556
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
557
+ desc "Dumps the #{name} database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
558
+ task name => :load_config do
559
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
560
+ Using `bin/rails db:structure:dump:#{name}` is deprecated and will be removed in Rails 6.2.
561
+ Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump:#{name}` instead.
562
+ MSG
563
+ db_namespace["schema:dump:#{name}"].invoke
564
+ db_namespace["structure:dump:#{name}"].reenable
565
+ end
307
566
  end
308
567
  end
309
568
 
310
- # desc "Recreate the test database from an existent schema.rb file"
311
- task :load_schema => %w(db:test:purge) do
312
- begin
313
- should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
314
- ActiveRecord::Schema.verbose = false
315
- ActiveRecord::Tasks::DatabaseTasks.load_schema_for ActiveRecord::Base.configurations['test'], :ruby, ENV['SCHEMA']
316
- ensure
317
- if should_reconnect
318
- ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[ActiveRecord::Tasks::DatabaseTasks.env])
569
+ namespace :load do
570
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
571
+ desc "Recreates the #{name} database from the structure.sql file"
572
+ task name => :load_config do
573
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
574
+ Using `bin/rails db:structure:load:#{name}` is deprecated and will be removed in Rails 6.2.
575
+ Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load:#{name}` instead.
576
+ MSG
577
+ db_namespace["schema:load:#{name}"].invoke
319
578
  end
320
579
  end
321
580
  end
581
+ end
322
582
 
323
- # desc "Recreate the test database from an existent structure.sql file"
324
- task :load_structure => %w(db:test:purge) do
325
- ActiveRecord::Tasks::DatabaseTasks.load_schema_for ActiveRecord::Base.configurations['test'], :sql, ENV['SCHEMA']
583
+ namespace :test do
584
+ # desc "Recreate the test database from the current schema"
585
+ task load: %w(db:test:purge) do
586
+ db_namespace["test:load_schema"].invoke
326
587
  end
327
588
 
328
- # desc "Recreate the test database from a fresh schema"
329
- task :clone => %w(db:test:deprecated environment) do
330
- case ActiveRecord::Base.schema_format
331
- when :ruby
332
- db_namespace["test:clone_schema"].invoke
333
- when :sql
334
- db_namespace["test:clone_structure"].invoke
589
+ # desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on `config.active_record.schema_format`)"
590
+ task load_schema: %w(db:test:purge) do
591
+ should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
592
+ ActiveRecord::Schema.verbose = false
593
+ ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
594
+ filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.name)
595
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord::Base.schema_format, filename)
596
+ end
597
+ ensure
598
+ if should_reconnect
599
+ ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
335
600
  end
336
601
  end
337
602
 
338
- # desc "Recreate the test database from a fresh schema.rb file"
339
- task :clone_schema => %w(db:test:deprecated db:schema:dump db:test:load_schema)
340
-
341
- # desc "Recreate the test database from a fresh structure.sql file"
342
- task :clone_structure => %w(db:test:deprecated db:structure:dump db:test:load_structure)
603
+ # desc "Recreate the test database from an existent structure.sql file"
604
+ task load_structure: %w(db:test:purge) do
605
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
606
+ Using `bin/rails db:test:load_structure` is deprecated and will be removed in Rails 6.2.
607
+ Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_schema` instead.
608
+ MSG
609
+ db_namespace["test:load_schema"].invoke
610
+ end
343
611
 
344
612
  # desc "Empty the test database"
345
- task :purge => %w(environment load_config) do
346
- ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations['test']
613
+ task purge: %w(load_config check_protected_environments) do
614
+ ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
615
+ ActiveRecord::Tasks::DatabaseTasks.purge(db_config)
616
+ end
347
617
  end
348
618
 
349
- # desc 'Check for pending migrations and load the test schema'
350
- task :prepare => %w(environment load_config) do
619
+ # desc 'Load the test schema'
620
+ task prepare: :load_config do
351
621
  unless ActiveRecord::Base.configurations.blank?
352
- db_namespace['test:load'].invoke
622
+ db_namespace["test:load"].invoke
623
+ end
624
+ end
625
+
626
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
627
+ # desc "Recreate the #{name} test database"
628
+ namespace :load do
629
+ task name => "db:test:purge:#{name}" do
630
+ db_namespace["test:load_schema:#{name}"].invoke
631
+ end
632
+ end
633
+
634
+ # desc "Recreate the #{name} test database from an existent schema.rb file"
635
+ namespace :load_schema do
636
+ task name => "db:test:purge:#{name}" do
637
+ should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
638
+ ActiveRecord::Schema.verbose = false
639
+ filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(name)
640
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
641
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord::Base.schema_format, filename)
642
+ ensure
643
+ if should_reconnect
644
+ ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
645
+ end
646
+ end
647
+ end
648
+
649
+ # desc "Recreate the #{name} test database from an existent structure.sql file"
650
+ namespace :load_structure do
651
+ task name => "db:test:purge:#{name}" do
652
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
653
+ Using `bin/rails db:test:load_structure:#{name}` is deprecated and will be removed in Rails 6.2.
654
+ Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_structure:#{name}` instead.
655
+ MSG
656
+ db_namespace["test:load_schema:#{name}"].invoke
657
+ end
658
+ end
659
+
660
+ # desc "Empty the #{name} test database"
661
+ namespace :purge do
662
+ task name => %w(load_config check_protected_environments) do
663
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
664
+ ActiveRecord::Tasks::DatabaseTasks.purge(db_config)
665
+ end
666
+ end
667
+
668
+ # desc 'Load the #{name} database test schema'
669
+ namespace :prepare do
670
+ task name => :load_config do
671
+ db_namespace["test:load:#{name}"].invoke
672
+ end
353
673
  end
354
674
  end
355
675
  end
@@ -358,15 +678,19 @@ end
358
678
  namespace :railties do
359
679
  namespace :install do
360
680
  # desc "Copies missing migrations from Railties (e.g. engines). You can specify Railties to use with FROM=railtie1,railtie2"
361
- task :migrations => :'db:load_config' do
362
- to_load = ENV['FROM'].blank? ? :all : ENV['FROM'].split(",").map {|n| n.strip }
681
+ task migrations: :'db:load_config' do
682
+ to_load = ENV["FROM"].blank? ? :all : ENV["FROM"].split(",").map(&:strip)
363
683
  railties = {}
364
684
  Rails.application.migration_railties.each do |railtie|
365
685
  next unless to_load == :all || to_load.include?(railtie.railtie_name)
366
686
 
367
- if railtie.respond_to?(:paths) && (path = railtie.paths['db/migrate'].first)
687
+ if railtie.respond_to?(:paths) && (path = railtie.paths["db/migrate"].first)
368
688
  railties[railtie.railtie_name] = path
369
689
  end
690
+
691
+ unless ENV["MIGRATIONS_PATH"].blank?
692
+ railties[railtie.railtie_name] = railtie.root + ENV["MIGRATIONS_PATH"]
693
+ end
370
694
  end
371
695
 
372
696
  on_skip = Proc.new do |name, migration|
@@ -377,8 +701,8 @@ namespace :railties do
377
701
  puts "Copied migration #{migration.basename} from #{name}"
378
702
  end
379
703
 
380
- ActiveRecord::Migration.copy(ActiveRecord::Migrator.migrations_paths.first, railties,
381
- :on_skip => on_skip, :on_copy => on_copy)
704
+ ActiveRecord::Migration.copy(ActiveRecord::Tasks::DatabaseTasks.migrations_paths.first, railties,
705
+ on_skip: on_skip, on_copy: on_copy)
382
706
  end
383
707
  end
384
708
  end