activerecord 6.0.0.rc1 → 6.0.0.rc2

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -0
  3. data/lib/active_record/associations/builder/collection_association.rb +2 -2
  4. data/lib/active_record/associations/collection_proxy.rb +1 -1
  5. data/lib/active_record/associations/join_dependency.rb +10 -9
  6. data/lib/active_record/associations/join_dependency/join_association.rb +11 -2
  7. data/lib/active_record/associations/preloader/association.rb +3 -1
  8. data/lib/active_record/attribute_methods.rb +0 -51
  9. data/lib/active_record/attribute_methods/dirty.rb +6 -1
  10. data/lib/active_record/autosave_association.rb +1 -1
  11. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +93 -11
  12. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -3
  13. data/lib/active_record/connection_adapters/abstract/quoting.rb +53 -0
  14. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -1
  15. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -7
  16. data/lib/active_record/connection_adapters/abstract/transaction.rb +12 -4
  17. data/lib/active_record/connection_adapters/abstract_adapter.rb +40 -20
  18. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -2
  19. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  20. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +3 -1
  21. data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -1
  22. data/lib/active_record/connection_adapters/postgresql/quoting.rb +39 -2
  23. data/lib/active_record/connection_adapters/postgresql_adapter.rb +8 -1
  24. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +38 -2
  25. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +12 -2
  26. data/lib/active_record/connection_handling.rb +6 -2
  27. data/lib/active_record/database_configurations.rb +6 -6
  28. data/lib/active_record/gem_version.rb +1 -1
  29. data/lib/active_record/middleware/database_selector.rb +3 -3
  30. data/lib/active_record/middleware/database_selector/resolver.rb +2 -2
  31. data/lib/active_record/migration.rb +26 -23
  32. data/lib/active_record/railtie.rb +0 -1
  33. data/lib/active_record/railties/databases.rake +57 -23
  34. data/lib/active_record/reflection.rb +1 -1
  35. data/lib/active_record/relation/calculations.rb +1 -1
  36. data/lib/active_record/relation/finder_methods.rb +4 -2
  37. data/lib/active_record/relation/merger.rb +6 -2
  38. data/lib/active_record/relation/query_methods.rb +32 -32
  39. data/lib/active_record/sanitization.rb +30 -2
  40. data/lib/active_record/schema.rb +1 -1
  41. data/lib/active_record/schema_dumper.rb +5 -1
  42. data/lib/active_record/table_metadata.rb +6 -10
  43. data/lib/active_record/tasks/database_tasks.rb +41 -8
  44. data/lib/active_record/tasks/mysql_database_tasks.rb +3 -1
  45. data/lib/active_record/timestamp.rb +26 -16
  46. data/lib/active_record/touch_later.rb +2 -0
  47. data/lib/active_record/transactions.rb +9 -10
  48. data/lib/active_record/type_caster/connection.rb +16 -10
  49. data/lib/arel/visitors/depth_first.rb +1 -1
  50. data/lib/arel/visitors/to_sql.rb +23 -26
  51. data/lib/arel/visitors/visitor.rb +9 -5
  52. metadata +8 -8
@@ -46,7 +46,7 @@ module ActiveRecord
46
46
  conn = PG.connect(conn_params)
47
47
  ConnectionAdapters::PostgreSQLAdapter.new(conn, logger, conn_params, config)
48
48
  rescue ::PG::Error => error
49
- if error.message.include?("does not exist")
49
+ if error.message.include?(conn_params[:dbname])
50
50
  raise ActiveRecord::NoDatabaseError
51
51
  else
52
52
  raise
@@ -259,6 +259,12 @@ module ActiveRecord
259
259
  @use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
260
260
  end
261
261
 
262
+ def self.database_exists?(config)
263
+ !!ActiveRecord::Base.postgresql_connection(config)
264
+ rescue ActiveRecord::NoDatabaseError
265
+ false
266
+ end
267
+
262
268
  # Is this connection alive and ready for queries?
263
269
  def active?
264
270
  @lock.synchronize do
@@ -302,6 +308,7 @@ module ActiveRecord
302
308
  end
303
309
 
304
310
  def discard! # :nodoc:
311
+ super
305
312
  @connection.socket_io.reopen(IO::NULL) rescue nil
306
313
  @connection = nil
307
314
  end
@@ -13,11 +13,11 @@ module ActiveRecord
13
13
  end
14
14
 
15
15
  def quote_table_name(name)
16
- @quoted_table_names[name] ||= super.gsub(".", "\".\"").freeze
16
+ self.class.quoted_table_names[name] ||= super.gsub(".", "\".\"").freeze
17
17
  end
18
18
 
19
19
  def quote_column_name(name)
20
- @quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}")
20
+ self.class.quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}")
21
21
  end
22
22
 
23
23
  def quoted_time(value)
@@ -45,6 +45,42 @@ module ActiveRecord
45
45
  0
46
46
  end
47
47
 
48
+ def column_name_matcher
49
+ COLUMN_NAME
50
+ end
51
+
52
+ def column_name_with_order_matcher
53
+ COLUMN_NAME_WITH_ORDER
54
+ end
55
+
56
+ COLUMN_NAME = /
57
+ \A
58
+ (
59
+ (?:
60
+ # "table_name"."column_name" | function(one or no argument)
61
+ ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\)
62
+ )
63
+ (?:\s+AS\s+(?:\w+|"\w+"))?
64
+ )
65
+ (?:\s*,\s*\g<1>)*
66
+ \z
67
+ /ix
68
+
69
+ COLUMN_NAME_WITH_ORDER = /
70
+ \A
71
+ (
72
+ (?:
73
+ # "table_name"."column_name" | function(one or no argument)
74
+ ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\)
75
+ )
76
+ (?:\s+ASC|\s+DESC)?
77
+ )
78
+ (?:\s*,\s*\g<1>)*
79
+ \z
80
+ /ix
81
+
82
+ private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
83
+
48
84
  private
49
85
 
50
86
  def _type_cast(value)
@@ -98,6 +98,16 @@ module ActiveRecord
98
98
  configure_connection
99
99
  end
100
100
 
101
+ def self.database_exists?(config)
102
+ config = config.symbolize_keys
103
+ if config[:database] == ":memory:"
104
+ return true
105
+ else
106
+ database_file = defined?(Rails.root) ? File.expand_path(config[:database], Rails.root) : config[:database]
107
+ File.exist?(database_file)
108
+ end
109
+ end
110
+
101
111
  def supports_ddl_transactions?
102
112
  true
103
113
  end
@@ -485,9 +495,9 @@ module ActiveRecord
485
495
  result = exec_query(sql, "SCHEMA").first
486
496
 
487
497
  if result
488
- # Splitting with left parentheses and picking up last will return all
498
+ # Splitting with left parentheses and discarding the first part will return all
489
499
  # columns separated with comma(,).
490
- columns_string = result["sql"].split("(").last
500
+ columns_string = result["sql"].split("(", 2).last
491
501
 
492
502
  columns_string.split(",").each do |column_string|
493
503
  # This regex will match the column name and collation type and will save
@@ -173,7 +173,7 @@ module ActiveRecord
173
173
  raise "Anonymous class is not allowed." unless name
174
174
 
175
175
  config_or_env ||= DEFAULT_ENV.call.to_sym
176
- pool_name = self == Base ? "primary" : name
176
+ pool_name = primary_class? ? "primary" : name
177
177
  self.connection_specification_name = pool_name
178
178
 
179
179
  resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new(Base.configurations)
@@ -204,11 +204,15 @@ module ActiveRecord
204
204
  # Return the specification name from the current class or its parent.
205
205
  def connection_specification_name
206
206
  if !defined?(@connection_specification_name) || @connection_specification_name.nil?
207
- return self == Base ? "primary" : superclass.connection_specification_name
207
+ return primary_class? ? "primary" : superclass.connection_specification_name
208
208
  end
209
209
  @connection_specification_name
210
210
  end
211
211
 
212
+ def primary_class? # :nodoc:
213
+ self == Base || defined?(ApplicationRecord) && self == ApplicationRecord
214
+ end
215
+
212
216
  # Returns the configuration of the associated connection as a hash:
213
217
  #
214
218
  # ActiveRecord::Base.connection_config
@@ -141,7 +141,7 @@ module ActiveRecord
141
141
  config_without_url.delete "url"
142
142
 
143
143
  ActiveRecord::DatabaseConfigurations::UrlConfig.new(env_name, spec_name, url, config_without_url)
144
- elsif config["database"] || (config.size == 1 && config.values.all? { |v| v.is_a? String })
144
+ elsif config["database"] || config["adapter"] || ENV["DATABASE_URL"]
145
145
  ActiveRecord::DatabaseConfigurations::HashConfig.new(env_name, spec_name, config)
146
146
  else
147
147
  config.each_pair.map do |sub_spec_name, sub_config|
@@ -153,11 +153,11 @@ module ActiveRecord
153
153
  def build_url_config(url, configs)
154
154
  env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call.to_s
155
155
 
156
- if original_config = configs.find(&:for_current_env?)
157
- if original_config.url_config?
158
- configs
159
- else
160
- configs.map do |config|
156
+ if configs.find(&:for_current_env?)
157
+ configs.map do |config|
158
+ if config.url_config?
159
+ config
160
+ else
161
161
  ActiveRecord::DatabaseConfigurations::UrlConfig.new(config.env_name, config.spec_name, url, config.config)
162
162
  end
163
163
  end
@@ -10,7 +10,7 @@ module ActiveRecord
10
10
  MAJOR = 6
11
11
  MINOR = 0
12
12
  TINY = 0
13
- PRE = "rc1"
13
+ PRE = "rc2"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -35,10 +35,10 @@ module ActiveRecord
35
35
  # config.active_record.database_resolver = MyResolver
36
36
  # config.active_record.database_resolver_context = MyResolver::MySession
37
37
  class DatabaseSelector
38
- def initialize(app, resolver_klass = Resolver, context_klass = Resolver::Session, options = {})
38
+ def initialize(app, resolver_klass = nil, context_klass = nil, options = {})
39
39
  @app = app
40
- @resolver_klass = resolver_klass
41
- @context_klass = context_klass
40
+ @resolver_klass = resolver_klass || Resolver
41
+ @context_klass = context_klass || Resolver::Session
42
42
  @options = options
43
43
  end
44
44
 
@@ -46,8 +46,8 @@ module ActiveRecord
46
46
  private
47
47
 
48
48
  def read_from_primary(&blk)
49
- ActiveRecord::Base.connection.while_preventing_writes do
50
- ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do
49
+ ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do
50
+ ActiveRecord::Base.connection_handler.while_preventing_writes do
51
51
  instrumenter.instrument("database_selector.active_record.read_from_primary") do
52
52
  yield
53
53
  end
@@ -494,9 +494,9 @@ module ActiveRecord
494
494
  # This migration will create the horses table for you on the way up, and
495
495
  # automatically figure out how to drop the table on the way down.
496
496
  #
497
- # Some commands like +remove_column+ cannot be reversed. If you care to
498
- # define how to move up and down in these cases, you should define the +up+
499
- # and +down+ methods as before.
497
+ # Some commands cannot be reversed. If you care to define how to move up
498
+ # and down in these cases, you should define the +up+ and +down+ methods
499
+ # as before.
500
500
  #
501
501
  # If a command cannot be reversed, an
502
502
  # <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
@@ -885,13 +885,14 @@ module ActiveRecord
885
885
 
886
886
  def copy(destination, sources, options = {})
887
887
  copied = []
888
+ schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
888
889
 
889
890
  FileUtils.mkdir_p(destination) unless File.exist?(destination)
890
891
 
891
- destination_migrations = ActiveRecord::MigrationContext.new(destination).migrations
892
+ destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
892
893
  last = destination_migrations.last
893
894
  sources.each do |scope, path|
894
- source_migrations = ActiveRecord::MigrationContext.new(path).migrations
895
+ source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
895
896
 
896
897
  source_migrations.each do |migration|
897
898
  source = File.binread(migration.filename)
@@ -1014,10 +1015,11 @@ module ActiveRecord
1014
1015
  end
1015
1016
 
1016
1017
  class MigrationContext #:nodoc:
1017
- attr_reader :migrations_paths
1018
+ attr_reader :migrations_paths, :schema_migration
1018
1019
 
1019
- def initialize(migrations_paths)
1020
+ def initialize(migrations_paths, schema_migration)
1020
1021
  @migrations_paths = migrations_paths
1022
+ @schema_migration = schema_migration
1021
1023
  end
1022
1024
 
1023
1025
  def migrate(target_version = nil, &block)
@@ -1048,7 +1050,7 @@ module ActiveRecord
1048
1050
  migrations
1049
1051
  end
1050
1052
 
1051
- Migrator.new(:up, selected_migrations, target_version).migrate
1053
+ Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
1052
1054
  end
1053
1055
 
1054
1056
  def down(target_version = nil)
@@ -1058,20 +1060,20 @@ module ActiveRecord
1058
1060
  migrations
1059
1061
  end
1060
1062
 
1061
- Migrator.new(:down, selected_migrations, target_version).migrate
1063
+ Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
1062
1064
  end
1063
1065
 
1064
1066
  def run(direction, target_version)
1065
- Migrator.new(direction, migrations, target_version).run
1067
+ Migrator.new(direction, migrations, schema_migration, target_version).run
1066
1068
  end
1067
1069
 
1068
1070
  def open
1069
- Migrator.new(:up, migrations, nil)
1071
+ Migrator.new(:up, migrations, schema_migration)
1070
1072
  end
1071
1073
 
1072
1074
  def get_all_versions
1073
- if SchemaMigration.table_exists?
1074
- SchemaMigration.all_versions.map(&:to_i)
1075
+ if schema_migration.table_exists?
1076
+ schema_migration.all_versions.map(&:to_i)
1075
1077
  else
1076
1078
  []
1077
1079
  end
@@ -1108,12 +1110,12 @@ module ActiveRecord
1108
1110
  end
1109
1111
 
1110
1112
  def migrations_status
1111
- db_list = ActiveRecord::SchemaMigration.normalized_versions
1113
+ db_list = schema_migration.normalized_versions
1112
1114
 
1113
1115
  file_list = migration_files.map do |file|
1114
1116
  version, name, scope = parse_migration_filename(file)
1115
1117
  raise IllegalMigrationNameError.new(file) unless version
1116
- version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
1118
+ version = schema_migration.normalize_migration_number(version)
1117
1119
  status = db_list.delete(version) ? "up" : "down"
1118
1120
  [status, version, (name + scope).humanize]
1119
1121
  end.compact
@@ -1153,7 +1155,7 @@ module ActiveRecord
1153
1155
  end
1154
1156
 
1155
1157
  def move(direction, steps)
1156
- migrator = Migrator.new(direction, migrations)
1158
+ migrator = Migrator.new(direction, migrations, schema_migration)
1157
1159
 
1158
1160
  if current_version != 0 && !migrator.current_migration
1159
1161
  raise UnknownMigrationVersionError.new(current_version)
@@ -1172,27 +1174,28 @@ module ActiveRecord
1172
1174
  end
1173
1175
  end
1174
1176
 
1175
- class Migrator #:nodoc:
1177
+ class Migrator # :nodoc:
1176
1178
  class << self
1177
1179
  attr_accessor :migrations_paths
1178
1180
 
1179
1181
  # For cases where a table doesn't exist like loading from schema cache
1180
1182
  def current_version
1181
- MigrationContext.new(migrations_paths).current_version
1183
+ MigrationContext.new(migrations_paths, SchemaMigration).current_version
1182
1184
  end
1183
1185
  end
1184
1186
 
1185
1187
  self.migrations_paths = ["db/migrate"]
1186
1188
 
1187
- def initialize(direction, migrations, target_version = nil)
1189
+ def initialize(direction, migrations, schema_migration, target_version = nil)
1188
1190
  @direction = direction
1189
1191
  @target_version = target_version
1190
1192
  @migrated_versions = nil
1191
1193
  @migrations = migrations
1194
+ @schema_migration = schema_migration
1192
1195
 
1193
1196
  validate(@migrations)
1194
1197
 
1195
- ActiveRecord::SchemaMigration.create_table
1198
+ @schema_migration.create_table
1196
1199
  ActiveRecord::InternalMetadata.create_table
1197
1200
  end
1198
1201
 
@@ -1246,7 +1249,7 @@ module ActiveRecord
1246
1249
  end
1247
1250
 
1248
1251
  def load_migrated
1249
- @migrated_versions = Set.new(Base.connection.migration_context.get_all_versions)
1252
+ @migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
1250
1253
  end
1251
1254
 
1252
1255
  private
@@ -1330,10 +1333,10 @@ module ActiveRecord
1330
1333
  def record_version_state_after_migrating(version)
1331
1334
  if down?
1332
1335
  migrated.delete(version)
1333
- ActiveRecord::SchemaMigration.delete_by(version: version.to_s)
1336
+ @schema_migration.delete_by(version: version.to_s)
1334
1337
  else
1335
1338
  migrated << version
1336
- ActiveRecord::SchemaMigration.create!(version: version.to_s)
1339
+ @schema_migration.create!(version: version.to_s)
1337
1340
  end
1338
1341
  end
1339
1342
 
@@ -134,7 +134,6 @@ end_error
134
134
 
135
135
  cache = YAML.load(File.read(filename))
136
136
  if cache.version == current_version
137
- connection.schema_cache = cache
138
137
  connection_pool.schema_cache = cache.dup
139
138
  else
140
139
  warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}."
@@ -2,6 +2,8 @@
2
2
 
3
3
  require "active_record"
4
4
 
5
+ databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
6
+
5
7
  db_namespace = namespace :db do
6
8
  desc "Set the environment value for the database"
7
9
  task "environment:set" => :load_config do
@@ -23,7 +25,7 @@ db_namespace = namespace :db do
23
25
  ActiveRecord::Tasks::DatabaseTasks.create_all
24
26
  end
25
27
 
26
- ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name|
28
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
27
29
  desc "Create #{spec_name} database for current environment"
28
30
  task spec_name => :load_config do
29
31
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
@@ -42,7 +44,7 @@ db_namespace = namespace :db do
42
44
  ActiveRecord::Tasks::DatabaseTasks.drop_all
43
45
  end
44
46
 
45
- ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name|
47
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
46
48
  desc "Drop #{spec_name} database for current environment"
47
49
  task spec_name => [:load_config, :check_protected_environments] do
48
50
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
@@ -101,7 +103,7 @@ db_namespace = namespace :db do
101
103
  end
102
104
 
103
105
  namespace :migrate do
104
- ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name|
106
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
105
107
  desc "Migrate #{spec_name} database for current environment"
106
108
  task spec_name => :load_config do
107
109
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
@@ -142,7 +144,7 @@ db_namespace = namespace :db do
142
144
  end
143
145
 
144
146
  namespace :up do
145
- ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name|
147
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
146
148
  task spec_name => :load_config do
147
149
  raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
148
150
 
@@ -176,7 +178,7 @@ db_namespace = namespace :db do
176
178
  end
177
179
 
178
180
  namespace :down do
179
- ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name|
181
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
180
182
  task spec_name => :load_config do
181
183
  raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
182
184
 
@@ -203,7 +205,7 @@ db_namespace = namespace :db do
203
205
  end
204
206
 
205
207
  namespace :status do
206
- ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name|
208
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
207
209
  desc "Display status of migrations for #{spec_name} database"
208
210
  task spec_name => :load_config do
209
211
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
@@ -250,7 +252,11 @@ db_namespace = namespace :db do
250
252
 
251
253
  # desc "Raises an error if there are pending migrations"
252
254
  task abort_if_pending_migrations: :load_config do
253
- pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
255
+ pending_migrations = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).flat_map do |db_config|
256
+ ActiveRecord::Base.establish_connection(db_config.config)
257
+
258
+ ActiveRecord::Base.connection.migration_context.open.pending_migrations
259
+ end
254
260
 
255
261
  if pending_migrations.any?
256
262
  puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
@@ -261,17 +267,56 @@ db_namespace = namespace :db do
261
267
  end
262
268
  end
263
269
 
270
+ namespace :abort_if_pending_migrations do
271
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
272
+ # desc "Raises an error if there are pending migrations for #{spec_name} database"
273
+ task spec_name => :load_config do
274
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
275
+ ActiveRecord::Base.establish_connection(db_config.config)
276
+
277
+ pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
278
+
279
+ if pending_migrations.any?
280
+ puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
281
+ pending_migrations.each do |pending_migration|
282
+ puts " %4d %s" % [pending_migration.version, pending_migration.name]
283
+ end
284
+ abort %{Run `rails db:migrate:#{spec_name}` to update your database then try again.}
285
+ end
286
+ end
287
+ end
288
+ end
289
+
264
290
  desc "Creates the database, loads the schema, and initializes with the seed data (use db:reset to also drop the database first)"
265
291
  task setup: ["db:schema:load_if_ruby", "db:structure:load_if_sql", :seed]
266
292
 
267
293
  desc "Runs setup if database does not exist, or runs migrations if it does"
268
294
  task prepare: :load_config do
295
+ seed = false
296
+
269
297
  ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
270
298
  ActiveRecord::Base.establish_connection(db_config.config)
271
- db_namespace["migrate"].invoke
299
+
300
+ ActiveRecord::Tasks::DatabaseTasks.migrate
301
+
302
+ # Skipped when no database
303
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config.config, ActiveRecord::Base.schema_format, db_config.spec_name)
304
+
272
305
  rescue ActiveRecord::NoDatabaseError
273
- db_namespace["setup"].invoke
306
+ ActiveRecord::Tasks::DatabaseTasks.create_current(db_config.env_name, db_config.spec_name)
307
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(
308
+ db_config.config,
309
+ ActiveRecord::Base.schema_format,
310
+ nil,
311
+ db_config.env_name,
312
+ db_config.spec_name
313
+ )
314
+
315
+ seed = true
274
316
  end
317
+
318
+ ActiveRecord::Base.establish_connection
319
+ ActiveRecord::Tasks::DatabaseTasks.load_seed if seed
275
320
  end
276
321
 
277
322
  desc "Loads the seed data from db/seeds.rb"
@@ -336,13 +381,9 @@ db_namespace = namespace :db do
336
381
  namespace :schema do
337
382
  desc "Creates a db/schema.rb file that is portable against any DB supported by Active Record"
338
383
  task dump: :load_config do
339
- require "active_record/schema_dumper"
340
384
  ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
341
- filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.spec_name, :ruby)
342
- File.open(filename, "w:utf-8") do |file|
343
- ActiveRecord::Base.establish_connection(db_config.config)
344
- ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
345
- end
385
+ ActiveRecord::Base.establish_connection(db_config.config)
386
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config.config, :ruby, db_config.spec_name)
346
387
  end
347
388
 
348
389
  db_namespace["schema:dump"].reenable
@@ -385,14 +426,7 @@ db_namespace = namespace :db do
385
426
  task dump: :load_config do
386
427
  ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
387
428
  ActiveRecord::Base.establish_connection(db_config.config)
388
- filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.spec_name, :sql)
389
- ActiveRecord::Tasks::DatabaseTasks.structure_dump(db_config.config, filename)
390
- if ActiveRecord::SchemaMigration.table_exists?
391
- File.open(filename, "a") do |f|
392
- f.puts ActiveRecord::Base.connection.dump_schema_information
393
- f.print "\n"
394
- end
395
- end
429
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config.config, :sql, db_config.spec_name)
396
430
  end
397
431
 
398
432
  db_namespace["structure:dump"].reenable