aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test')
-rw-r--r--activerecord/test/cases/adapter_test.rb4
-rw-r--r--activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb83
-rw-r--r--activerecord/test/cases/adapters/postgresql/range_test.rb16
-rw-r--r--activerecord/test/cases/adapters/postgresql/uuid_test.rb6
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb9
-rw-r--r--activerecord/test/cases/associations/cascaded_eager_loading_test.rb6
-rw-r--r--activerecord/test/cases/associations/eager_test.rb14
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb57
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb4
-rw-r--r--activerecord/test/cases/base_test.rb16
-rw-r--r--activerecord/test/cases/bind_parameter_test.rb12
-rw-r--r--activerecord/test/cases/calculations_test.rb5
-rw-r--r--activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb10
-rw-r--r--activerecord/test/cases/database_configurations_test.rb117
-rw-r--r--activerecord/test/cases/database_selector_test.rb4
-rw-r--r--activerecord/test/cases/finder_test.rb10
-rw-r--r--activerecord/test/cases/legacy_configurations_test.rb43
-rw-r--r--activerecord/test/cases/migration/change_schema_test.rb6
-rw-r--r--activerecord/test/cases/migration/columns_test.rb11
-rw-r--r--activerecord/test/cases/migration/foreign_key_test.rb184
-rw-r--r--activerecord/test/cases/migration/references_foreign_key_test.rb31
-rw-r--r--activerecord/test/cases/relation/delegation_test.rb2
-rw-r--r--activerecord/test/cases/relation/mutation_test.rb4
-rw-r--r--activerecord/test/cases/relation/where_test.rb8
-rw-r--r--activerecord/test/cases/relations_test.rb89
-rw-r--r--activerecord/test/cases/scoping/named_scoping_test.rb9
-rw-r--r--activerecord/test/models/bird.rb4
-rw-r--r--activerecord/test/models/company.rb2
-rw-r--r--activerecord/test/models/contract.rb8
-rw-r--r--activerecord/test/models/post.rb5
-rw-r--r--activerecord/test/models/rating.rb1
-rw-r--r--activerecord/test/models/reply.rb2
-rw-r--r--activerecord/test/models/topic.rb3
-rw-r--r--activerecord/test/schema/schema.rb1
34 files changed, 581 insertions, 205 deletions
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb
index 05d8aa59c4..2baf3db49a 100644
--- a/activerecord/test/cases/adapter_test.rb
+++ b/activerecord/test/cases/adapter_test.rb
@@ -348,6 +348,10 @@ module ActiveRecord
assert_equal "special_db_type", @connection.type_to_sql(:special_db_type)
end
+ def test_supports_foreign_keys_in_create_is_deprecated
+ assert_deprecated { @connection.supports_foreign_keys_in_create? }
+ end
+
def test_supports_multi_insert_is_deprecated
assert_deprecated { @connection.supports_multi_insert? }
end
diff --git a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb
index 7bc86476b6..ed3f669331 100644
--- a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb
@@ -56,7 +56,7 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase
@conn.columns_for_distinct("posts.id", [order])
end
- def test_errors_for_bigint_fks_on_integer_pk_table
+ def test_errors_for_bigint_fks_on_integer_pk_table_in_alter_table
# table old_cars has primary key of integer
error = assert_raises(ActiveRecord::MismatchedForeignKey) do
@@ -64,9 +64,86 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase
@conn.add_foreign_key :engines, :old_cars
end
- assert_match "Column `old_car_id` on table `engines` has a type of `bigint(20)`", error.message
+ assert_includes error.message, <<~MSG.squish
+ Column `old_car_id` on table `engines` does not match column `id` on `old_cars`,
+ which has type `int(11)`. To resolve this issue, change the type of the `old_car_id`
+ column on `engines` to be :integer. (For example `t.integer :old_car_id`).
+ MSG
assert_not_nil error.cause
- @conn.exec_query("ALTER TABLE engines DROP COLUMN old_car_id")
+ ensure
+ @conn.execute("ALTER TABLE engines DROP COLUMN old_car_id") rescue nil
+ end
+
+ def test_errors_for_bigint_fks_on_integer_pk_table_in_create_table
+ # table old_cars has primary key of integer
+
+ error = assert_raises(ActiveRecord::MismatchedForeignKey) do
+ @conn.execute(<<~SQL)
+ CREATE TABLE activerecord_unittest.foos (
+ id bigint NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ old_car_id bigint,
+ INDEX index_foos_on_old_car_id (old_car_id),
+ CONSTRAINT fk_rails_ff771f3c96 FOREIGN KEY (old_car_id) REFERENCES old_cars (id)
+ )
+ SQL
+ end
+
+ assert_includes error.message, <<~MSG.squish
+ Column `old_car_id` on table `foos` does not match column `id` on `old_cars`,
+ which has type `int(11)`. To resolve this issue, change the type of the `old_car_id`
+ column on `foos` to be :integer. (For example `t.integer :old_car_id`).
+ MSG
+ assert_not_nil error.cause
+ ensure
+ @conn.drop_table :foos, if_exists: true
+ end
+
+ def test_errors_for_integer_fks_on_bigint_pk_table_in_create_table
+ # table old_cars has primary key of bigint
+
+ error = assert_raises(ActiveRecord::MismatchedForeignKey) do
+ @conn.execute(<<~SQL)
+ CREATE TABLE activerecord_unittest.foos (
+ id bigint NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ car_id int,
+ INDEX index_foos_on_car_id (car_id),
+ CONSTRAINT fk_rails_ff771f3c96 FOREIGN KEY (car_id) REFERENCES cars (id)
+ )
+ SQL
+ end
+
+ assert_includes error.message, <<~MSG.squish
+ Column `car_id` on table `foos` does not match column `id` on `cars`,
+ which has type `bigint(20)`. To resolve this issue, change the type of the `car_id`
+ column on `foos` to be :bigint. (For example `t.bigint :car_id`).
+ MSG
+ assert_not_nil error.cause
+ ensure
+ @conn.drop_table :foos, if_exists: true
+ end
+
+ def test_errors_for_bigint_fks_on_string_pk_table_in_create_table
+ # table old_cars has primary key of string
+
+ error = assert_raises(ActiveRecord::MismatchedForeignKey) do
+ @conn.execute(<<~SQL)
+ CREATE TABLE activerecord_unittest.foos (
+ id bigint NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ subscriber_id bigint,
+ INDEX index_foos_on_subscriber_id (subscriber_id),
+ CONSTRAINT fk_rails_ff771f3c96 FOREIGN KEY (subscriber_id) REFERENCES subscribers (nick)
+ )
+ SQL
+ end
+
+ assert_includes error.message, <<~MSG.squish
+ Column `subscriber_id` on table `foos` does not match column `nick` on `subscribers`,
+ which has type `varchar(255)`. To resolve this issue, change the type of the `subscriber_id`
+ column on `foos` to be :string. (For example `t.string :subscriber_id`).
+ MSG
+ assert_not_nil error.cause
+ ensure
+ @conn.drop_table :foos, if_exists: true
end
def test_errors_when_an_insert_query_is_called_while_preventing_writes
diff --git a/activerecord/test/cases/adapters/postgresql/range_test.rb b/activerecord/test/cases/adapters/postgresql/range_test.rb
index 478cd5aa76..068f1e8bea 100644
--- a/activerecord/test/cases/adapters/postgresql/range_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/range_test.rb
@@ -375,6 +375,22 @@ class PostgresqlRangeTest < ActiveRecord::PostgreSQLTestCase
assert_equal(-Float::INFINITY...Float::INFINITY, record.float_range)
end
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.6.0")
+ def test_endless_range_values
+ record = PostgresqlRange.create!(
+ int4_range: eval("1.."),
+ int8_range: eval("10.."),
+ float_range: eval("0.5..")
+ )
+
+ record = PostgresqlRange.find(record.id)
+
+ assert_equal 1...Float::INFINITY, record.int4_range
+ assert_equal 10...Float::INFINITY, record.int8_range
+ assert_equal 0.5...Float::INFINITY, record.float_range
+ end
+ end
+
private
def assert_equal_round_trip(range, attribute, value)
round_trip(range, attribute, value)
diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb
index 9912763c1b..6591d50d06 100644
--- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb
@@ -114,6 +114,12 @@ class PostgresqlUUIDTest < ActiveRecord::PostgreSQLTestCase
assert_equal "foobar", uuid.guid_before_type_cast
end
+ def test_invalid_uuid_dont_match_to_nil
+ UUIDType.create!
+ assert_empty UUIDType.where(guid: "")
+ assert_empty UUIDType.where(guid: "foobar")
+ end
+
def test_acceptable_uuid_regex
# Valid uuids
["A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11",
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index c01138c059..3525fa2ab8 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -448,8 +448,13 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
end
def test_with_select
- assert_equal 1, Company.find(2).firm_with_select.attributes.size
- assert_equal 1, Company.all.merge!(includes: :firm_with_select).find(2).firm_with_select.attributes.size
+ assert_equal 1, Post.find(2).author_with_select.attributes.size
+ assert_equal 1, Post.includes(:author_with_select).find(2).author_with_select.attributes.size
+ end
+
+ def test_custom_attribute_with_select
+ assert_equal 2, Company.find(2).firm_with_select.attributes.size
+ assert_equal 2, Company.includes(:firm_with_select).find(2).firm_with_select.attributes.size
end
def test_belongs_to_without_counter_cache_option
diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb
index a9e22c7643..b9e16cab21 100644
--- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb
+++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb
@@ -18,7 +18,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase
:categorizations, :people, :categories, :edges, :vertices
def test_eager_association_loading_with_cascaded_two_levels
- authors = Author.all.merge!(includes: { posts: :comments }, order: "authors.id").to_a
+ authors = Author.includes(posts: :comments).order(:id).to_a
assert_equal 3, authors.size
assert_equal 5, authors[0].posts.size
assert_equal 3, authors[1].posts.size
@@ -26,7 +26,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase
end
def test_eager_association_loading_with_cascaded_two_levels_and_one_level
- authors = Author.all.merge!(includes: [{ posts: :comments }, :categorizations], order: "authors.id").to_a
+ authors = Author.includes({ posts: :comments }, :categorizations).order(:id).to_a
assert_equal 3, authors.size
assert_equal 5, authors[0].posts.size
assert_equal 3, authors[1].posts.size
@@ -36,7 +36,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase
end
def test_eager_association_loading_with_hmt_does_not_table_name_collide_when_joining_associations
- authors = Author.joins(:posts).eager_load(:comments).where(posts: { tags_count: 1 }).to_a
+ authors = Author.joins(:posts).eager_load(:comments).where(posts: { tags_count: 1 }).order(:id).to_a
assert_equal 3, assert_no_queries { authors.size }
assert_equal 10, assert_no_queries { authors[0].comments.size }
end
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index b37e59038e..126d512068 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -4,6 +4,7 @@ require "cases/helper"
require "models/post"
require "models/tagging"
require "models/tag"
+require "models/rating"
require "models/comment"
require "models/author"
require "models/essay"
@@ -44,7 +45,7 @@ end
class EagerAssociationTest < ActiveRecord::TestCase
fixtures :posts, :comments, :authors, :essays, :author_addresses, :categories, :categories_posts,
- :companies, :accounts, :tags, :taggings, :people, :readers, :categorizations,
+ :companies, :accounts, :tags, :taggings, :ratings, :people, :readers, :categorizations,
:owners, :pets, :author_favorites, :jobs, :references, :subscribers, :subscriptions, :books,
:developers, :projects, :developers_projects, :members, :memberships, :clubs, :sponsors
@@ -89,6 +90,17 @@ class EagerAssociationTest < ActiveRecord::TestCase
"expected to find only david's posts"
end
+ def test_loading_polymorphic_association_with_mixed_table_conditions
+ rating = Rating.first
+ assert_equal [taggings(:normal_comment_rating)], rating.taggings_without_tag
+
+ rating = Rating.preload(:taggings_without_tag).first
+ assert_equal [taggings(:normal_comment_rating)], rating.taggings_without_tag
+
+ rating = Rating.eager_load(:taggings_without_tag).first
+ assert_equal [taggings(:normal_comment_rating)], rating.taggings_without_tag
+ end
+
def test_loading_with_scope_including_joins
member = Member.first
assert_equal members(:groucho), member
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 38e25a9100..6a7efe2121 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1230,10 +1230,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_not_predicate Ship.reflect_on_association(:treasures), :has_cached_counter?
# Count should come from sql count() of treasures rather than treasures_count attribute
- assert_queries(1) do
- assert_equal ship.treasures.size, 0
- assert_predicate ship.treasures, :loaded?
- end
+ assert_equal ship.treasures.size, 0
assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed" do
ship.treasures.create(name: "Gold")
@@ -1354,20 +1351,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
post = posts(:welcome)
assert_no_queries do
assert_not_empty post.comments
- assert_equal 2, post.comments.size
- assert_not_predicate post.comments, :loaded?
- end
- post = posts(:misc_by_bob)
- assert_no_queries do
- assert_empty post.comments
- assert_predicate post.comments, :loaded?
- end
- end
-
- def test_empty_association_loading_with_counter_cache
- post = posts(:misc_by_bob)
- assert_no_queries do
- assert_empty post.comments.to_a
end
end
@@ -1755,6 +1738,14 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_nil posts.first
end
+ def test_destroy_all_on_desynced_counter_cache_association
+ category = categories(:general)
+ assert_operator category.categorizations.count, :>, 0
+
+ category.categorizations.destroy_all
+ assert_equal 0, category.categorizations.count
+ end
+
def test_destroy_on_association_clears_scope
author = Author.create!(name: "Gannon")
posts = author.posts
@@ -2004,22 +1995,24 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_not_predicate company.clients, :loaded?
end
- def test_zero_counter_cache_usage_on_unloaded_association
- car = Car.create!(name: "My AppliCar")
- assert_no_queries do
- assert_equal car.engines.size, 0
- assert_predicate car.engines, :loaded?
- end
+ def test_counter_cache_on_unloaded_association
+ car = Car.create(name: "My AppliCar")
+ assert_equal 0, car.engines.size
end
- def test_counter_cache_on_new_record_unloaded_association
- car = Car.new(name: "My AppliCar")
- # Ensure no schema queries inside assertion
- Engine.primary_key
- assert_no_queries do
- assert_equal car.engines.size, 0
- assert_predicate car.engines, :loaded?
- end
+ def test_ids_reader_cache_not_used_for_size_when_association_is_dirty
+ firm = Firm.create!(name: "Startup")
+ assert_equal 0, firm.client_ids.size
+ firm.clients.build
+ assert_equal 1, firm.clients.size
+ end
+
+ def test_ids_reader_cache_should_be_cleared_when_collection_is_deleted
+ firm = companies(:first_firm)
+ assert_equal [2, 3, 11], firm.client_ids
+ client = firm.clients.first
+ firm.clients.delete(client)
+ assert_equal [3, 11], firm.client_ids
end
def test_get_ids_ignores_include_option
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index d341dd0083..148c9dd347 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -711,6 +711,10 @@ class AttributeMethodsTest < ActiveRecord::TestCase
record.written_on = "Jan 01 00:00:00 2014"
assert_equal record, YAML.load(YAML.dump(record))
end
+ ensure
+ # NOTE: Reset column info because global topics
+ # don't have tz-aware attributes by default.
+ Topic.reset_column_information
end
test "setting a time zone-aware time in the current time zone" do
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 363593ca19..63528d09d5 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -438,12 +438,6 @@ class BasicsTest < ActiveRecord::TestCase
Post.reset_table_name
end
- if current_adapter?(:Mysql2Adapter)
- def test_update_all_with_order_and_limit
- assert_equal 1, Topic.limit(1).order("id DESC").update_all(content: "bulk updated!")
- end
- end
-
def test_null_fields
assert_nil Topic.find(1).parent_id
assert_nil Topic.create("title" => "Hey you").parent_id
@@ -691,6 +685,9 @@ class BasicsTest < ActiveRecord::TestCase
topic = Topic.find(1)
topic.attributes = attributes
assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time
+
+ topic.save!
+ assert_equal topic, Topic.find_by(attributes)
end
end
@@ -1226,14 +1223,15 @@ class BasicsTest < ActiveRecord::TestCase
end
def test_attribute_names
- assert_equal ["id", "type", "firm_id", "firm_name", "name", "client_of", "rating", "account_id", "description"],
- Company.attribute_names
+ expected = ["id", "type", "firm_id", "firm_name", "name", "client_of", "rating", "account_id", "description", "metadata"]
+ assert_equal expected, Company.attribute_names
end
def test_has_attribute
assert Company.has_attribute?("id")
assert Company.has_attribute?("type")
assert Company.has_attribute?("name")
+ assert Company.has_attribute?("metadata")
assert_not Company.has_attribute?("lastname")
assert_not Company.has_attribute?("age")
end
@@ -1535,7 +1533,7 @@ class BasicsTest < ActiveRecord::TestCase
Bird.create!(name: "Bluejay")
ActiveRecord::Base.connection.while_preventing_writes do
- assert_nothing_raised { Bird.where(name: "Bluejay").explain }
+ assert_queries(2) { Bird.where(name: "Bluejay").explain }
end
end
diff --git a/activerecord/test/cases/bind_parameter_test.rb b/activerecord/test/cases/bind_parameter_test.rb
index 22a98036f3..ca97a5dc65 100644
--- a/activerecord/test/cases/bind_parameter_test.rb
+++ b/activerecord/test/cases/bind_parameter_test.rb
@@ -44,6 +44,18 @@ if ActiveRecord::Base.connection.prepared_statements
assert_equal 0, topics.count
end
+ def test_too_many_binds_with_query_cache
+ Topic.connection.enable_query_cache!
+ bind_params_length = @connection.send(:bind_params_length)
+ topics = Topic.where(id: (1 .. bind_params_length + 1).to_a)
+ assert_equal Topic.count, topics.count
+
+ topics = Topic.where.not(id: (1 .. bind_params_length + 1).to_a)
+ assert_equal 0, topics.count
+ ensure
+ Topic.connection.disable_query_cache!
+ end
+
def test_bind_from_join_in_subquery
subquery = Author.joins(:thinking_posts).where(name: "David")
scope = Author.from(subquery, "authors").where(id: 1)
diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb
index 850bc49676..b001667ac9 100644
--- a/activerecord/test/cases/calculations_test.rb
+++ b/activerecord/test/cases/calculations_test.rb
@@ -690,8 +690,9 @@ class CalculationsTest < ActiveRecord::TestCase
end
def test_pluck_not_auto_table_name_prefix_if_column_joined
- Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
- assert_equal [7], Company.joins(:contracts).pluck(:developer_id)
+ company = Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
+ metadata = company.contracts.first.metadata
+ assert_equal [metadata], Company.joins(:contracts).pluck(:metadata)
end
def test_pluck_with_selection_clause
diff --git a/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb b/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb
index 225cccc62c..515bf5df06 100644
--- a/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb
+++ b/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb
@@ -72,6 +72,16 @@ module ActiveRecord
assert_equal expected, actual
end
+ def test_resolver_with_database_uri_and_multiple_envs
+ ENV["DATABASE_URL"] = "postgres://localhost"
+ ENV["RAILS_ENV"] = "test"
+
+ config = { "production" => { "adapter" => "postgresql", "database" => "foo_prod" }, "test" => { "adapter" => "postgresql", "database" => "foo_test" } }
+ actual = resolve_spec(:test, config)
+ expected = { "adapter" => "postgresql", "database" => "foo_test", "host" => "localhost", "name" => "test" }
+ assert_equal expected, actual
+ end
+
def test_resolver_with_database_uri_and_unknown_symbol_key
ENV["DATABASE_URL"] = "postgres://localhost/foo"
config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
diff --git a/activerecord/test/cases/database_configurations_test.rb b/activerecord/test/cases/database_configurations_test.rb
new file mode 100644
index 0000000000..ed8151f01a
--- /dev/null
+++ b/activerecord/test/cases/database_configurations_test.rb
@@ -0,0 +1,117 @@
+# frozen_string_literal: true
+
+require "cases/helper"
+
+class DatabaseConfigurationsTest < ActiveRecord::TestCase
+ unless in_memory_db?
+ def test_empty_returns_true_when_db_configs_are_empty
+ old_config = ActiveRecord::Base.configurations
+ config = {}
+
+ ActiveRecord::Base.configurations = config
+
+ assert_predicate ActiveRecord::Base.configurations, :empty?
+ assert_predicate ActiveRecord::Base.configurations, :blank?
+ ensure
+ ActiveRecord::Base.configurations = old_config
+ ActiveRecord::Base.establish_connection :arunit
+ end
+ end
+
+ def test_configs_for_getter_with_env_name
+ configs = ActiveRecord::Base.configurations.configs_for(env_name: "arunit")
+
+ assert_equal 1, configs.size
+ assert_equal ["arunit"], configs.map(&:env_name)
+ end
+
+ def test_configs_for_getter_with_env_and_spec_name
+ config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", spec_name: "primary")
+
+ assert_equal "arunit", config.env_name
+ assert_equal "primary", config.spec_name
+ end
+
+ def test_default_hash_returns_config_hash_from_default_env
+ original_rails_env = ENV["RAILS_ENV"]
+ ENV["RAILS_ENV"] = "arunit"
+
+ assert_equal ActiveRecord::Base.configurations.configs_for(env_name: "arunit", spec_name: "primary").config, ActiveRecord::Base.configurations.default_hash
+ ensure
+ ENV["RAILS_ENV"] = original_rails_env
+ end
+
+ def test_find_db_config_returns_a_db_config_object_for_the_given_env
+ config = ActiveRecord::Base.configurations.find_db_config("arunit2")
+
+ assert_equal "arunit2", config.env_name
+ assert_equal "primary", config.spec_name
+ end
+
+ def test_to_h_turns_db_config_object_back_into_a_hash
+ configs = ActiveRecord::Base.configurations
+ assert_equal "ActiveRecord::DatabaseConfigurations", configs.class.name
+ assert_equal "Hash", configs.to_h.class.name
+ assert_equal ["arunit", "arunit2", "arunit_without_prepared_statements"], ActiveRecord::Base.configurations.to_h.keys.sort
+ end
+end
+
+class LegacyDatabaseConfigurationsTest < ActiveRecord::TestCase
+ unless in_memory_db?
+ def test_setting_configurations_hash
+ old_config = ActiveRecord::Base.configurations
+ config = { "adapter" => "sqlite3" }
+
+ assert_deprecated do
+ ActiveRecord::Base.configurations["readonly"] = config
+ end
+
+ assert_equal ["arunit", "arunit2", "arunit_without_prepared_statements", "readonly"], ActiveRecord::Base.configurations.configs_for.map(&:env_name).sort
+ ensure
+ ActiveRecord::Base.configurations = old_config
+ ActiveRecord::Base.establish_connection :arunit
+ end
+ end
+
+ def test_can_turn_configurations_into_a_hash
+ assert ActiveRecord::Base.configurations.to_h.is_a?(Hash), "expected to be a hash but was not."
+ assert_equal ["arunit", "arunit2", "arunit_without_prepared_statements"].sort, ActiveRecord::Base.configurations.to_h.keys.sort
+ end
+
+ def test_each_is_deprecated
+ assert_deprecated do
+ ActiveRecord::Base.configurations.each do |db_config|
+ assert_equal "primary", db_config.spec_name
+ end
+ end
+ end
+
+ def test_first_is_deprecated
+ assert_deprecated do
+ db_config = ActiveRecord::Base.configurations.first
+ assert_equal "arunit", db_config.env_name
+ assert_equal "primary", db_config.spec_name
+ end
+ end
+
+ def test_fetch_is_deprecated
+ assert_deprecated do
+ db_config = ActiveRecord::Base.configurations.fetch("arunit").first
+ assert_equal "arunit", db_config.env_name
+ assert_equal "primary", db_config.spec_name
+ end
+ end
+
+ def test_values_are_deprecated
+ config_hashes = ActiveRecord::Base.configurations.configurations.map(&:config)
+ assert_deprecated do
+ assert_equal config_hashes, ActiveRecord::Base.configurations.values
+ end
+ end
+
+ def test_unsupported_method_raises
+ assert_raises NotImplementedError do
+ ActiveRecord::Base.configurations.select { |a| a == "foo" }
+ end
+ end
+end
diff --git a/activerecord/test/cases/database_selector_test.rb b/activerecord/test/cases/database_selector_test.rb
index 4106a6ec46..fd02d2acb4 100644
--- a/activerecord/test/cases/database_selector_test.rb
+++ b/activerecord/test/cases/database_selector_test.rb
@@ -11,6 +11,10 @@ module ActiveRecord
@session = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session.new(@session_store)
end
+ teardown do
+ ActiveRecord::Base.connection_handlers = { writing: ActiveRecord::Base.default_connection_handler }
+ end
+
def test_empty_session
assert_equal Time.at(0), @session.last_write_timestamp
end
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index 6af2a43c7f..4040682280 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -271,6 +271,16 @@ class FinderTest < ActiveRecord::TestCase
assert_equal true, Topic.exists?({})
end
+ def test_exists_with_distinct_and_offset_and_joins
+ assert Post.left_joins(:comments).distinct.offset(10).exists?
+ assert_not Post.left_joins(:comments).distinct.offset(11).exists?
+ end
+
+ def test_exists_with_distinct_and_offset_and_select
+ assert Post.select(:body).distinct.offset(3).exists?
+ assert_not Post.select(:body).distinct.offset(4).exists?
+ end
+
# Ensure +exists?+ runs without an error by excluding distinct value.
# See https://github.com/rails/rails/pull/26981.
def test_exists_with_order_and_distinct
diff --git a/activerecord/test/cases/legacy_configurations_test.rb b/activerecord/test/cases/legacy_configurations_test.rb
deleted file mode 100644
index c36feb5116..0000000000
--- a/activerecord/test/cases/legacy_configurations_test.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require "cases/helper"
-
-module ActiveRecord
- class LegacyConfigurationsTest < ActiveRecord::TestCase
- def test_can_turn_configurations_into_a_hash
- assert ActiveRecord::Base.configurations.to_h.is_a?(Hash), "expected to be a hash but was not."
- assert_equal ["arunit", "arunit2", "arunit_without_prepared_statements"].sort, ActiveRecord::Base.configurations.to_h.keys.sort
- end
-
- def test_each_is_deprecated
- assert_deprecated do
- ActiveRecord::Base.configurations.each do |db_config|
- assert_equal "primary", db_config.spec_name
- end
- end
- end
-
- def test_first_is_deprecated
- assert_deprecated do
- db_config = ActiveRecord::Base.configurations.first
- assert_equal "arunit", db_config.env_name
- assert_equal "primary", db_config.spec_name
- end
- end
-
- def test_fetch_is_deprecated
- assert_deprecated do
- db_config = ActiveRecord::Base.configurations.fetch("arunit").first
- assert_equal "arunit", db_config.env_name
- assert_equal "primary", db_config.spec_name
- end
- end
-
- def test_values_are_deprecated
- config_hashes = ActiveRecord::Base.configurations.configurations.map(&:config)
- assert_deprecated do
- assert_equal config_hashes, ActiveRecord::Base.configurations.values
- end
- end
- end
-end
diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb
index 7777508349..cc0587fa50 100644
--- a/activerecord/test/cases/migration/change_schema_test.rb
+++ b/activerecord/test/cases/migration/change_schema_test.rb
@@ -462,7 +462,11 @@ module ActiveRecord
end
def test_create_table_with_force_cascade_drops_dependent_objects
- skip "MySQL > 5.5 does not drop dependent objects with DROP TABLE CASCADE" if current_adapter?(:Mysql2Adapter)
+ if current_adapter?(:Mysql2Adapter)
+ skip "MySQL > 5.5 does not drop dependent objects with DROP TABLE CASCADE"
+ elsif current_adapter?(:SQLite3Adapter)
+ skip "SQLite3 does not support DROP TABLE CASCADE syntax"
+ end
# can't re-create table referenced by foreign key
assert_raises(ActiveRecord::StatementInvalid) do
@connection.create_table :trains, force: true
diff --git a/activerecord/test/cases/migration/columns_test.rb b/activerecord/test/cases/migration/columns_test.rb
index cedd9c44e3..1c66c8186f 100644
--- a/activerecord/test/cases/migration/columns_test.rb
+++ b/activerecord/test/cases/migration/columns_test.rb
@@ -318,6 +318,17 @@ module ActiveRecord
ensure
connection.drop_table(:my_table) rescue nil
end
+
+ def test_add_column_without_column_name
+ e = assert_raise ArgumentError do
+ connection.create_table "my_table", force: true do |t|
+ t.timestamp
+ end
+ end
+ assert_equal "Missing column name(s) for timestamp", e.message
+ ensure
+ connection.drop_table :my_table, if_exists: true
+ end
end
end
end
diff --git a/activerecord/test/cases/migration/foreign_key_test.rb b/activerecord/test/cases/migration/foreign_key_test.rb
index bb233fbf74..6547ebb5d1 100644
--- a/activerecord/test/cases/migration/foreign_key_test.rb
+++ b/activerecord/test/cases/migration/foreign_key_test.rb
@@ -3,7 +3,7 @@
require "cases/helper"
require "support/schema_dumping_helper"
-if ActiveRecord::Base.connection.supports_foreign_keys_in_create?
+if ActiveRecord::Base.connection.supports_foreign_keys?
module ActiveRecord
class Migration
class ForeignKeyInCreateTest < ActiveRecord::TestCase
@@ -20,9 +20,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys_in_create?
end
end
- class ForeignKeyChangeColumnTest < ActiveRecord::TestCase
- self.use_transactional_tests = false
-
+ module ForeignKeyChangeColumnSharedTest
class Rocket < ActiveRecord::Base
has_many :astronauts
end
@@ -31,24 +29,39 @@ if ActiveRecord::Base.connection.supports_foreign_keys_in_create?
belongs_to :rocket
end
- setup do
- @connection = ActiveRecord::Base.connection
- @connection.create_table "rockets", force: true do |t|
- t.string :name
+ class CreateRocketsMigration < ActiveRecord::Migration::Current
+ def up
+ create_table :rockets do |t|
+ t.string :name
+ end
+
+ create_table :astronauts do |t|
+ t.string :name
+ t.references :rocket, foreign_key: true
+ end
end
- @connection.create_table "astronauts", force: true do |t|
- t.string :name
- t.references :rocket, foreign_key: true
+ def down
+ drop_table :astronauts, if_exists: true
+ drop_table :rockets, if_exists: true
end
+ end
+
+ def setup
+ @connection = ActiveRecord::Base.connection
+ @migration = CreateRocketsMigration.new
+ silence_stream($stdout) { @migration.migrate(:up) }
+ Rocket.reset_table_name
Rocket.reset_column_information
+ Astronaut.reset_table_name
Astronaut.reset_column_information
end
- teardown do
- @connection.drop_table "astronauts", if_exists: true
- @connection.drop_table "rockets", if_exists: true
+ def teardown
+ silence_stream($stdout) { @migration.migrate(:down) }
+ Rocket.reset_table_name
Rocket.reset_column_information
+ Astronaut.reset_table_name
Astronaut.reset_column_information
end
@@ -56,53 +69,114 @@ if ActiveRecord::Base.connection.supports_foreign_keys_in_create?
rocket = Rocket.create!(name: "myrocket")
rocket.astronauts << Astronaut.create!
- @connection.change_column_null :rockets, :name, false
+ @connection.change_column_null Rocket.table_name, :name, false
- foreign_keys = @connection.foreign_keys("astronauts")
+ foreign_keys = @connection.foreign_keys(Astronaut.table_name)
assert_equal 1, foreign_keys.size
fk = foreign_keys.first
assert_equal "myrocket", Rocket.first.name
- assert_equal "astronauts", fk.from_table
- assert_equal "rockets", fk.to_table
+ assert_equal Astronaut.table_name, fk.from_table
+ assert_equal Rocket.table_name, fk.to_table
end
def test_rename_column_of_child_table
rocket = Rocket.create!(name: "myrocket")
rocket.astronauts << Astronaut.create!
- @connection.rename_column :astronauts, :name, :astronaut_name
+ @connection.rename_column Astronaut.table_name, :name, :astronaut_name
- foreign_keys = @connection.foreign_keys("astronauts")
+ foreign_keys = @connection.foreign_keys(Astronaut.table_name)
assert_equal 1, foreign_keys.size
fk = foreign_keys.first
assert_equal "myrocket", Rocket.first.name
- assert_equal "astronauts", fk.from_table
- assert_equal "rockets", fk.to_table
+ assert_equal Astronaut.table_name, fk.from_table
+ assert_equal Rocket.table_name, fk.to_table
end
def test_rename_reference_column_of_child_table
rocket = Rocket.create!(name: "myrocket")
rocket.astronauts << Astronaut.create!
- @connection.rename_column :astronauts, :rocket_id, :new_rocket_id
+ @connection.rename_column Astronaut.table_name, :rocket_id, :new_rocket_id
- foreign_keys = @connection.foreign_keys("astronauts")
+ foreign_keys = @connection.foreign_keys(Astronaut.table_name)
assert_equal 1, foreign_keys.size
fk = foreign_keys.first
assert_equal "myrocket", Rocket.first.name
- assert_equal "astronauts", fk.from_table
- assert_equal "rockets", fk.to_table
+ assert_equal Astronaut.table_name, fk.from_table
+ assert_equal Rocket.table_name, fk.to_table
assert_equal "new_rocket_id", fk.options[:column]
end
+
+ def test_remove_reference_column_of_child_table
+ rocket = Rocket.create!(name: "myrocket")
+ rocket.astronauts << Astronaut.create!
+
+ @connection.remove_column Astronaut.table_name, :rocket_id
+
+ assert_empty @connection.foreign_keys(Astronaut.table_name)
+ end
+
+ def test_remove_foreign_key_by_column
+ rocket = Rocket.create!(name: "myrocket")
+ rocket.astronauts << Astronaut.create!
+
+ @connection.remove_foreign_key Astronaut.table_name, column: :rocket_id
+
+ assert_empty @connection.foreign_keys(Astronaut.table_name)
+ end
+
+ def test_remove_foreign_key_by_column_in_change_table
+ rocket = Rocket.create!(name: "myrocket")
+ rocket.astronauts << Astronaut.create!
+
+ @connection.change_table Astronaut.table_name do |t|
+ t.remove_foreign_key column: :rocket_id
+ end
+
+ assert_empty @connection.foreign_keys(Astronaut.table_name)
+ end
+ end
+
+ class ForeignKeyChangeColumnTest < ActiveRecord::TestCase
+ include ForeignKeyChangeColumnSharedTest
+
+ self.use_transactional_tests = false
+ end
+
+ class ForeignKeyChangeColumnWithPrefixTest < ActiveRecord::TestCase
+ include ForeignKeyChangeColumnSharedTest
+
+ self.use_transactional_tests = false
+
+ setup do
+ ActiveRecord::Base.table_name_prefix = "p_"
+ end
+
+ teardown do
+ ActiveRecord::Base.table_name_prefix = nil
+ end
+ end
+
+ class ForeignKeyChangeColumnWithSuffixTest < ActiveRecord::TestCase
+ include ForeignKeyChangeColumnSharedTest
+
+ self.use_transactional_tests = false
+
+ setup do
+ ActiveRecord::Base.table_name_suffix = "_p"
+ end
+
+ teardown do
+ ActiveRecord::Base.table_name_suffix = nil
+ end
end
end
end
-end
-if ActiveRecord::Base.connection.supports_foreign_keys?
module ActiveRecord
class Migration
class ForeignKeyTest < ActiveRecord::TestCase
@@ -141,7 +215,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
assert_equal "fk_test_has_pk", fk.to_table
assert_equal "fk_id", fk.column
assert_equal "pk_id", fk.primary_key
- assert_equal "fk_name", fk.name
+ assert_equal "fk_name", fk.name unless current_adapter?(:SQLite3Adapter)
end
def test_add_foreign_key_inferes_column
@@ -155,7 +229,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
assert_equal "rockets", fk.to_table
assert_equal "rocket_id", fk.column
assert_equal "id", fk.primary_key
- assert_equal("fk_rails_78146ddd2e", fk.name)
+ assert_equal "fk_rails_78146ddd2e", fk.name unless current_adapter?(:SQLite3Adapter)
end
def test_add_foreign_key_with_column
@@ -169,7 +243,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
assert_equal "rockets", fk.to_table
assert_equal "rocket_id", fk.column
assert_equal "id", fk.primary_key
- assert_equal("fk_rails_78146ddd2e", fk.name)
+ assert_equal "fk_rails_78146ddd2e", fk.name unless current_adapter?(:SQLite3Adapter)
end
def test_add_foreign_key_with_non_standard_primary_key
@@ -188,7 +262,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
assert_equal "space_shuttles", fk.to_table
assert_equal "pk", fk.primary_key
ensure
- @connection.remove_foreign_key :astronauts, name: "custom_pk"
+ @connection.remove_foreign_key :astronauts, name: "custom_pk", to_table: "space_shuttles"
@connection.drop_table :space_shuttles
end
@@ -262,6 +336,8 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
end
def test_foreign_key_exists_by_name
+ skip if current_adapter?(:SQLite3Adapter)
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", name: "fancy_named_fk"
assert @connection.foreign_key_exists?(:astronauts, name: "fancy_named_fk")
@@ -293,6 +369,8 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
end
def test_remove_foreign_key_by_name
+ skip if current_adapter?(:SQLite3Adapter)
+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", name: "fancy_named_fk"
assert_equal 1, @connection.foreign_keys("astronauts").size
@@ -301,9 +379,10 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
end
def test_remove_foreign_non_existing_foreign_key_raises
- assert_raises ArgumentError do
+ e = assert_raises ArgumentError do
@connection.remove_foreign_key :astronauts, :rockets
end
+ assert_equal "Table 'astronauts' has no foreign key for rockets", e.message
end
if ActiveRecord::Base.connection.supports_validate_constraints?
@@ -382,7 +461,11 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
def test_schema_dumping_with_options
output = dump_table_schema "fk_test_has_fk"
- assert_match %r{\s+add_foreign_key "fk_test_has_fk", "fk_test_has_pk", column: "fk_id", primary_key: "pk_id", name: "fk_name"$}, output
+ if current_adapter?(:SQLite3Adapter)
+ assert_match %r{\s+add_foreign_key "fk_test_has_fk", "fk_test_has_pk", column: "fk_id", primary_key: "pk_id"$}, output
+ else
+ assert_match %r{\s+add_foreign_key "fk_test_has_fk", "fk_test_has_pk", column: "fk_id", primary_key: "pk_id", name: "fk_name"$}, output
+ end
end
def test_schema_dumping_with_custom_fk_ignore_pattern
@@ -436,7 +519,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
end
class CreateSchoolsAndClassesMigration < ActiveRecord::Migration::Current
- def change
+ def up
create_table(:schools)
create_table(:classes) do |t|
@@ -444,6 +527,11 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
end
add_foreign_key :classes, :schools
end
+
+ def down
+ drop_table :classes, if_exists: true
+ drop_table :schools, if_exists: true
+ end
end
def test_add_foreign_key_with_prefix
@@ -468,30 +556,4 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
end
end
end
-else
- module ActiveRecord
- class Migration
- class NoForeignKeySupportTest < ActiveRecord::TestCase
- setup do
- @connection = ActiveRecord::Base.connection
- end
-
- def test_add_foreign_key_should_be_noop
- @connection.add_foreign_key :clubs, :categories
- end
-
- def test_remove_foreign_key_should_be_noop
- @connection.remove_foreign_key :clubs, :categories
- end
-
- unless current_adapter?(:SQLite3Adapter)
- def test_foreign_keys_should_raise_not_implemented
- assert_raises NotImplementedError do
- @connection.foreign_keys("clubs")
- end
- end
- end
- end
- end
- end
end
diff --git a/activerecord/test/cases/migration/references_foreign_key_test.rb b/activerecord/test/cases/migration/references_foreign_key_test.rb
index 620e9ab6ca..90a50a5651 100644
--- a/activerecord/test/cases/migration/references_foreign_key_test.rb
+++ b/activerecord/test/cases/migration/references_foreign_key_test.rb
@@ -2,7 +2,7 @@
require "cases/helper"
-if ActiveRecord::Base.connection.supports_foreign_keys_in_create?
+if ActiveRecord::Base.connection.supports_foreign_keys?
module ActiveRecord
class Migration
class ReferencesForeignKeyInCreateTest < ActiveRecord::TestCase
@@ -65,9 +65,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys_in_create?
end
end
end
-end
-if ActiveRecord::Base.connection.supports_foreign_keys?
module ActiveRecord
class Migration
class ReferencesForeignKeyTest < ActiveRecord::TestCase
@@ -172,13 +170,18 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
end
class CreateDogsMigration < ActiveRecord::Migration::Current
- def change
+ def up
create_table :dog_owners
create_table :dogs do |t|
t.references :dog_owner, foreign_key: true
end
end
+
+ def down
+ drop_table :dogs, if_exists: true
+ drop_table :dog_owners, if_exists: true
+ end
end
def test_references_foreign_key_with_prefix
@@ -232,24 +235,4 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
end
end
end
-else
- class ReferencesWithoutForeignKeySupportTest < ActiveRecord::TestCase
- setup do
- @connection = ActiveRecord::Base.connection
- @connection.create_table(:testing_parents, force: true)
- end
-
- teardown do
- @connection.drop_table("testings", if_exists: true)
- @connection.drop_table("testing_parents", if_exists: true)
- end
-
- test "ignores foreign keys defined with the table" do
- @connection.create_table :testings do |t|
- t.references :testing_parent, foreign_key: true
- end
-
- assert_includes @connection.data_sources, "testings"
- end
- end
end
diff --git a/activerecord/test/cases/relation/delegation_test.rb b/activerecord/test/cases/relation/delegation_test.rb
index 63ae438de3..4de3b1300c 100644
--- a/activerecord/test/cases/relation/delegation_test.rb
+++ b/activerecord/test/cases/relation/delegation_test.rb
@@ -50,7 +50,7 @@ module ActiveRecord
:first_or_create, :first_or_create!, :first_or_initialize,
:find_or_create_by, :find_or_create_by!, :create_or_find_by, :create_or_find_by!, :find_or_initialize_by,
:find_by, :find_by!,
- :destroy_all, :delete_all, :update_all,
+ :destroy_all, :delete_all, :update_all, :delete_by, :destroy_by,
:find_each, :find_in_batches, :in_batches,
:select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or,
:where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending,
diff --git a/activerecord/test/cases/relation/mutation_test.rb b/activerecord/test/cases/relation/mutation_test.rb
index f82ecd4449..96249b8d51 100644
--- a/activerecord/test/cases/relation/mutation_test.rb
+++ b/activerecord/test/cases/relation/mutation_test.rb
@@ -26,7 +26,7 @@ module ActiveRecord
assert relation.order!(:name).equal?(relation)
node = relation.order_values.first
assert_predicate node, :ascending?
- assert_equal :name, node.expr.name
+ assert_equal "name", node.expr.name
assert_equal "posts", node.expr.relation.name
end
@@ -89,7 +89,7 @@ module ActiveRecord
node = relation.order_values.first
assert_predicate node, :ascending?
- assert_equal :name, node.expr.name
+ assert_equal "name", node.expr.name
assert_equal "posts", node.expr.relation.name
end
diff --git a/activerecord/test/cases/relation/where_test.rb b/activerecord/test/cases/relation/where_test.rb
index d49ed092b2..bec204643b 100644
--- a/activerecord/test/cases/relation/where_test.rb
+++ b/activerecord/test/cases/relation/where_test.rb
@@ -50,8 +50,12 @@ module ActiveRecord
assert_equal [chef], chefs.to_a
end
- def test_where_with_casted_value_is_nil
- assert_equal 4, Topic.where(last_read: "").count
+ def test_where_with_invalid_value
+ topics(:first).update!(written_on: nil, bonus_time: nil, last_read: nil)
+ assert_empty Topic.where(parent_id: Object.new)
+ assert_empty Topic.where(written_on: "")
+ assert_empty Topic.where(bonus_time: "")
+ assert_empty Topic.where(last_read: "")
end
def test_rewhere_on_root
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 0ab0459c38..adc50a694e 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -14,6 +14,7 @@ require "models/person"
require "models/computer"
require "models/reply"
require "models/company"
+require "models/contract"
require "models/bird"
require "models/car"
require "models/engine"
@@ -290,8 +291,17 @@ class RelationTest < ActiveRecord::TestCase
Topic.order(Arel.sql("title NULLS FIRST")).reverse_order
end
assert_raises(ActiveRecord::IrreversibleOrderError) do
+ Topic.order(Arel.sql("title NULLS FIRST")).reverse_order
+ end
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
Topic.order(Arel.sql("title nulls last")).reverse_order
end
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
+ Topic.order(Arel.sql("title NULLS FIRST, author_name")).reverse_order
+ end
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
+ Topic.order(Arel.sql("author_name, title nulls last")).reverse_order
+ end
end
def test_default_reverse_order_on_table_without_primary_key
@@ -1166,13 +1176,23 @@ class RelationTest < ActiveRecord::TestCase
assert_equal "green", parrot.color
end
+ def test_first_or_create_with_after_initialize
+ Bird.create!(color: "yellow", name: "canary")
+ parrot = assert_deprecated do
+ Bird.where(color: "green").first_or_create do |bird|
+ bird.name = "parrot"
+ bird.enable_count = true
+ end
+ end
+ assert_equal 0, parrot.total_count
+ end
+
def test_first_or_create_with_block
- canary = Bird.create!(color: "yellow", name: "canary")
+ Bird.create!(color: "yellow", name: "canary")
parrot = Bird.where(color: "green").first_or_create do |bird|
bird.name = "parrot"
- assert_equal canary, Bird.find_by!(name: "canary")
+ assert_deprecated { assert_equal 0, Bird.count }
end
- assert_equal 1, parrot.total_count
assert_kind_of Bird, parrot
assert_predicate parrot, :persisted?
assert_equal "green", parrot.color
@@ -1213,13 +1233,23 @@ class RelationTest < ActiveRecord::TestCase
assert_raises(ActiveRecord::RecordInvalid) { Bird.where(color: "green").first_or_create! }
end
+ def test_first_or_create_bang_with_after_initialize
+ Bird.create!(color: "yellow", name: "canary")
+ parrot = assert_deprecated do
+ Bird.where(color: "green").first_or_create! do |bird|
+ bird.name = "parrot"
+ bird.enable_count = true
+ end
+ end
+ assert_equal 0, parrot.total_count
+ end
+
def test_first_or_create_bang_with_valid_block
- canary = Bird.create!(color: "yellow", name: "canary")
+ Bird.create!(color: "yellow", name: "canary")
parrot = Bird.where(color: "green").first_or_create! do |bird|
bird.name = "parrot"
- assert_equal canary, Bird.find_by!(name: "canary")
+ assert_deprecated { assert_equal 0, Bird.count }
end
- assert_equal 1, parrot.total_count
assert_kind_of Bird, parrot
assert_predicate parrot, :persisted?
assert_equal "green", parrot.color
@@ -1268,13 +1298,23 @@ class RelationTest < ActiveRecord::TestCase
assert_equal "green", parrot.color
end
+ def test_first_or_initialize_with_after_initialize
+ Bird.create!(color: "yellow", name: "canary")
+ parrot = assert_deprecated do
+ Bird.where(color: "green").first_or_initialize do |bird|
+ bird.name = "parrot"
+ bird.enable_count = true
+ end
+ end
+ assert_equal 0, parrot.total_count
+ end
+
def test_first_or_initialize_with_block
- canary = Bird.create!(color: "yellow", name: "canary")
+ Bird.create!(color: "yellow", name: "canary")
parrot = Bird.where(color: "green").first_or_initialize do |bird|
bird.name = "parrot"
- assert_equal canary, Bird.find_by!(name: "canary")
+ assert_deprecated { assert_equal 0, Bird.count }
end
- assert_equal 1, parrot.total_count
assert_kind_of Bird, parrot
assert_not_predicate parrot, :persisted?
assert_predicate parrot, :valid?
@@ -1646,6 +1686,24 @@ class RelationTest < ActiveRecord::TestCase
assert_predicate topics, :loaded?
end
+ def test_delete_by
+ david = authors(:david)
+
+ assert_difference("Post.count", -3) { david.posts.delete_by(body: "hello") }
+
+ deleted = Author.delete_by(id: david.id)
+ assert_equal 1, deleted
+ end
+
+ def test_destroy_by
+ david = authors(:david)
+
+ assert_difference("Post.count", -3) { david.posts.destroy_by(body: "hello") }
+
+ destroyed = Author.destroy_by(id: david.id)
+ assert_equal [david], destroyed
+ end
+
test "find_by with hash conditions returns the first matching record" do
assert_equal posts(:eager_other), Post.order(:id).find_by(author_id: 2)
end
@@ -1815,6 +1873,19 @@ class RelationTest < ActiveRecord::TestCase
assert_equal [1, 1, 1], posts.map(&:author_address_id)
end
+ test "joins with select custom attribute" do
+ contract = Company.create!(name: "test").contracts.create!
+ company = Company.joins(:contracts).select(:id, :metadata).find(contract.company_id)
+ assert_equal contract.metadata, company.metadata
+ end
+
+ test "joins with order by custom attribute" do
+ companies = Company.create!([{ name: "test1" }, { name: "test2" }])
+ companies.each { |company| company.contracts.create! }
+ assert_equal companies, Company.joins(:contracts).order(:metadata)
+ assert_equal companies.reverse, Company.joins(:contracts).order(metadata: :desc)
+ end
+
test "delegations do not leak to other classes" do
Topic.all.by_lifo
assert Topic.all.class.method_defined?(:by_lifo)
diff --git a/activerecord/test/cases/scoping/named_scoping_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb
index 27f9df295f..8b08e40468 100644
--- a/activerecord/test/cases/scoping/named_scoping_test.rb
+++ b/activerecord/test/cases/scoping/named_scoping_test.rb
@@ -50,7 +50,7 @@ class NamedScopingTest < ActiveRecord::TestCase
def test_calling_merge_at_first_in_scope
Topic.class_eval do
- scope :calling_merge_at_first_in_scope, Proc.new { merge(Topic.replied) }
+ scope :calling_merge_at_first_in_scope, Proc.new { merge(Topic.unscoped.replied) }
end
assert_equal Topic.calling_merge_at_first_in_scope.to_a, Topic.replied.to_a
end
@@ -447,9 +447,10 @@ class NamedScopingTest < ActiveRecord::TestCase
assert_equal [posts(:sti_comments)], Post.with_special_comments.with_post(4).to_a.uniq
end
- def test_chaining_doesnt_leak_conditions_to_another_scopes
- expected = Topic.where(approved: false).where(id: Topic.children.select(:parent_id))
- assert_equal expected.to_a, Topic.rejected.has_children.to_a
+ def test_class_method_in_scope
+ assert_deprecated do
+ assert_equal [topics(:second)], topics(:first).approved_replies.ordered
+ end
end
def test_nested_scoping
diff --git a/activerecord/test/models/bird.rb b/activerecord/test/models/bird.rb
index c9f6759c7d..20af7c6122 100644
--- a/activerecord/test/models/bird.rb
+++ b/activerecord/test/models/bird.rb
@@ -17,8 +17,8 @@ class Bird < ActiveRecord::Base
throw(:abort)
end
- attr_accessor :total_count
+ attr_accessor :total_count, :enable_count
after_initialize do
- self.total_count = Bird.count
+ self.total_count = Bird.count if enable_count
end
end
diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb
index 838f515aad..a0f48d23f1 100644
--- a/activerecord/test/models/company.rb
+++ b/activerecord/test/models/company.rb
@@ -13,6 +13,8 @@ class Company < AbstractCompany
has_many :contracts
has_many :developers, through: :contracts
+ attribute :metadata, :json
+
scope :of_first_firm, lambda {
joins(account: :firm).
where("firms.id" => 1)
diff --git a/activerecord/test/models/contract.rb b/activerecord/test/models/contract.rb
index 3f663375c4..89719775c4 100644
--- a/activerecord/test/models/contract.rb
+++ b/activerecord/test/models/contract.rb
@@ -5,7 +5,9 @@ class Contract < ActiveRecord::Base
belongs_to :developer, primary_key: :id
belongs_to :firm, foreign_key: "company_id"
- before_save :hi
+ attribute :metadata, :json
+
+ before_save :hi, :update_metadata
after_save :bye
attr_accessor :hi_count, :bye_count
@@ -19,6 +21,10 @@ class Contract < ActiveRecord::Base
@bye_count ||= 0
@bye_count += 1
end
+
+ def update_metadata
+ self.metadata = { company_id: company_id, developer_id: developer_id }
+ end
end
class NewContract < Contract
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index e32cc59399..c6eb77dba4 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -31,6 +31,7 @@ class Post < ActiveRecord::Base
belongs_to :author_with_posts, -> { includes(:posts) }, class_name: "Author", foreign_key: :author_id
belongs_to :author_with_address, -> { includes(:author_address) }, class_name: "Author", foreign_key: :author_id
+ belongs_to :author_with_select, -> { select(:id) }, class_name: "Author", foreign_key: :author_id
def first_comment
super.body
@@ -327,6 +328,10 @@ class FakeKlass
# noop
end
+ def columns_hash
+ { "name" => nil }
+ end
+
def arel_table
Post.arel_table
end
diff --git a/activerecord/test/models/rating.rb b/activerecord/test/models/rating.rb
index cf06bc6931..49aa38285f 100644
--- a/activerecord/test/models/rating.rb
+++ b/activerecord/test/models/rating.rb
@@ -3,4 +3,5 @@
class Rating < ActiveRecord::Base
belongs_to :comment
has_many :taggings, as: :taggable
+ has_many :taggings_without_tag, -> { left_joins(:tag).where("tags.id": nil) }, as: :taggable, class_name: "Tagging"
end
diff --git a/activerecord/test/models/reply.rb b/activerecord/test/models/reply.rb
index 0807bcf875..b35623a344 100644
--- a/activerecord/test/models/reply.rb
+++ b/activerecord/test/models/reply.rb
@@ -7,6 +7,8 @@ class Reply < Topic
belongs_to :topic_with_primary_key, class_name: "Topic", primary_key: "title", foreign_key: "parent_title", counter_cache: "replies_count", touch: true
has_many :replies, class_name: "SillyReply", dependent: :destroy, foreign_key: "parent_id"
has_many :silly_unique_replies, dependent: :destroy, foreign_key: "parent_id"
+
+ scope :ordered, -> { Reply.order(:id) }
end
class SillyReply < Topic
diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb
index fdb461ed7f..75890c327a 100644
--- a/activerecord/test/models/topic.rb
+++ b/activerecord/test/models/topic.rb
@@ -10,9 +10,6 @@ class Topic < ActiveRecord::Base
scope :approved, -> { where(approved: true) }
scope :rejected, -> { where(approved: false) }
- scope :children, -> { where.not(parent_id: nil) }
- scope :has_children, -> { where(id: Topic.children.select(:parent_id)) }
-
scope :scope_with_lambda, lambda { all }
scope :by_lifo, -> { where(author_name: "lifo") }
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 86d5a67a13..349b8afc48 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -247,6 +247,7 @@ ActiveRecord::Schema.define do
create_table :contracts, force: true do |t|
t.references :developer, index: false
t.references :company, index: false
+ t.string :metadata
end
create_table :customers, force: true do |t|