diff options
Diffstat (limited to 'activerecord/test')
7 files changed, 169 insertions, 1 deletions
diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb index b65af4b819..166a59ec7b 100644 --- a/activerecord/test/cases/associations/inner_join_association_test.rb +++ b/activerecord/test/cases/associations/inner_join_association_test.rb @@ -69,6 +69,16 @@ class InnerJoinAssociationTest < ActiveRecord::TestCase assert_equal [expected], Person.joins(string_join).joins(agents.create_join(agents, agents.create_on(constraint))) end + def test_deduplicate_joins + posts = Post.arel_table + constraint = posts[:author_id].eq(Author.arel_attribute(:id)) + + authors = Author.joins(posts.create_join(posts, posts.create_on(constraint))) + authors = authors.joins(:author_address).merge(authors.where("posts.type": "SpecialPost")) + + assert_equal [authors(:david)], authors + end + def test_construct_finder_sql_ignores_empty_joins_hash sql = Author.joins({}).to_sql assert_no_match(/JOIN/i, sql) diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index dbd1d03c4c..abce4565a4 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -952,6 +952,90 @@ class CalculationsTest < ActiveRecord::TestCase assert_equal({ "proposed" => 2, "published" => 2 }, Book.group(:status).count) end + def test_select_avg_with_group_by_as_virtual_attribute_with_sql + rails_core = companies(:rails_core) + + sql = <<~SQL + SELECT firm_id, AVG(credit_limit) AS avg_credit_limit + FROM accounts + WHERE firm_id = ? + GROUP BY firm_id + LIMIT 1 + SQL + + account = Account.find_by_sql([sql, rails_core]).first + + # id was not selected, so it should be nil + # (cannot select id because it wasn't used in the GROUP BY clause) + assert_nil account.id + + # firm_id was explicitly selected, so it should be present + assert_equal(rails_core, account.firm) + + # avg_credit_limit should be present as a virtual attribute + assert_equal(52.5, account.avg_credit_limit) + end + + def test_select_avg_with_group_by_as_virtual_attribute_with_ar + rails_core = companies(:rails_core) + + account = Account + .select(:firm_id, "AVG(credit_limit) AS avg_credit_limit") + .where(firm: rails_core) + .group(:firm_id) + .take! + + # id was not selected, so it should be nil + # (cannot select id because it wasn't used in the GROUP BY clause) + assert_nil account.id + + # firm_id was explicitly selected, so it should be present + assert_equal(rails_core, account.firm) + + # avg_credit_limit should be present as a virtual attribute + assert_equal(52.5, account.avg_credit_limit) + end + + def test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_sql + rails_core = companies(:rails_core) + + sql = <<~SQL + SELECT companies.*, AVG(accounts.credit_limit) AS avg_credit_limit + FROM companies + INNER JOIN accounts ON companies.id = accounts.firm_id + WHERE companies.id = ? + GROUP BY companies.id + LIMIT 1 + SQL + + firm = DependentFirm.find_by_sql([sql, rails_core]).first + + # all the DependentFirm attributes should be present + assert_equal rails_core, firm + assert_equal rails_core.name, firm.name + + # avg_credit_limit should be present as a virtual attribute + assert_equal(52.5, firm.avg_credit_limit) + end + + def test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_ar + rails_core = companies(:rails_core) + + firm = DependentFirm + .select("companies.*", "AVG(accounts.credit_limit) AS avg_credit_limit") + .where(id: rails_core) + .joins(:account) + .group(:id) + .take! + + # all the DependentFirm attributes should be present + assert_equal rails_core, firm + assert_equal rails_core.name, firm.name + + # avg_credit_limit should be present as a virtual attribute + assert_equal(52.5, firm.avg_credit_limit) + end + def test_count_with_block_and_column_name_raises_an_error assert_raises(ArgumentError) do Account.count(:firm_id) { true } 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 ee2972101f..2ac249b478 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 @@ -28,6 +28,22 @@ module ActiveRecord resolver.resolve(spec, spec) end + def test_invalid_string_config + config = { "foo" => "bar" } + + assert_raises ActiveRecord::DatabaseConfigurations::InvalidConfigurationError do + resolve_config(config) + end + end + + def test_invalid_symbol_config + config = { "foo" => :bar } + + assert_raises ActiveRecord::DatabaseConfigurations::InvalidConfigurationError do + resolve_config(config) + end + end + def test_resolver_with_database_uri_and_current_env_symbol_key ENV["DATABASE_URL"] = "postgres://localhost/foo" config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } } diff --git a/activerecord/test/cases/database_selector_test.rb b/activerecord/test/cases/database_selector_test.rb index fd02d2acb4..340151e6db 100644 --- a/activerecord/test/cases/database_selector_test.rb +++ b/activerecord/test/cases/database_selector_test.rb @@ -123,6 +123,40 @@ module ActiveRecord assert read end + def test_preventing_writes_turns_off_for_primary_write + resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver.new(@session, delay: 5.seconds) + + # Session should start empty + assert_nil @session_store[:last_write] + + called = false + resolver.write do + assert ActiveRecord::Base.connected_to?(role: :writing) + called = true + end + assert called + + # and be populated by the last write time + assert @session_store[:last_write] + + read = false + write = false + resolver.read do + assert ActiveRecord::Base.connected_to?(role: :writing) + assert ActiveRecord::Base.connection_handler.prevent_writes + read = true + + resolver.write do + assert ActiveRecord::Base.connected_to?(role: :writing) + assert_not ActiveRecord::Base.connection_handler.prevent_writes + write = true + end + end + + assert write + assert read + end + def test_read_from_replica_with_no_delay resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver.new(@session, delay: 0.seconds) diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index a2a501a794..38baf0509c 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -491,6 +491,7 @@ class DirtyTest < ActiveRecord::TestCase assert_equal 4, pirate.previous_changes.size assert_equal [nil, "arrr"], pirate.previous_changes["catchphrase"] + assert_nil pirate.catchphrase_previously_was assert_equal [nil, pirate.id], pirate.previous_changes["id"] assert_nil pirate.previous_changes["updated_on"][0] assert_not_nil pirate.previous_changes["updated_on"][1] @@ -507,6 +508,7 @@ class DirtyTest < ActiveRecord::TestCase assert_equal 4, pirate.previous_changes.size assert_equal [nil, "arrr"], pirate.previous_changes["catchphrase"] + assert_nil pirate.catchphrase_previously_was assert_equal [nil, pirate.id], pirate.previous_changes["id"] assert_includes pirate.previous_changes, "updated_on" assert_includes pirate.previous_changes, "created_on" @@ -525,6 +527,7 @@ class DirtyTest < ActiveRecord::TestCase assert_equal 2, pirate.previous_changes.size assert_equal ["arrr", "Me Maties!"], pirate.previous_changes["catchphrase"] + assert_equal "arrr", pirate.catchphrase_previously_was assert_not_nil pirate.previous_changes["updated_on"][0] assert_not_nil pirate.previous_changes["updated_on"][1] assert_not pirate.previous_changes.key?("parrot_id") @@ -539,6 +542,7 @@ class DirtyTest < ActiveRecord::TestCase assert_equal 2, pirate.previous_changes.size assert_equal ["Me Maties!", "Thar She Blows!"], pirate.previous_changes["catchphrase"] + assert_equal "Me Maties!", pirate.catchphrase_previously_was assert_not_nil pirate.previous_changes["updated_on"][0] assert_not_nil pirate.previous_changes["updated_on"][1] assert_not pirate.previous_changes.key?("parrot_id") @@ -551,6 +555,7 @@ class DirtyTest < ActiveRecord::TestCase assert_equal 2, pirate.previous_changes.size assert_equal ["Thar She Blows!", "Ahoy!"], pirate.previous_changes["catchphrase"] + assert_equal "Thar She Blows!", pirate.catchphrase_previously_was assert_not_nil pirate.previous_changes["updated_on"][0] assert_not_nil pirate.previous_changes["updated_on"][1] assert_not pirate.previous_changes.key?("parrot_id") @@ -563,6 +568,7 @@ class DirtyTest < ActiveRecord::TestCase assert_equal 2, pirate.previous_changes.size assert_equal ["Ahoy!", "Ninjas suck!"], pirate.previous_changes["catchphrase"] + assert_equal "Ahoy!", pirate.catchphrase_previously_was assert_not_nil pirate.previous_changes["updated_on"][0] assert_not_nil pirate.previous_changes["updated_on"][1] assert_not pirate.previous_changes.key?("parrot_id") diff --git a/activerecord/test/cases/insert_all_test.rb b/activerecord/test/cases/insert_all_test.rb index d086d77081..42c623fafb 100644 --- a/activerecord/test/cases/insert_all_test.rb +++ b/activerecord/test/cases/insert_all_test.rb @@ -2,6 +2,7 @@ require "cases/helper" require "models/book" +require "models/speedometer" class ReadonlyNameBook < Book attr_readonly :name @@ -225,6 +226,23 @@ class InsertAllTest < ActiveRecord::TestCase assert_equal new_name, Book.find(1).name end + def test_upsert_all_updates_existing_record_by_primary_key + skip unless supports_insert_on_duplicate_update? + + Book.upsert_all [{ id: 1, name: "New edition" }], unique_by: :id + + assert_equal "New edition", Book.find(1).name + end + + def test_upsert_all_updates_existing_record_by_configured_primary_key + skip unless supports_insert_on_duplicate_update? + + error = assert_raises ArgumentError do + Speedometer.upsert_all [{ speedometer_id: "s1", name: "New Speedometer" }] + end + assert_match "No unique index found for speedometer_id", error.message + end + def test_upsert_all_does_not_update_readonly_attributes skip unless supports_insert_on_duplicate_update? diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 1a20fe5dc2..8b3ae02947 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -1932,7 +1932,7 @@ class RelationTest < ActiveRecord::TestCase assert_no_queries do result = authors_count.map do |post| - [post.num_posts, post.author.try(:name)] + [post.num_posts, post.author&.name] end expected = [[1, nil], [5, "David"], [3, "Mary"], [2, "Bob"]] |