diff options
-rw-r--r-- | activejob/test/cases/test_helper_test.rb | 18 | ||||
-rw-r--r-- | activerecord/lib/active_record/railties/databases.rake | 42 | ||||
-rw-r--r-- | activerecord/lib/active_record/tasks/database_tasks.rb | 14 | ||||
-rw-r--r-- | guides/source/testing.md | 19 | ||||
-rw-r--r-- | railties/test/application/rake/multi_dbs_test.rb | 59 | ||||
-rw-r--r-- | railties/test/generators/model_generator_test.rb | 13 |
6 files changed, 143 insertions, 22 deletions
diff --git a/activejob/test/cases/test_helper_test.rb b/activejob/test/cases/test_helper_test.rb index d6607cb6b6..32471cfacc 100644 --- a/activejob/test/cases/test_helper_test.rb +++ b/activejob/test/cases/test_helper_test.rb @@ -1710,28 +1710,28 @@ class PerformedJobsTest < ActiveJob::TestCase def test_assert_performed_with_time now = Time.now - args = [{ argument1: { now: now } }] + args = [{ argument1: { now: now }, argument2: now }] - assert_enqueued_with(job: MultipleKwargsJob, args: args) do - MultipleKwargsJob.perform_later(argument1: { now: now }) + assert_performed_with(job: MultipleKwargsJob, args: args) do + MultipleKwargsJob.perform_later(argument1: { now: now }, argument2: now) end end def test_assert_performed_with_date_time now = DateTime.now - args = [{ argument1: { now: now } }] + args = [{ argument1: { now: now }, argument2: now }] - assert_enqueued_with(job: MultipleKwargsJob, args: args) do - MultipleKwargsJob.perform_later(argument1: { now: now }) + assert_performed_with(job: MultipleKwargsJob, args: args) do + MultipleKwargsJob.perform_later(argument1: { now: now }, argument2: now) end end def test_assert_performed_with_time_with_zone now = Time.now.in_time_zone("Tokyo") - args = [{ argument1: { now: now } }] + args = [{ argument1: { now: now }, argument2: now }] - assert_enqueued_with(job: MultipleKwargsJob, args: args) do - MultipleKwargsJob.perform_later(argument1: { now: now }) + assert_performed_with(job: MultipleKwargsJob, args: args) do + MultipleKwargsJob.perform_later(argument1: { now: now }, argument2: now) end end diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 64a4cb0886..e0bc5180c0 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -128,6 +128,8 @@ db_namespace = namespace :db do # desc 'Runs the "up" for a given migration VERSION.' task up: :load_config do + ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:up") + raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty? ActiveRecord::Tasks::DatabaseTasks.check_target_version @@ -139,8 +141,29 @@ db_namespace = namespace :db do db_namespace["_dump"].invoke end + namespace :up do + ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name| + task spec_name => :load_config do + raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty? + + db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name) + + ActiveRecord::Base.establish_connection(db_config.config) + ActiveRecord::Tasks::DatabaseTasks.check_target_version + ActiveRecord::Base.connection.migration_context.run( + :up, + ActiveRecord::Tasks::DatabaseTasks.target_version + ) + + db_namespace["_dump"].invoke + end + end + end + # desc 'Runs the "down" for a given migration VERSION.' task down: :load_config do + ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:down") + raise "VERSION is required - To go down one migration, use db:rollback" if !ENV["VERSION"] || ENV["VERSION"].empty? ActiveRecord::Tasks::DatabaseTasks.check_target_version @@ -152,6 +175,25 @@ db_namespace = namespace :db do db_namespace["_dump"].invoke end + namespace :down do + ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name| + task spec_name => :load_config do + raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty? + + db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name) + + ActiveRecord::Base.establish_connection(db_config.config) + ActiveRecord::Tasks::DatabaseTasks.check_target_version + ActiveRecord::Base.connection.migration_context.run( + :down, + ActiveRecord::Tasks::DatabaseTasks.target_version + ) + + db_namespace["_dump"].invoke + end + end + end + desc "Display status of migrations" task status: :load_config do ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config| diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 53e7e1e6d7..c79ed8db60 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -155,6 +155,20 @@ module ActiveRecord end end + def raise_for_multi_db(environment = env, command:) + db_configs = ActiveRecord::Base.configurations.configs_for(env_name: environment) + + if db_configs.count > 1 + dbs_list = [] + + db_configs.each do |db| + dbs_list << "#{command}:#{db.spec_name}" + end + + 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}." + end + end + def create_current(environment = env) each_current_configuration(environment) { |configuration| create configuration diff --git a/guides/source/testing.md b/guides/source/testing.md index 1fad02812b..26448958ea 100644 --- a/guides/source/testing.md +++ b/guides/source/testing.md @@ -1733,6 +1733,25 @@ class ProductTest < ActiveSupport::TestCase end ``` +### Asserting Time Arguments in Jobs + +When serializing job arguments, `Time`, `DateTime`, and `ActiveSupport::TimeWithZone` lose microsecond precision. This means comparing deserialized time with actual time doesn't always work. To compensate for the loss of precision, `assert_enqueued_with` and `assert_performed_with` will remove microseconds from time objects in argument assertions. + +```ruby +require 'test_helper' + +class ProductTest < ActiveSupport::TestCase + include ActiveJob::TestHelper + + test 'that product is reserved at a given time' do + now = Time.now + assert_performed_with(job: ReservationJob, args: [product, now]) do + product.reserve(now) + end + end +end +``` + Testing Action Cable -------------------- diff --git a/railties/test/application/rake/multi_dbs_test.rb b/railties/test/application/rake/multi_dbs_test.rb index 147b8f94e1..31ea2246a9 100644 --- a/railties/test/application/rake/multi_dbs_test.rb +++ b/railties/test/application/rake/multi_dbs_test.rb @@ -24,7 +24,6 @@ module ApplicationTests assert_no_match(/already exists/, output) assert File.exist?(expected_database) - output = rails("db:drop") assert_match(/Dropped database/, output) assert_match_namespace(namespace, output) @@ -137,6 +136,36 @@ module ApplicationTests end end + def db_up_and_down(version, namespace = nil) + Dir.chdir(app_path) do + generate_models_for_animals + rails("db:migrate") + + if namespace + down_output = rails("db:migrate:down:#{namespace}", "VERSION=#{version}") + up_output = rails("db:migrate:up:#{namespace}", "VERSION=#{version}") + else + assert_raises RuntimeError, /You're using a multiple database application/ do + down_output = rails("db:migrate:down", "VERSION=#{version}") + end + + assert_raises RuntimeError, /You're using a multiple database application/ do + up_output = rails("db:migrate:up", "VERSION=#{version}") + end + end + + case namespace + when "primary" + assert_match(/OneMigration: reverting/, down_output) + assert_match(/OneMigration: migrated/, up_output) + when nil + else + assert_match(/TwoMigration: reverting/, down_output) + assert_match(/TwoMigration: migrated/, up_output) + end + end + end + def db_prepare Dir.chdir(app_path) do generate_models_for_animals @@ -219,6 +248,34 @@ module ApplicationTests end end + test "db:migrate:down and db:migrate:up without a namespace raises in a multi-db application" do + require "#{app_path}/config/environment" + + app_file "db/migrate/01_one_migration.rb", <<-MIGRATION + class OneMigration < ActiveRecord::Migration::Current + end + MIGRATION + + db_up_and_down "01" + end + + test "db:migrate:down:namespace and db:migrate:up:namespace works" do + require "#{app_path}/config/environment" + + app_file "db/migrate/01_one_migration.rb", <<-MIGRATION + class OneMigration < ActiveRecord::Migration::Current + end + MIGRATION + + app_file "db/animals_migrate/02_two_migration.rb", <<-MIGRATION + class TwoMigration < ActiveRecord::Migration::Current + end + MIGRATION + + db_up_and_down "01", "primary" + db_up_and_down "02", "animals" + end + test "db:migrate:status works on all databases" do require "#{app_path}/config/environment" db_migrate_and_migrate_status diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb index df765432bc..d6abaf7a6f 100644 --- a/railties/test/generators/model_generator_test.rb +++ b/railties/test/generators/model_generator_test.rb @@ -422,18 +422,7 @@ class ModelGeneratorTest < Rails::Generators::TestCase end end - def test_required_polymorphic_belongs_to_generates_correct_model - run_generator ["account", "supplier:references{polymorphic}"] - - expected_file = <<~FILE - class Account < ApplicationRecord - belongs_to :supplier, polymorphic: true - end - FILE - assert_file "app/models/account.rb", expected_file - end - - def test_required_and_polymorphic_are_order_independent + def test_polymorphic_belongs_to_generates_correct_model run_generator ["account", "supplier:references{polymorphic}"] expected_file = <<~FILE |