activerecord 6.0.3.4 → 6.1.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 (245) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +891 -695
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_record.rb +7 -14
  6. data/lib/active_record/aggregations.rb +5 -5
  7. data/lib/active_record/association_relation.rb +30 -12
  8. data/lib/active_record/associations.rb +118 -11
  9. data/lib/active_record/associations/alias_tracker.rb +19 -15
  10. data/lib/active_record/associations/association.rb +44 -28
  11. data/lib/active_record/associations/association_scope.rb +19 -15
  12. data/lib/active_record/associations/belongs_to_association.rb +22 -8
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
  14. data/lib/active_record/associations/builder/association.rb +32 -5
  15. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  16. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -1
  18. data/lib/active_record/associations/builder/has_many.rb +6 -2
  19. data/lib/active_record/associations/builder/has_one.rb +11 -14
  20. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  21. data/lib/active_record/associations/collection_association.rb +19 -6
  22. data/lib/active_record/associations/collection_proxy.rb +13 -5
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +24 -2
  25. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  26. data/lib/active_record/associations/has_one_association.rb +15 -1
  27. data/lib/active_record/associations/join_dependency.rb +72 -50
  28. data/lib/active_record/associations/join_dependency/join_association.rb +39 -16
  29. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  30. data/lib/active_record/associations/preloader.rb +11 -5
  31. data/lib/active_record/associations/preloader/association.rb +51 -25
  32. data/lib/active_record/associations/preloader/through_association.rb +2 -2
  33. data/lib/active_record/associations/singular_association.rb +1 -1
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/attribute_assignment.rb +10 -8
  36. data/lib/active_record/attribute_methods.rb +64 -54
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
  38. data/lib/active_record/attribute_methods/dirty.rb +1 -11
  39. data/lib/active_record/attribute_methods/primary_key.rb +6 -2
  40. data/lib/active_record/attribute_methods/query.rb +3 -6
  41. data/lib/active_record/attribute_methods/read.rb +8 -11
  42. data/lib/active_record/attribute_methods/serialization.rb +11 -5
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
  44. data/lib/active_record/attribute_methods/write.rb +12 -20
  45. data/lib/active_record/attributes.rb +33 -8
  46. data/lib/active_record/autosave_association.rb +57 -40
  47. data/lib/active_record/base.rb +2 -14
  48. data/lib/active_record/callbacks.rb +152 -22
  49. data/lib/active_record/coders/yaml_column.rb +1 -1
  50. data/lib/active_record/connection_adapters.rb +50 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +191 -134
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -22
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -8
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +116 -27
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +228 -83
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +80 -32
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +54 -72
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +133 -96
  64. data/lib/active_record/connection_adapters/column.rb +15 -1
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  67. data/lib/active_record/connection_adapters/mysql/database_statements.rb +23 -25
  68. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  70. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -6
  71. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  72. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
  73. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +11 -7
  74. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  75. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
  76. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  77. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  78. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  79. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +13 -54
  80. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  82. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  83. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  84. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -5
  89. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
  90. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  91. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
  93. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
  94. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  95. data/lib/active_record/connection_adapters/postgresql_adapter.rb +73 -58
  96. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  97. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  98. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +31 -6
  99. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
  100. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  101. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +37 -4
  102. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +49 -50
  103. data/lib/active_record/connection_handling.rb +218 -71
  104. data/lib/active_record/core.rb +245 -61
  105. data/lib/active_record/database_configurations.rb +124 -85
  106. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  107. data/lib/active_record/database_configurations/database_config.rb +52 -9
  108. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  109. data/lib/active_record/database_configurations/url_config.rb +15 -40
  110. data/lib/active_record/delegated_type.rb +209 -0
  111. data/lib/active_record/destroy_association_async_job.rb +36 -0
  112. data/lib/active_record/enum.rb +82 -38
  113. data/lib/active_record/errors.rb +47 -12
  114. data/lib/active_record/explain.rb +9 -4
  115. data/lib/active_record/explain_subscriber.rb +1 -1
  116. data/lib/active_record/fixture_set/file.rb +10 -17
  117. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  118. data/lib/active_record/fixture_set/render_context.rb +1 -1
  119. data/lib/active_record/fixture_set/table_row.rb +2 -2
  120. data/lib/active_record/fixtures.rb +58 -9
  121. data/lib/active_record/gem_version.rb +3 -3
  122. data/lib/active_record/inheritance.rb +40 -18
  123. data/lib/active_record/insert_all.rb +35 -6
  124. data/lib/active_record/integration.rb +3 -5
  125. data/lib/active_record/internal_metadata.rb +16 -7
  126. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  127. data/lib/active_record/locking/optimistic.rb +33 -17
  128. data/lib/active_record/locking/pessimistic.rb +6 -2
  129. data/lib/active_record/log_subscriber.rb +27 -8
  130. data/lib/active_record/middleware/database_selector.rb +4 -1
  131. data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
  132. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  133. data/lib/active_record/migration.rb +113 -83
  134. data/lib/active_record/migration/command_recorder.rb +47 -27
  135. data/lib/active_record/migration/compatibility.rb +68 -17
  136. data/lib/active_record/model_schema.rb +117 -13
  137. data/lib/active_record/nested_attributes.rb +2 -3
  138. data/lib/active_record/no_touching.rb +1 -1
  139. data/lib/active_record/persistence.rb +50 -45
  140. data/lib/active_record/query_cache.rb +15 -5
  141. data/lib/active_record/querying.rb +11 -6
  142. data/lib/active_record/railtie.rb +64 -44
  143. data/lib/active_record/railties/console_sandbox.rb +2 -4
  144. data/lib/active_record/railties/databases.rake +276 -99
  145. data/lib/active_record/readonly_attributes.rb +4 -0
  146. data/lib/active_record/reflection.rb +71 -57
  147. data/lib/active_record/relation.rb +96 -67
  148. data/lib/active_record/relation/batches.rb +38 -31
  149. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  150. data/lib/active_record/relation/calculations.rb +101 -44
  151. data/lib/active_record/relation/delegation.rb +2 -1
  152. data/lib/active_record/relation/finder_methods.rb +45 -15
  153. data/lib/active_record/relation/from_clause.rb +1 -1
  154. data/lib/active_record/relation/merger.rb +27 -25
  155. data/lib/active_record/relation/predicate_builder.rb +59 -38
  156. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  157. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  158. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
  159. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  160. data/lib/active_record/relation/query_methods.rb +333 -195
  161. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  162. data/lib/active_record/relation/spawn_methods.rb +8 -7
  163. data/lib/active_record/relation/where_clause.rb +104 -57
  164. data/lib/active_record/result.rb +41 -33
  165. data/lib/active_record/runtime_registry.rb +2 -2
  166. data/lib/active_record/sanitization.rb +6 -17
  167. data/lib/active_record/schema_dumper.rb +34 -4
  168. data/lib/active_record/schema_migration.rb +2 -8
  169. data/lib/active_record/scoping/named.rb +6 -17
  170. data/lib/active_record/secure_token.rb +16 -8
  171. data/lib/active_record/serialization.rb +5 -3
  172. data/lib/active_record/signed_id.rb +116 -0
  173. data/lib/active_record/statement_cache.rb +20 -4
  174. data/lib/active_record/store.rb +2 -2
  175. data/lib/active_record/suppressor.rb +2 -2
  176. data/lib/active_record/table_metadata.rb +42 -51
  177. data/lib/active_record/tasks/database_tasks.rb +140 -113
  178. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
  179. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
  180. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
  181. data/lib/active_record/test_databases.rb +5 -4
  182. data/lib/active_record/test_fixtures.rb +37 -16
  183. data/lib/active_record/timestamp.rb +4 -6
  184. data/lib/active_record/touch_later.rb +21 -21
  185. data/lib/active_record/transactions.rb +19 -66
  186. data/lib/active_record/type.rb +8 -1
  187. data/lib/active_record/type/serialized.rb +6 -2
  188. data/lib/active_record/type/time.rb +10 -0
  189. data/lib/active_record/type_caster/connection.rb +0 -1
  190. data/lib/active_record/type_caster/map.rb +8 -5
  191. data/lib/active_record/validations.rb +1 -0
  192. data/lib/active_record/validations/numericality.rb +35 -0
  193. data/lib/active_record/validations/uniqueness.rb +24 -4
  194. data/lib/arel.rb +5 -13
  195. data/lib/arel/attributes/attribute.rb +4 -0
  196. data/lib/arel/collectors/bind.rb +5 -0
  197. data/lib/arel/collectors/composite.rb +8 -0
  198. data/lib/arel/collectors/sql_string.rb +7 -0
  199. data/lib/arel/collectors/substitute_binds.rb +7 -0
  200. data/lib/arel/nodes.rb +3 -1
  201. data/lib/arel/nodes/binary.rb +82 -8
  202. data/lib/arel/nodes/bind_param.rb +8 -0
  203. data/lib/arel/nodes/casted.rb +21 -9
  204. data/lib/arel/nodes/equality.rb +6 -9
  205. data/lib/arel/nodes/grouping.rb +3 -0
  206. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  207. data/lib/arel/nodes/in.rb +8 -1
  208. data/lib/arel/nodes/infix_operation.rb +13 -1
  209. data/lib/arel/nodes/join_source.rb +1 -1
  210. data/lib/arel/nodes/node.rb +7 -6
  211. data/lib/arel/nodes/ordering.rb +27 -0
  212. data/lib/arel/nodes/sql_literal.rb +3 -0
  213. data/lib/arel/nodes/table_alias.rb +7 -3
  214. data/lib/arel/nodes/unary.rb +0 -1
  215. data/lib/arel/predications.rb +12 -18
  216. data/lib/arel/select_manager.rb +1 -2
  217. data/lib/arel/table.rb +13 -5
  218. data/lib/arel/visitors.rb +0 -7
  219. data/lib/arel/visitors/dot.rb +14 -2
  220. data/lib/arel/visitors/mysql.rb +11 -1
  221. data/lib/arel/visitors/postgresql.rb +15 -4
  222. data/lib/arel/visitors/to_sql.rb +89 -78
  223. data/lib/rails/generators/active_record/migration.rb +6 -1
  224. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  225. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  226. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +3 -3
  227. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  228. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  229. metadata +25 -26
  230. data/lib/active_record/advisory_lock_base.rb +0 -18
  231. data/lib/active_record/attribute_decorators.rb +0 -88
  232. data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
  233. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  234. data/lib/active_record/define_callbacks.rb +0 -22
  235. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  236. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  237. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  238. data/lib/arel/attributes.rb +0 -22
  239. data/lib/arel/visitors/depth_first.rb +0 -203
  240. data/lib/arel/visitors/ibm_db.rb +0 -34
  241. data/lib/arel/visitors/informix.rb +0 -62
  242. data/lib/arel/visitors/mssql.rb +0 -156
  243. data/lib/arel/visitors/oracle.rb +0 -158
  244. data/lib/arel/visitors/oracle12.rb +0 -65
  245. data/lib/arel/visitors/where_sql.rb +0 -22
@@ -4,7 +4,6 @@ require "active_record/database_configurations"
4
4
 
5
5
  module ActiveRecord
6
6
  module Tasks # :nodoc:
7
- class DatabaseAlreadyExists < StandardError; end # :nodoc:
8
7
  class DatabaseNotSupported < StandardError; end # :nodoc:
9
8
 
10
9
  # ActiveRecord::Tasks::DatabaseTasks is a utility class, which encapsulates
@@ -39,17 +38,18 @@ module ActiveRecord
39
38
  module DatabaseTasks
40
39
  ##
41
40
  # :singleton-method:
42
- # 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
43
42
  mattr_accessor :structure_dump_flags, instance_accessor: false
44
43
 
45
44
  ##
46
45
  # :singleton-method:
47
- # Extra flags passed to database CLI tool when calling db:structure:load
46
+ # Extra flags passed to database CLI tool when calling db:schema:load
48
47
  mattr_accessor :structure_load_flags, instance_accessor: false
49
48
 
50
49
  extend self
51
50
 
52
51
  attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
52
+ deprecate :current_config=
53
53
  attr_accessor :database_configuration
54
54
 
55
55
  LOCAL_HOSTS = ["127.0.0.1", "localhost"]
@@ -106,38 +106,45 @@ module ActiveRecord
106
106
  def spec
107
107
  @spec ||= "primary"
108
108
  end
109
+ deprecate spec: "please use name instead"
110
+
111
+ def name
112
+ @name ||= "primary"
113
+ end
109
114
 
110
115
  def seed_loader
111
116
  @seed_loader ||= Rails.application
112
117
  end
113
118
 
114
119
  def current_config(options = {})
115
- options.reverse_merge! env: env
116
- options[:spec] ||= "primary"
117
120
  if options.has_key?(:config)
118
121
  @current_config = options[:config]
119
122
  else
120
- @current_config ||= ActiveRecord::Base.configurations.configs_for(env_name: options[:env], spec_name: options[:spec]).config
123
+ env_name = options[:env] || env
124
+ name = options[:spec] || "primary"
125
+
126
+ @current_config ||= ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: name)&.configuration_hash
121
127
  end
122
128
  end
129
+ deprecate :current_config
123
130
 
124
- def create(*arguments)
125
- configuration = arguments.first
126
- class_for_adapter(configuration["adapter"]).new(*arguments).create
127
- $stdout.puts "Created database '#{configuration['database']}'" if verbose?
131
+ def create(configuration, *arguments)
132
+ db_config = resolve_configuration(configuration)
133
+ database_adapter_for(db_config, *arguments).create
134
+ $stdout.puts "Created database '#{db_config.database}'" if verbose?
128
135
  rescue DatabaseAlreadyExists
129
- $stderr.puts "Database '#{configuration['database']}' already exists" if verbose?
136
+ $stderr.puts "Database '#{db_config.database}' already exists" if verbose?
130
137
  rescue Exception => error
131
138
  $stderr.puts error
132
- $stderr.puts "Couldn't create '#{configuration['database']}' database. Please check your configuration."
139
+ $stderr.puts "Couldn't create '#{db_config.database}' database. Please check your configuration."
133
140
  raise
134
141
  end
135
142
 
136
143
  def create_all
137
144
  old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
138
- each_local_configuration { |configuration| create configuration }
145
+ each_local_configuration { |db_config| create(db_config) }
139
146
  if old_pool
140
- ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec.to_hash)
147
+ ActiveRecord::Base.connection_handler.establish_connection(old_pool.db_config)
141
148
  end
142
149
  end
143
150
 
@@ -147,7 +154,9 @@ module ActiveRecord
147
154
  begin
148
155
  Rails.application.config.load_database_yaml
149
156
  rescue
150
- $stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB."
157
+ unless ActiveRecord::Base.suppress_multiple_database_warning
158
+ $stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB."
159
+ end
151
160
 
152
161
  {}
153
162
  end
@@ -162,7 +171,7 @@ module ActiveRecord
162
171
  return if database_configs.count == 1
163
172
 
164
173
  database_configs.each do |db_config|
165
- yield db_config.spec_name
174
+ yield db_config.name
166
175
  end
167
176
  end
168
177
 
@@ -173,59 +182,49 @@ module ActiveRecord
173
182
  dbs_list = []
174
183
 
175
184
  db_configs.each do |db|
176
- dbs_list << "#{command}:#{db.spec_name}"
185
+ dbs_list << "#{command}:#{db.name}"
177
186
  end
178
187
 
179
188
  raise "You're using a multiple database application. To use `#{command}` you must run the namespaced task with a VERSION. Available tasks are #{dbs_list.to_sentence}."
180
189
  end
181
190
  end
182
191
 
183
- def create_current(environment = env, spec_name = nil)
184
- each_current_configuration(environment, spec_name) { |configuration|
185
- create configuration
186
- }
192
+ def create_current(environment = env, name = nil)
193
+ each_current_configuration(environment, name) { |db_config| create(db_config) }
187
194
  ActiveRecord::Base.establish_connection(environment.to_sym)
188
195
  end
189
196
 
190
- def drop(*arguments)
191
- configuration = arguments.first
192
- class_for_adapter(configuration["adapter"]).new(*arguments).drop
193
- $stdout.puts "Dropped database '#{configuration['database']}'" if verbose?
197
+ def drop(configuration, *arguments)
198
+ db_config = resolve_configuration(configuration)
199
+ database_adapter_for(db_config, *arguments).drop
200
+ $stdout.puts "Dropped database '#{db_config.database}'" if verbose?
194
201
  rescue ActiveRecord::NoDatabaseError
195
- $stderr.puts "Database '#{configuration['database']}' does not exist"
202
+ $stderr.puts "Database '#{db_config.database}' does not exist"
196
203
  rescue Exception => error
197
204
  $stderr.puts error
198
- $stderr.puts "Couldn't drop database '#{configuration['database']}'"
205
+ $stderr.puts "Couldn't drop database '#{db_config.database}'"
199
206
  raise
200
207
  end
201
208
 
202
209
  def drop_all
203
- each_local_configuration { |configuration| drop configuration }
210
+ each_local_configuration { |db_config| drop(db_config) }
204
211
  end
205
212
 
206
213
  def drop_current(environment = env)
207
- each_current_configuration(environment) { |configuration|
208
- drop configuration
209
- }
214
+ each_current_configuration(environment) { |db_config| drop(db_config) }
210
215
  end
211
216
 
212
- def truncate_tables(configuration)
213
- ActiveRecord::Base.connected_to(database: { truncation: configuration }) do
214
- conn = ActiveRecord::Base.connection
215
- table_names = conn.tables
216
- table_names -= [
217
- conn.schema_migration.table_name,
218
- InternalMetadata.table_name
219
- ]
217
+ def truncate_tables(db_config)
218
+ ActiveRecord::Base.establish_connection(db_config)
220
219
 
221
- ActiveRecord::Base.connection.truncate_tables(*table_names)
222
- end
220
+ connection = ActiveRecord::Base.connection
221
+ connection.truncate_tables(*connection.tables)
223
222
  end
224
223
  private :truncate_tables
225
224
 
226
225
  def truncate_all(environment = env)
227
226
  ActiveRecord::Base.configurations.configs_for(env_name: environment).each do |db_config|
228
- truncate_tables db_config.config
227
+ truncate_tables(db_config)
229
228
  end
230
229
  end
231
230
 
@@ -250,7 +249,7 @@ module ActiveRecord
250
249
  end
251
250
 
252
251
  # output
253
- puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
252
+ puts "\ndatabase: #{ActiveRecord::Base.connection_db_config.database}\n\n"
254
253
  puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
255
254
  puts "-" * 50
256
255
  ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
@@ -269,115 +268,126 @@ module ActiveRecord
269
268
  ENV["VERSION"].to_i if ENV["VERSION"] && !ENV["VERSION"].empty?
270
269
  end
271
270
 
272
- def charset_current(environment = env, specification_name = spec)
273
- charset ActiveRecord::Base.configurations.configs_for(env_name: environment, spec_name: specification_name).config
271
+ def charset_current(env_name = env, db_name = name)
272
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: db_name)
273
+ charset(db_config)
274
274
  end
275
275
 
276
- def charset(*arguments)
277
- configuration = arguments.first
278
- class_for_adapter(configuration["adapter"]).new(*arguments).charset
276
+ def charset(configuration, *arguments)
277
+ db_config = resolve_configuration(configuration)
278
+ database_adapter_for(db_config, *arguments).charset
279
279
  end
280
280
 
281
- def collation_current(environment = env, specification_name = spec)
282
- collation ActiveRecord::Base.configurations.configs_for(env_name: environment, spec_name: specification_name).config
281
+ def collation_current(env_name = env, db_name = name)
282
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: db_name)
283
+ collation(db_config)
283
284
  end
284
285
 
285
- def collation(*arguments)
286
- configuration = arguments.first
287
- class_for_adapter(configuration["adapter"]).new(*arguments).collation
286
+ def collation(configuration, *arguments)
287
+ db_config = resolve_configuration(configuration)
288
+ database_adapter_for(db_config, *arguments).collation
288
289
  end
289
290
 
290
291
  def purge(configuration)
291
- class_for_adapter(configuration["adapter"]).new(configuration).purge
292
+ db_config = resolve_configuration(configuration)
293
+ database_adapter_for(db_config).purge
292
294
  end
293
295
 
294
296
  def purge_all
295
- each_local_configuration { |configuration|
296
- purge configuration
297
- }
297
+ each_local_configuration { |db_config| purge(db_config) }
298
298
  end
299
299
 
300
300
  def purge_current(environment = env)
301
- each_current_configuration(environment) { |configuration|
302
- purge configuration
303
- }
301
+ each_current_configuration(environment) { |db_config| purge(db_config) }
304
302
  ActiveRecord::Base.establish_connection(environment.to_sym)
305
303
  end
306
304
 
307
- def structure_dump(*arguments)
308
- configuration = arguments.first
309
- filename = arguments.delete_at 1
310
- class_for_adapter(configuration["adapter"]).new(*arguments).structure_dump(filename, structure_dump_flags)
305
+ def structure_dump(configuration, *arguments)
306
+ db_config = resolve_configuration(configuration)
307
+ filename = arguments.delete_at(0)
308
+ database_adapter_for(db_config, *arguments).structure_dump(filename, structure_dump_flags)
311
309
  end
312
310
 
313
- def structure_load(*arguments)
314
- configuration = arguments.first
315
- filename = arguments.delete_at 1
316
- class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename, structure_load_flags)
311
+ def structure_load(configuration, *arguments)
312
+ db_config = resolve_configuration(configuration)
313
+ filename = arguments.delete_at(0)
314
+ database_adapter_for(db_config, *arguments).structure_load(filename, structure_load_flags)
317
315
  end
318
316
 
319
- def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary") # :nodoc:
320
- file ||= dump_filename(spec_name, format)
317
+ def load_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
318
+ file ||= dump_filename(db_config.name, format)
321
319
 
322
320
  verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
323
321
  check_schema_file(file)
324
- ActiveRecord::Base.establish_connection(configuration)
322
+ ActiveRecord::Base.establish_connection(db_config)
325
323
 
326
324
  case format
327
325
  when :ruby
328
326
  load(file)
329
327
  when :sql
330
- structure_load(configuration, file)
328
+ structure_load(db_config, file)
331
329
  else
332
330
  raise ArgumentError, "unknown format #{format.inspect}"
333
331
  end
334
332
  ActiveRecord::InternalMetadata.create_table
335
- ActiveRecord::InternalMetadata[:environment] = environment
333
+ ActiveRecord::InternalMetadata[:environment] = db_config.env_name
336
334
  ActiveRecord::InternalMetadata[:schema_sha1] = schema_sha1(file)
337
335
  ensure
338
336
  Migration.verbose = verbose_was
339
337
  end
340
338
 
341
- def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary")
342
- file ||= dump_filename(spec_name, format)
339
+ def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = nil, name = nil)
340
+ db_config = resolve_configuration(configuration)
341
+
342
+ if environment || name
343
+ ActiveSupport::Deprecation.warn("`environment` and `name` will be removed as parameters in 6.2.0, you may now pass an ActiveRecord::DatabaseConfigurations::DatabaseConfig as `configuration` instead.")
344
+ end
345
+
346
+ name ||= db_config.name
347
+
348
+ file ||= dump_filename(name, format)
343
349
 
344
350
  return true unless File.exist?(file)
345
351
 
346
- ActiveRecord::Base.establish_connection(configuration)
352
+ ActiveRecord::Base.establish_connection(db_config)
353
+
354
+ return false unless ActiveRecord::InternalMetadata.enabled?
347
355
  return false unless ActiveRecord::InternalMetadata.table_exists?
356
+
348
357
  ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
349
358
  end
350
359
 
351
- def reconstruct_from_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary") # :nodoc:
352
- file ||= dump_filename(spec_name, format)
360
+ def reconstruct_from_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
361
+ file ||= dump_filename(db_config.name, format)
353
362
 
354
363
  check_schema_file(file)
355
364
 
356
- ActiveRecord::Base.establish_connection(configuration)
365
+ ActiveRecord::Base.establish_connection(db_config)
357
366
 
358
- if schema_up_to_date?(configuration, format, file, environment, spec_name)
359
- truncate_tables(configuration)
367
+ if schema_up_to_date?(db_config, format, file)
368
+ truncate_tables(db_config)
360
369
  else
361
- purge(configuration)
362
- load_schema(configuration, format, file, environment, spec_name)
370
+ purge(db_config)
371
+ load_schema(db_config, format, file)
363
372
  end
364
373
  rescue ActiveRecord::NoDatabaseError
365
- create(configuration)
366
- load_schema(configuration, format, file, environment, spec_name)
374
+ create(db_config)
375
+ load_schema(db_config, format, file)
367
376
  end
368
377
 
369
- def dump_schema(configuration, format = ActiveRecord::Base.schema_format, spec_name = "primary") # :nodoc:
378
+ def dump_schema(db_config, format = ActiveRecord::Base.schema_format) # :nodoc:
370
379
  require "active_record/schema_dumper"
371
- filename = dump_filename(spec_name, format)
380
+ filename = dump_filename(db_config.name, format)
372
381
  connection = ActiveRecord::Base.connection
373
382
 
383
+ FileUtils.mkdir_p(db_dir)
374
384
  case format
375
385
  when :ruby
376
386
  File.open(filename, "w:utf-8") do |file|
377
387
  ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
378
388
  end
379
389
  when :sql
380
- structure_dump(configuration, filename)
390
+ structure_dump(db_config, filename)
381
391
  if connection.schema_migration.table_exists?
382
392
  File.open(filename, "a") do |f|
383
393
  f.puts connection.dump_schema_information
@@ -400,36 +410,36 @@ module ActiveRecord
400
410
  end
401
411
  end
402
412
 
403
- def dump_filename(namespace, format = ActiveRecord::Base.schema_format)
404
- filename = if namespace == "primary"
413
+ def dump_filename(db_config_name, format = ActiveRecord::Base.schema_format)
414
+ filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
405
415
  schema_file_type(format)
406
416
  else
407
- "#{namespace}_#{schema_file_type(format)}"
417
+ "#{db_config_name}_#{schema_file_type(format)}"
408
418
  end
409
419
 
410
420
  ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
411
421
  end
412
422
 
413
- def cache_dump_filename(namespace)
414
- filename = if namespace == "primary"
423
+ def cache_dump_filename(db_config_name, schema_cache_path: nil)
424
+ filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
415
425
  "schema_cache.yml"
416
426
  else
417
- "#{namespace}_schema_cache.yml"
427
+ "#{db_config_name}_schema_cache.yml"
418
428
  end
419
429
 
420
- ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
430
+ schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
421
431
  end
422
432
 
423
433
  def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
424
- each_current_configuration(environment) { |configuration, spec_name, env|
425
- load_schema(configuration, format, file, env, spec_name)
426
- }
434
+ each_current_configuration(environment) do |db_config|
435
+ load_schema(db_config, format, file)
436
+ end
427
437
  ActiveRecord::Base.establish_connection(environment.to_sym)
428
438
  end
429
439
 
430
440
  def check_schema_file(filename)
431
441
  unless File.exist?(filename)
432
- message = +%{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}
442
+ message = +%{#{filename} doesn't exist yet. Run `bin/rails db:migrate` to create it, then try again.}
433
443
  message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails.root)
434
444
  Kernel.abort message
435
445
  end
@@ -450,16 +460,33 @@ module ActiveRecord
450
460
  # ==== Examples:
451
461
  # ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
452
462
  def dump_schema_cache(conn, filename)
453
- conn.schema_cache.clear!
454
- conn.data_sources.each { |table| conn.schema_cache.add(table) }
455
- open(filename, "wb") { |f| f.write(YAML.dump(conn.schema_cache)) }
463
+ conn.schema_cache.dump_to(filename)
464
+ end
465
+
466
+ def clear_schema_cache(filename)
467
+ FileUtils.rm_f filename, verbose: false
456
468
  end
457
469
 
458
470
  private
471
+ def resolve_configuration(configuration)
472
+ Base.configurations.resolve(configuration)
473
+ end
474
+
459
475
  def verbose?
460
476
  ENV["VERBOSE"] ? ENV["VERBOSE"] != "false" : true
461
477
  end
462
478
 
479
+ # Create a new instance for the specified db configuration object
480
+ # For classes that have been converted to use db_config objects, pass a
481
+ # `DatabaseConfig`, otherwise pass a `Hash`
482
+ def database_adapter_for(db_config, *arguments)
483
+ klass = class_for_adapter(db_config.adapter)
484
+ converted = klass.respond_to?(:using_database_configurations?) && klass.using_database_configurations?
485
+
486
+ config = converted ? db_config : db_config.configuration_hash
487
+ klass.new(config, *arguments)
488
+ end
489
+
463
490
  def class_for_adapter(adapter)
464
491
  _key, task = @tasks.each_pair.detect { |pattern, _task| adapter[pattern] }
465
492
  unless task
@@ -468,34 +495,34 @@ module ActiveRecord
468
495
  task.is_a?(String) ? task.constantize : task
469
496
  end
470
497
 
471
- def each_current_configuration(environment, spec_name = nil)
498
+ def each_current_configuration(environment, name = nil)
472
499
  environments = [environment]
473
- environments << "test" if environment == "development"
500
+ environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
474
501
 
475
502
  environments.each do |env|
476
503
  ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
477
- next if spec_name && spec_name != db_config.spec_name
504
+ next if name && name != db_config.name
478
505
 
479
- yield db_config.config, db_config.spec_name, env
506
+ yield db_config
480
507
  end
481
508
  end
482
509
  end
483
510
 
484
511
  def each_local_configuration
485
512
  ActiveRecord::Base.configurations.configs_for.each do |db_config|
486
- configuration = db_config.config
487
- next unless configuration["database"]
513
+ next unless db_config.database
488
514
 
489
- if local_database?(configuration)
490
- yield configuration
515
+ if local_database?(db_config)
516
+ yield db_config
491
517
  else
492
- $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
518
+ $stderr.puts "This task only modifies local databases. #{db_config.database} is on a remote host."
493
519
  end
494
520
  end
495
521
  end
496
522
 
497
- def local_database?(configuration)
498
- configuration["host"].blank? || LOCAL_HOSTS.include?(configuration["host"])
523
+ def local_database?(db_config)
524
+ host = db_config.host
525
+ host.blank? || LOCAL_HOSTS.include?(host)
499
526
  end
500
527
 
501
528
  def schema_sha1(file)