aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activejob/test/cases/test_helper_test.rb18
-rw-r--r--activerecord/lib/active_record/railties/databases.rake42
-rw-r--r--activerecord/lib/active_record/tasks/database_tasks.rb14
-rw-r--r--guides/source/testing.md19
-rw-r--r--railties/test/application/rake/multi_dbs_test.rb59
-rw-r--r--railties/test/generators/model_generator_test.rb13
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