Expose assert_queries_match and assert_no_queries_match assertions

This commit is contained in:
fatkodima 2023-12-20 12:28:55 +02:00
parent bf725a7876
commit f48bbff32c
65 changed files with 934 additions and 790 deletions

@ -99,7 +99,7 @@ class ActionText::ModelTest < ActiveSupport::TestCase
test "eager loading" do
Message.create!(subject: "Subject", content: "<h1>Content</h1>")
message = assert_queries(2) { Message.with_rich_text_content.last }
message = assert_queries_count(2) { Message.with_rich_text_content.last }
assert_no_queries do
assert_equal "Content", message.content.to_plain_text
end
@ -108,7 +108,7 @@ class ActionText::ModelTest < ActiveSupport::TestCase
test "eager loading all rich text" do
Message.create!(subject: "Subject", content: "<h1>Content</h1>", body: "<h2>Body</h2>")
message = assert_queries(1) { Message.with_all_rich_text.last }
message = assert_queries_count(1) { Message.with_all_rich_text.last }
assert_no_queries do
assert_equal "Content", message.content.to_plain_text
assert_equal "Body", message.body.to_plain_text

@ -19,7 +19,7 @@ def setup
end
def test_cache_relation_other
assert_queries(1) do
assert_queries_count(1) do
cache(Project.all) { concat("Hello World") }
end
assert_equal "Hello World", controller.cache_store.read("views/test/hello_world:fa9482a68ce25bf7589b8eddad72f736/projects-#{Project.count}")

@ -23,21 +23,28 @@
*Jean Boussier*
* Make `assert_queries` and `assert_no_queries` assertions public.
* Make `assert_queries_count`, `assert_no_queries`, `assert_queries_match` and
`assert_no_queries_match` assertions public.
To assert the expected number of queries are made, Rails internally uses
`assert_queries` and `assert_no_queries`. These assertions can be now
be used in applications as well.
To assert the expected number of queries are made, Rails internally uses `assert_queries_count` and
`assert_no_queries`. To assert that specific SQL queries are made, `assert_queries_match` and
`assert_no_queries_match` are used. These assertions can now be used in applications as well.
```ruby
class ArticleTest < ActiveSupport::TestCase
test "queries are made" do
assert_queries(1) { Article.first }
assert_queries_count(1) { Article.first }
end
test "creates a foreign key" do
assert_queries_match(/ADD FOREIGN KEY/i, include_schema: true) do
@connection.add_foreign_key(:comments, :posts)
end
end
end
```
*Petrik de Heus*
*Petrik de Heus*, *fatkodima*
* Fix `has_secure_token` calls the setter method on initialize.

@ -5,29 +5,104 @@ module Assertions
module QueryAssertions
# Asserts that the number of SQL queries executed in the given block matches the expected count.
#
# assert_queries(1) { Post.first }
# # Check for exact number of queries
# assert_queries_count(1) { Post.first }
#
# If the +:matcher+ option is provided, only queries that match the matcher are counted.
# # Check for any number of queries
# assert_queries_count { Post.first }
#
# assert_queries(1, matcher: /LIMIT \?/) { Post.first }
# If the +:include_schema+ option is provided, any queries (including schema related) are counted.
#
def assert_queries(expected_count, matcher: nil, &block)
# assert_queries_count(1, include_schema: true) { Post.columns }
#
def assert_queries_count(count = nil, include_schema: false, &block)
ActiveRecord::Base.connection.materialize_transactions
queries = []
callback = lambda do |*, payload|
queries << payload[:sql] if %w[ SCHEMA TRANSACTION ].exclude?(payload[:name]) && (matcher.nil? || payload[:sql].match(matcher))
end
ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
result = _assert_nothing_raised_or_warn("assert_queries", &block)
assert_equal expected_count, queries.size, "#{queries.size} instead of #{expected_count} queries were executed. Queries: #{queries.join("\n\n")}"
counter = SQLCounter.new
ActiveSupport::Notifications.subscribed(counter, "sql.active_record") do
result = _assert_nothing_raised_or_warn("assert_queries_count", &block)
queries = include_schema ? counter.log_all : counter.log
if count
assert_equal count, queries.size, "#{queries.size} instead of #{count} queries were executed. Queries: #{queries.join("\n\n")}"
else
assert_operator queries.size, :>=, 1, "1 or more queries expected, but none were executed.#{queries.empty? ? '' : "\nQueries:\n#{queries.join("\n")}"}"
end
result
end
end
# Asserts that no SQL queries are executed in the given block.
def assert_no_queries(&block)
assert_queries(0, &block)
#
# assert_no_queries { post.comments }
#
# If the +:include_schema+ option is provided, any queries (including schema related) are counted.
#
# assert_no_queries(include_schema: true) { Post.columns }
#
def assert_no_queries(include_schema: false, &block)
assert_queries_count(0, include_schema: include_schema, &block)
end
# Asserts that the SQL queries executed in the given block match expected pattern.
#
# # Check for exact number of queries
# assert_queries_match(/LIMIT \?/, count: 1) { Post.first }
#
# # Check for any number of queries
# assert_queries_match(/LIMIT \?/) { Post.first }
#
# If the +:include_schema+ option is provided, any queries (including schema related)
# that match the matcher are considered.
#
# assert_queries_match(/FROM pg_attribute/i, include_schema: true) { Post.columns }
#
def assert_queries_match(match, count: nil, include_schema: false, &block)
ActiveRecord::Base.connection.materialize_transactions
counter = SQLCounter.new
ActiveSupport::Notifications.subscribed(counter, "sql.active_record") do
result = _assert_nothing_raised_or_warn("assert_queries_match", &block)
queries = include_schema ? counter.log_all : counter.log
matched_queries = queries.select { |query| match === query }
if count
assert_equal count, matched_queries.size, "#{matched_queries.size} instead of #{count} queries were executed.#{queries.empty? ? '' : "\nQueries:\n#{queries.join("\n")}"}"
else
assert_operator matched_queries.size, :>=, 1, "1 or more queries expected, but none were executed.#{queries.empty? ? '' : "\nQueries:\n#{queries.join("\n")}"}"
end
result
end
end
# Asserts that no SQL queries matching the pattern are executed in the given block.
#
# assert_no_queries_match(/SELECT/i) { post.comments }
#
# If the +:include_schema+ option is provided, any queries (including schema related)
# that match the matcher are counted.
#
# assert_no_queries_match(/FROM pg_attribute/i, include_schema: true) { Post.columns }
#
def assert_no_queries_match(match, include_schema: false, &block)
assert_queries_match(match, count: 0, include_schema: include_schema, &block)
end
class SQLCounter # :nodoc:
attr_reader :log, :log_all
def initialize
@log = []
@log_all = []
end
def call(*, payload)
return if payload[:cached]
sql = payload[:sql]
@log_all << sql
@log << sql unless payload[:name] == "SCHEMA"
end
end
end
end

@ -99,7 +99,7 @@ def test_index_in_create
def test_index_in_bulk_change
%w(SPATIAL FULLTEXT UNIQUE).each do |type|
expected = "ALTER TABLE `people` ADD #{type} INDEX `index_people_on_last_name` (`last_name`)"
assert_sql(expected) do
assert_queries_match(expected) do
ActiveRecord::Base.connection.change_table(:people, bulk: true) do |t|
t.index :last_name, type: type
end
@ -107,7 +107,7 @@ def test_index_in_bulk_change
end
expected = "ALTER TABLE `people` ADD INDEX `index_people_on_last_name` USING btree (`last_name`(10)), ALGORITHM = COPY"
assert_sql(expected) do
assert_queries_match(expected) do
ActiveRecord::Base.connection.change_table(:people, bulk: true) do |t|
t.index :last_name, length: 10, using: :btree, algorithm: :copy
end

@ -8,7 +8,7 @@ class OptimizerHintsTest < ActiveRecord::AbstractMysqlTestCase
fixtures :posts
def test_optimizer_hints
assert_sql(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
assert_queries_match(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
posts = Post.optimizer_hints("NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)")
posts = posts.select(:id).where(author_id: [0, 1])
assert_includes posts.explain, "| index | index_posts_on_author_id | index_posts_on_author_id |"
@ -16,7 +16,7 @@ def test_optimizer_hints
end
def test_optimizer_hints_with_count_subquery
assert_sql(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
assert_queries_match(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
posts = Post.optimizer_hints("NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)")
posts = posts.select(:id).where(author_id: [0, 1]).limit(5)
assert_equal 5, posts.count
@ -24,13 +24,13 @@ def test_optimizer_hints_with_count_subquery
end
def test_optimizer_hints_is_sanitized
assert_sql(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
assert_queries_match(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
posts = Post.optimizer_hints("/*+ NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id) */")
posts = posts.select(:id).where(author_id: [0, 1])
assert_includes posts.explain, "| index | index_posts_on_author_id | index_posts_on_author_id |"
end
assert_sql(%r{\ASELECT /\*\+ \*\* // `posts`\.\*, // \*\* \*/}) do
assert_queries_match(%r{\ASELECT /\*\+ \*\* // `posts`\.\*, // \*\* \*/}) do
posts = Post.optimizer_hints("**// `posts`.*, //**")
posts = posts.select(:id).where(author_id: [0, 1])
assert_equal({ "id" => 1 }, posts.first.as_json)
@ -38,7 +38,7 @@ def test_optimizer_hints_is_sanitized
end
def test_optimizer_hints_with_unscope
assert_sql(%r{\ASELECT `posts`\.`id`}) do
assert_queries_match(%r{\ASELECT `posts`\.`id`}) do
posts = Post.optimizer_hints("/*+ NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id) */")
posts = posts.select(:id).where(author_id: [0, 1])
posts.unscope(:optimizer_hints).load
@ -46,7 +46,7 @@ def test_optimizer_hints_with_unscope
end
def test_optimizer_hints_with_or
assert_sql(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
assert_queries_match(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
Post.optimizer_hints("NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)")
.or(Post.all).load
end

@ -24,19 +24,19 @@ def teardown
end
def test_encoding
assert_queries(1, ignore_none: true) do
assert_queries_count(1, include_schema: true) do
assert_not_nil @connection.encoding
end
end
def test_collation
assert_queries(1, ignore_none: true) do
assert_queries_count(1, include_schema: true) do
assert_not_nil @connection.collation
end
end
def test_ctype
assert_queries(1, ignore_none: true) do
assert_queries_count(1, include_schema: true) do
assert_not_nil @connection.ctype
end
end

@ -12,7 +12,7 @@ def setup
end
def test_optimizer_hints
assert_sql(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do
assert_queries_match(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do
posts = Post.optimizer_hints("SeqScan(posts)")
posts = posts.select(:id).where(author_id: [0, 1])
assert_includes posts.explain, "Seq Scan on posts"
@ -20,7 +20,7 @@ def test_optimizer_hints
end
def test_optimizer_hints_with_count_subquery
assert_sql(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do
assert_queries_match(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do
posts = Post.optimizer_hints("SeqScan(posts)")
posts = posts.select(:id).where(author_id: [0, 1]).limit(5)
assert_equal 5, posts.count
@ -28,13 +28,13 @@ def test_optimizer_hints_with_count_subquery
end
def test_optimizer_hints_is_sanitized
assert_sql(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do
assert_queries_match(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do
posts = Post.optimizer_hints("/*+ SeqScan(posts) */")
posts = posts.select(:id).where(author_id: [0, 1])
assert_includes posts.explain, "Seq Scan on posts"
end
assert_sql(%r{\ASELECT /\*\+ "posts"\.\*, \*/}) do
assert_queries_match(%r{\ASELECT /\*\+ "posts"\.\*, \*/}) do
posts = Post.optimizer_hints("**// \"posts\".*, //**")
posts = posts.select(:id).where(author_id: [0, 1])
assert_equal({ "id" => 1 }, posts.first.as_json)
@ -42,7 +42,7 @@ def test_optimizer_hints_is_sanitized
end
def test_optimizer_hints_with_unscope
assert_sql(%r{\ASELECT "posts"\."id"}) do
assert_queries_match(%r{\ASELECT "posts"\."id"}) do
posts = Post.optimizer_hints("/*+ SeqScan(posts) */")
posts = posts.select(:id).where(author_id: [0, 1])
posts.unscope(:optimizer_hints).load
@ -50,7 +50,7 @@ def test_optimizer_hints_with_unscope
end
def test_optimizer_hints_with_or
assert_sql(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do
assert_queries_match(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do
Post.optimizer_hints("SeqScan(posts)").or(Post.all).load
end

@ -462,14 +462,14 @@ def test_reload_type_map_for_newly_defined_types
@connection.create_enum "feeling", ["good", "bad"]
# Runs only SELECT, no type map reloading.
assert_queries(1, ignore_none: true) do
assert_queries_count(1, include_schema: true) do
result = @connection.select_all "SELECT 'good'::feeling"
assert_instance_of(PostgreSQLAdapter::OID::Enum,
result.column_types["feeling"])
end
ensure
# Reloads type map.
assert_sql(/from pg_type/i) do
assert_queries_match(/from pg_type/i, include_schema: true) do
@connection.drop_enum "feeling", if_exists: true
end
reset_connection
@ -481,13 +481,13 @@ def test_only_reload_type_map_once_for_every_unrecognized_type
connection.select_all "SELECT 1" # eagerly initialize the connection
silence_warnings do
assert_queries 2, ignore_none: true do
assert_queries_count(2, include_schema: true) do
connection.select_all "select 'pg_catalog.pg_class'::regclass"
end
assert_queries 1, ignore_none: true do
assert_queries_count(1, include_schema: true) do
connection.select_all "select 'pg_catalog.pg_class'::regclass"
end
assert_queries 2, ignore_none: true do
assert_queries_count(2, include_schema: true) do
connection.select_all "SELECT NULL::anyarray"
end
end
@ -534,7 +534,7 @@ def test_only_check_for_insensitive_comparison_capability_once
self.table_name = "ex"
end
attribute = number_klass.arel_table[:number]
assert_queries :any, ignore_none: true do
assert_queries_count(include_schema: true) do
@connection.case_insensitive_comparison(attribute, "foo")
end
assert_no_queries do

@ -9,7 +9,7 @@ class AnnotateTest < ActiveRecord::TestCase
def test_annotate_wraps_content_in_an_inline_comment
quoted_posts_id, quoted_posts = regexp_escape_table_name("posts.id"), regexp_escape_table_name("posts")
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
assert_queries_match(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
posts = Post.select(:id).annotate("foo")
assert posts.first
end
@ -18,27 +18,27 @@ def test_annotate_wraps_content_in_an_inline_comment
def test_annotate_is_sanitized
quoted_posts_id, quoted_posts = regexp_escape_table_name("posts.id"), regexp_escape_table_name("posts")
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/}i) do
assert_queries_match(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/}i) do
posts = Post.select(:id).annotate("*/foo/*")
assert posts.first
end
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \*\* //foo// \*\* \*/}i) do
assert_queries_match(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \*\* //foo// \*\* \*/}i) do
posts = Post.select(:id).annotate("**//foo//**")
assert posts.first
end
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* \* //foo// \* \* \*/}i) do
assert_queries_match(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* \* //foo// \* \* \*/}i) do
posts = Post.select(:id).annotate("* *//foo//* *")
assert posts.first
end
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/ /\* \* /bar \*/}i) do
assert_queries_match(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/ /\* \* /bar \*/}i) do
posts = Post.select(:id).annotate("*/foo/*").annotate("*/bar")
assert posts.first
end
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \+ MAX_EXECUTION_TIME\(1\) \*/}i) do
assert_queries_match(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \+ MAX_EXECUTION_TIME\(1\) \*/}i) do
posts = Post.select(:id).annotate("+ MAX_EXECUTION_TIME(1)")
assert posts.first
end

@ -7,39 +7,132 @@
module ActiveRecord
module Assertions
class QueryAssertionsTest < ActiveSupport::TestCase
extend AdapterHelper
include QueryAssertions
def test_assert_queries
assert_queries(1) { Post.first }
def test_assert_queries_count
assert_queries_count(1) { Post.first }
error = assert_raises(Minitest::Assertion) {
assert_queries(2) { Post.first }
assert_queries_count(2) { Post.first }
}
assert_match(/1 instead of 2 queries/, error.message)
error = assert_raises(Minitest::Assertion) {
assert_queries(0) { Post.first }
assert_queries_count(0) { Post.first }
}
assert_match(/1 instead of 0 queries/, error.message)
end
def test_assert_queries_with_matcher
def test_assert_queries_count_any
assert_queries_count { Post.first }
assert_raises(Minitest::Assertion, match: "1 or more queries expected") {
assert_queries_count { }
}
end
def test_assert_no_queries
assert_no_queries { Post.none }
assert_raises(Minitest::Assertion, match: "1 instead of 0") {
assert_no_queries { Post.first }
}
end
def test_assert_queries_match
assert_queries_match(/ASC LIMIT/i, count: 1) { Post.first }
assert_queries_match(/ASC LIMIT/i) { Post.first }
error = assert_raises(Minitest::Assertion) {
assert_queries(1, matcher: /WHERE "posts"."id" = \? LIMIT \?/) do
assert_queries_match(/ASC LIMIT/i, count: 2) { Post.first }
}
assert_match(/1 instead of 2 queries/, error.message)
error = assert_raises(Minitest::Assertion) {
assert_queries_match(/ASC LIMIT/i, count: 0) { Post.first }
}
assert_match(/1 instead of 0 queries/, error.message)
end
def test_assert_queries_match_with_matcher
error = assert_raises(Minitest::Assertion) {
assert_queries_match(/WHERE "posts"."id" = \? LIMIT \?/, count: 1) do
Post.where(id: 1).first
end
}
assert_match(/0 instead of 1 queries/, error.message)
end
def test_assert_no_queries
assert_no_queries { Post.none }
def test_assert_queries_match_when_there_are_no_queries
assert_raises(Minitest::Assertion, match: "1 or more queries expected, but none were executed") do
assert_queries_match(/something/) { Post.none }
end
end
def test_assert_no_queries_match
assert_no_queries_match(/something/) { Post.none }
error = assert_raises(Minitest::Assertion) {
assert_no_queries { Post.first }
assert_no_queries_match(/ORDER BY/i) { Post.first }
}
assert_match(/1 instead of 0/, error.message)
end
def test_assert_no_queries_match_matcher
assert_raises(Minitest::Assertion, match: "1 instead of 0") do
assert_no_queries_match(/ORDER BY/i) do
Post.first
end
end
end
if current_adapter?(:PostgreSQLAdapter)
def test_assert_queries_count_include_schema
Post.columns # load columns
assert_raises(Minitest::Assertion, match: "0 instead of 1 queries were executed") do
assert_queries_count(1, include_schema: true) { Post.columns }
end
Post.reset_column_information
assert_queries_count(1, include_schema: true) { Post.columns }
end
def test_assert_no_queries_include_schema
assert_no_queries { Post.none }
error = assert_raises(Minitest::Assertion) {
assert_no_queries { Post.first }
}
assert_match(/1 instead of 0/, error.message)
Post.reset_column_information
error = assert_raises(Minitest::Assertion) {
assert_no_queries(include_schema: true) { Post.columns }
}
assert_match(/1 instead of 0/, error.message)
end
def test_assert_queries_match_include_schema
Post.columns # load columns
assert_raises(Minitest::Assertion, match: "1 or more queries expected") do
assert_queries_match(/SELECT/i, include_schema: true) { Post.columns }
end
Post.reset_column_information
assert_queries_match(/SELECT/i, include_schema: true) { Post.columns }
end
def test_assert_no_queries_match_include_schema
Post.columns # load columns
assert_no_queries_match(/SELECT/i, include_schema: true) { Post.columns }
Post.reset_column_information
assert_raises(Minitest::Assertion, match: /\d instead of 0/) do
assert_no_queries_match(/SELECT/i, include_schema: true) { Post.columns }
end
end
end
end
end
end

@ -40,7 +40,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
def test_belongs_to
client = Client.find(3)
first_firm = companies(:first_firm)
assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) do
assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) do
assert_equal first_firm, client.firm
assert_equal first_firm.name, client.firm.name
end
@ -451,7 +451,7 @@ def test_reloading_the_belonging_object
Company.where(id: odegy_account.firm_id).update_all(name: "ODEGY")
assert_equal "Odegy", odegy_account.firm.name
assert_queries(1) { odegy_account.reload_firm }
assert_queries_count(1) { odegy_account.reload_firm }
assert_no_queries { odegy_account.firm }
assert_equal "ODEGY", odegy_account.firm.name
@ -473,10 +473,10 @@ def test_reload_the_belonging_object_with_query_cache
assert_equal 2, connection.query_cache.size
# Clear the cache and fetch the firm again, populating the cache with a query
assert_queries(1) { odegy_account.reload_firm }
assert_queries_count(1) { odegy_account.reload_firm }
# This query is not cached anymore, so it should make a real SQL query
assert_queries(1) { Account.find(odegy_account_id) }
assert_queries_count(1) { Account.find(odegy_account_id) }
ensure
ActiveRecord::Base.connection.disable_query_cache!
end
@ -489,7 +489,7 @@ def test_resetting_the_association
assert_equal "Odegy", odegy_account.firm.name
assert_no_queries { odegy_account.reset_firm }
assert_queries(1) { odegy_account.firm }
assert_queries_count(1) { odegy_account.firm }
assert_equal "ODEGY", odegy_account.firm.name
end
@ -717,7 +717,7 @@ def test_belongs_to_reassign_with_namespaced_models_and_counters
def test_belongs_to_counter_after_save
topic = Topic.create!(title: "monday night")
assert_queries(2) do
assert_queries_count(4) do
topic.replies.create!(title: "re: monday night", content: "football")
end
@ -754,7 +754,7 @@ def test_belongs_to_touch_with_reassigning
debate.touch(time: time)
debate2.touch(time: time)
assert_queries(3) do
assert_queries_count(5) do
reply.parent_title = "debate"
reply.save!
end
@ -765,7 +765,7 @@ def test_belongs_to_touch_with_reassigning
debate.touch(time: time)
debate2.touch(time: time)
assert_queries(3) do
assert_queries_count(5) do
reply.topic_with_primary_key = debate2
reply.save!
end
@ -778,7 +778,7 @@ def test_belongs_to_with_touch_option_on_touch
line_item = LineItem.create!
Invoice.create!(line_items: [line_item])
assert_queries(1) { line_item.touch }
assert_queries_count(3) { line_item.touch }
end
def test_belongs_to_with_touch_on_multiple_records
@ -786,14 +786,14 @@ def test_belongs_to_with_touch_on_multiple_records
line_item2 = LineItem.create!(amount: 2)
Invoice.create!(line_items: [line_item, line_item2])
assert_queries(1) do
assert_queries_count(3) do
LineItem.transaction do
line_item.touch
line_item2.touch
end
end
assert_queries(2) do
assert_queries_count(6) do
line_item.touch
line_item2.touch
end
@ -818,14 +818,14 @@ def test_belongs_to_with_touch_option_on_touch_and_removed_parent
line_item.invoice = nil
assert_queries(2) { line_item.touch }
assert_queries_count(4) { line_item.touch }
end
def test_belongs_to_with_touch_option_on_update
line_item = LineItem.create!
Invoice.create!(line_items: [line_item])
assert_queries(2) { line_item.update amount: 10 }
assert_queries_count(4) { line_item.update amount: 10 }
end
def test_belongs_to_with_touch_option_on_empty_update
@ -839,7 +839,7 @@ def test_belongs_to_with_touch_option_on_destroy
line_item = LineItem.create!
Invoice.create!(line_items: [line_item])
assert_queries(2) { line_item.destroy }
assert_queries_count(4) { line_item.destroy }
end
def test_belongs_to_with_touch_option_on_destroy_with_destroyed_parent
@ -847,7 +847,7 @@ def test_belongs_to_with_touch_option_on_destroy_with_destroyed_parent
invoice = Invoice.create!(line_items: [line_item])
invoice.destroy
assert_queries(1) { line_item.destroy }
assert_queries_count(3) { line_item.destroy }
end
def test_belongs_to_with_touch_option_on_touch_and_reassigned_parent
@ -856,7 +856,7 @@ def test_belongs_to_with_touch_option_on_touch_and_reassigned_parent
line_item.invoice = Invoice.create!
assert_queries(3) { line_item.touch }
assert_queries_count(5) { line_item.touch }
end
def test_belongs_to_counter_after_update
@ -933,7 +933,7 @@ def test_dont_find_target_when_foreign_key_is_null
def test_dont_find_target_when_saving_foreign_key_after_stale_association_loaded
client = Client.create!(name: "Test client", firm_with_basic_id: Firm.find(1))
client.firm_id = Firm.create!(name: "Test firm").id
assert_queries(1) { client.save! }
assert_queries_count(3) { client.save! }
end
def test_field_name_same_as_foreign_key
@ -1740,14 +1740,14 @@ class ShipRequired < ActiveRecord::Base
ship = ShipRequired.create!(name: "Medusa", developer: david)
assert_equal david, ship.developer
assert_queries(2) do # UPDATE and SELECT to check developer presence
assert_queries_count(4) do # UPDATE and SELECT to check developer presence
ship.update!(developer_id: jamis.id)
end
ship.update_column(:developer_id, nil)
ship.reload
assert_queries(2) do # UPDATE and SELECT to check developer presence
assert_queries_count(4) do # UPDATE and SELECT to check developer presence
ship.update!(developer_id: david.id)
end
end
@ -1757,7 +1757,7 @@ class ShipRequired < ActiveRecord::Base
ship = ShipRequired.create!(name: "Medusa", developer: david)
ship.reload # unload developer association
assert_queries(1) do # UPDATE only, no SELECT to check developer presence
assert_queries_count(3) do # UPDATE only, no SELECT to check developer presence
ship.update!(name: "Leviathan")
end
end
@ -1776,7 +1776,7 @@ def self.name; "Temp"; end
ship = model.create!(name: "Medusa", developer: david)
ship.reload # unload developer association
assert_queries(2) do # UPDATE and SELECT to check developer presence
assert_queries_count(4) do # UPDATE and SELECT to check developer presence
ship.update!(name: "Leviathan")
end
ensure

@ -37,8 +37,8 @@ def test_eager_association_loading_with_cascaded_two_levels_and_one_level
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 }).order(:id).to_a
assert_equal 3, assert_queries(0) { authors.size }
assert_equal 11, assert_queries(0) { authors[0].comments.size }
assert_equal 3, assert_queries_count(0) { authors.size }
assert_equal 11, assert_queries_count(0) { authors[0].comments.size }
end
def test_eager_association_loading_grafts_stashed_associations_to_correct_parent
@ -74,7 +74,7 @@ def test_eager_association_loading_with_join_for_count
authors = Author.joins(:special_posts).includes([:posts, :categorizations])
assert_nothing_raised { authors.count }
assert_queries(3) { authors.to_a }
assert_queries_count(3) { authors.to_a }
end
def test_eager_association_loading_with_cascaded_two_levels_with_two_has_many_associations
@ -103,14 +103,14 @@ def test_eager_association_loading_with_cascaded_three_levels_by_ping_pong
firms = Firm.all.merge!(includes: { account: { firm: :account } }, order: "companies.id").to_a
assert_equal 3, firms.size
assert_equal firms.first.account, firms.first.account.firm.account
assert_equal companies(:first_firm).account, assert_queries(0) { firms.first.account.firm.account }
assert_equal companies(:first_firm).account.firm.account, assert_queries(0) { firms.first.account.firm.account }
assert_equal companies(:first_firm).account, assert_queries_count(0) { firms.first.account.firm.account }
assert_equal companies(:first_firm).account.firm.account, assert_queries_count(0) { firms.first.account.firm.account }
end
def test_eager_association_loading_with_has_many_sti
topics = Topic.all.merge!(includes: :replies, order: "topics.id").to_a
first, second, = topics(:first).replies.size, topics(:second).replies.size
assert_queries(0) do
assert_queries_count(0) do
assert_equal first, topics[0].replies.size
assert_equal second, topics[1].replies.size
end
@ -121,7 +121,7 @@ def test_eager_association_loading_with_has_many_sti_and_subclasses
assert reply.save
topics = Topic.all.merge!(includes: :replies, order: ["topics.id", "replies_topics.id"]).to_a
assert_queries(0) do
assert_queries_count(0) do
assert_equal 2, topics[0].replies.size
assert_equal 0, topics[1].replies.size
end
@ -131,13 +131,13 @@ def test_eager_association_loading_with_belongs_to_sti
replies = Reply.all.merge!(includes: :topic, order: "topics.id").to_a
assert_includes replies, topics(:second)
assert_not_includes replies, topics(:first)
assert_equal topics(:first), assert_queries(0) { replies.first.topic }
assert_equal topics(:first), assert_queries_count(0) { replies.first.topic }
end
def test_eager_association_loading_with_multiple_stis_and_order
author = Author.all.merge!(includes: { posts: [ :special_comments, :very_special_comment ] }, order: ["authors.name", "comments.body", "very_special_comments_posts.body"], where: "posts.id = 4").first
assert_equal authors(:david), author
assert_queries(0) do
assert_queries_count(0) do
author.posts.first.special_comments
author.posts.first.very_special_comment
end
@ -146,7 +146,7 @@ def test_eager_association_loading_with_multiple_stis_and_order
def test_eager_association_loading_of_stis_with_multiple_references
authors = Author.all.merge!(includes: { posts: { special_comments: { post: [ :special_comments, :very_special_comment ] } } }, order: "comments.body, very_special_comments_posts.body", where: "posts.id = 4").to_a
assert_equal [authors(:david)], authors
assert_queries(0) do
assert_queries_count(0) do
authors.first.posts.first.special_comments.first.post.special_comments
authors.first.posts.first.special_comments.first.post.very_special_comment
end
@ -155,14 +155,14 @@ def test_eager_association_loading_of_stis_with_multiple_references
def test_eager_association_loading_where_first_level_returns_nil
authors = Author.all.merge!(includes: { post_about_thinking: :comments }, order: "authors.id DESC").to_a
assert_equal [authors(:bob), authors(:mary), authors(:david)], authors
assert_queries(0) do
assert_queries_count(0) do
authors[2].post_about_thinking.comments.first
end
end
def test_preload_through_missing_records
post = Post.where.not(author_id: Author.select(:id)).preload(author: { comments: :post }).first!
assert_queries(0) { assert_nil post.author }
assert_queries_count(0) { assert_nil post.author }
end
def test_eager_association_loading_with_missing_first_record
@ -172,12 +172,12 @@ def test_eager_association_loading_with_missing_first_record
def test_eager_association_loading_with_recursive_cascading_four_levels_has_many_through
source = Vertex.all.merge!(includes: { sinks: { sinks: { sinks: :sinks } } }, order: "vertices.id").first
assert_equal vertices(:vertex_4), assert_queries(0) { source.sinks.first.sinks.first.sinks.first }
assert_equal vertices(:vertex_4), assert_queries_count(0) { source.sinks.first.sinks.first.sinks.first }
end
def test_eager_association_loading_with_recursive_cascading_four_levels_has_and_belongs_to_many
sink = Vertex.all.merge!(includes: { sources: { sources: { sources: :sources } } }, order: "vertices.id DESC").first
assert_equal vertices(:vertex_1), assert_queries(0) { sink.sources.first.sources.first.sources.first.sources.first }
assert_equal vertices(:vertex_1), assert_queries_count(0) { sink.sources.first.sources.first.sources.first.sources.first }
end
def test_eager_association_loading_with_cascaded_interdependent_one_level_and_two_levels

@ -304,7 +304,7 @@ def test_associations_loaded_for_all_records
def test_finding_with_includes_on_has_many_association_with_same_include_includes_only_once
author_id = authors(:david).id
author = assert_queries(3) { Author.all.merge!(includes: { posts_with_comments: :comments }).find(author_id) } # find the author, then find the posts, then find the comments
author = assert_queries_count(3) { Author.all.merge!(includes: { posts_with_comments: :comments }).find(author_id) } # find the author, then find the posts, then find the comments
author.posts_with_comments.each do |post_with_comments|
assert_equal post_with_comments.comments.length, post_with_comments.comments.count
assert_nil post_with_comments.comments.to_a.uniq!
@ -315,7 +315,7 @@ def test_finding_with_includes_on_has_one_association_with_same_include_includes
author = authors(:david)
post = author.post_about_thinking_with_last_comment
last_comment = post.last_comment
author = assert_queries(3) { Author.all.merge!(includes: { post_about_thinking_with_last_comment: :last_comment }).find(author.id) } # find the author, then find the posts, then find the comments
author = assert_queries_count(3) { Author.all.merge!(includes: { post_about_thinking_with_last_comment: :last_comment }).find(author.id) } # find the author, then find the posts, then find the comments
assert_no_queries do
assert_equal post, author.post_about_thinking_with_last_comment
assert_equal last_comment, author.post_about_thinking_with_last_comment.last_comment
@ -326,7 +326,7 @@ def test_finding_with_includes_on_belongs_to_association_with_same_include_inclu
post = posts(:welcome)
author = post.author
author_address = author.author_address
post = assert_queries(3) { Post.all.merge!(includes: { author_with_address: :author_address }).find(post.id) } # find the post, then find the author, then find the address
post = assert_queries_count(3) { Post.all.merge!(includes: { author_with_address: :author_address }).find(post.id) } # find the post, then find the author, then find the address
assert_no_queries do
assert_equal author, post.author_with_address
assert_equal author_address, post.author_with_address.author_address
@ -336,7 +336,7 @@ def test_finding_with_includes_on_belongs_to_association_with_same_include_inclu
def test_finding_with_includes_on_null_belongs_to_association_with_same_include_includes_only_once
post = posts(:welcome)
post.update!(author: nil)
post = assert_queries(1) { Post.all.merge!(includes: { author_with_address: :author_address }).find(post.id) }
post = assert_queries_count(1) { Post.all.merge!(includes: { author_with_address: :author_address }).find(post.id) }
# find the post, then find the author which is null so no query for the author or address
assert_no_queries do
assert_nil post.author_with_address
@ -346,7 +346,7 @@ def test_finding_with_includes_on_null_belongs_to_association_with_same_include_
def test_finding_with_includes_on_null_belongs_to_polymorphic_association
sponsor = sponsors(:moustache_club_sponsor_for_groucho)
sponsor.update!(sponsorable: nil)
sponsor = assert_queries(1) { Sponsor.all.merge!(includes: :sponsorable).find(sponsor.id) }
sponsor = assert_queries_count(1) { Sponsor.all.merge!(includes: :sponsorable).find(sponsor.id) }
assert_no_queries do
assert_nil sponsor.sponsorable
end
@ -355,7 +355,7 @@ def test_finding_with_includes_on_null_belongs_to_polymorphic_association
def test_finding_with_includes_on_empty_polymorphic_type_column
sponsor = sponsors(:moustache_club_sponsor_for_groucho)
sponsor.update!(sponsorable_type: "", sponsorable_id: nil) # sponsorable_type column might be declared NOT NULL
sponsor = assert_queries(1) do
sponsor = assert_queries_count(1) do
assert_nothing_raised { Sponsor.all.merge!(includes: :sponsorable).find(sponsor.id) }
end
assert_no_queries do
@ -704,7 +704,7 @@ def test_eager_with_has_many_and_limit_and_high_offset
end
def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_array_conditions
assert_queries(1) do
assert_queries_count(1) do
posts = Post.references(:authors, :comments).
merge(includes: [ :author, :comments ], limit: 2, offset: 10,
where: [ "authors.name = ? and comments.body = ?", "David", "go wild" ]).to_a
@ -713,7 +713,7 @@ def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_array_condit
end
def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_hash_conditions
assert_queries(1) do
assert_queries_count(1) do
posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, offset: 10,
where: { "authors.name" => "David", "comments.body" => "go wild" }).to_a
assert_equal 0, posts.size
@ -1091,7 +1091,7 @@ def test_eager_with_valid_association_as_string_not_symbol
end
def test_eager_with_floating_point_numbers
assert_queries(2) do
assert_queries_count(2) do
# Before changes, the floating-point numbers will be interpreted as table names and will cause this to run in one query
Comment.all.merge!(where: "123.456 = 123.456", includes: :post).to_a
end
@ -1182,7 +1182,7 @@ def messages_for(name)
end
def test_load_with_sti_sharing_association
assert_queries(2) do # should not do 1 query per subclass
assert_queries_count(2) do # should not do 1 query per subclass
Comment.includes(:post).to_a
end
end
@ -1202,7 +1202,7 @@ def test_order_on_join_table_with_include_and_limit
end
def test_eager_loading_with_order_on_joined_table_preloads
posts = assert_queries(2) do
posts = assert_queries_count(2) do
Post.all.merge!(joins: :comments, includes: :author, order: "comments.id DESC").to_a
end
assert_equal posts(:eager_other), posts[2]
@ -1210,18 +1210,18 @@ def test_eager_loading_with_order_on_joined_table_preloads
end
def test_eager_loading_with_conditions_on_joined_table_preloads
posts = assert_queries(2) do
posts = assert_queries_count(2) do
Post.all.merge!(select: "distinct posts.*", includes: :author, joins: [:comments], where: "comments.body like 'Thank you%'", order: "posts.id").to_a
end
assert_equal [posts(:welcome)], posts
assert_equal authors(:david), assert_no_queries { posts[0].author }
posts = assert_queries(2) do
posts = assert_queries_count(2) do
Post.all.merge!(includes: :author, joins: { taggings: :tag }, where: "tags.name = 'General'", order: "posts.id").to_a
end
assert_equal posts(:welcome, :thinking), posts
posts = assert_queries(2) do
posts = assert_queries_count(2) do
Post.all.merge!(includes: :author, joins: { taggings: { tag: :taggings } }, where: "taggings_tags.super_tag_id=2", order: "posts.id").to_a
end
assert_equal posts(:welcome, :thinking), posts
@ -1240,13 +1240,13 @@ def test_preload_has_many_with_association_condition_and_default_scope
end
def test_eager_loading_with_conditions_on_string_joined_table_preloads
posts = assert_queries(2) do
posts = assert_queries_count(2) do
Post.all.merge!(select: "distinct posts.*", includes: :author, joins: "INNER JOIN comments on comments.post_id = posts.id", where: "comments.body like 'Thank you%'", order: "posts.id").to_a
end
assert_equal [posts(:welcome)], posts
assert_equal authors(:david), assert_no_queries { posts[0].author }
posts = assert_queries(2) do
posts = assert_queries_count(2) do
Post.all.merge!(select: "distinct posts.*", includes: :author, joins: ["INNER JOIN comments on comments.post_id = posts.id"], where: "comments.body like 'Thank you%'", order: "posts.id").to_a
end
assert_equal [posts(:welcome)], posts
@ -1254,7 +1254,7 @@ def test_eager_loading_with_conditions_on_string_joined_table_preloads
end
def test_eager_loading_with_select_on_joined_table_preloads
posts = assert_queries(2) do
posts = assert_queries_count(2) do
Post.all.merge!(select: "posts.*, authors.name as author_name", includes: :comments, joins: :author, order: "posts.id").to_a
end
assert_equal "David", posts[0].author_name
@ -1262,7 +1262,7 @@ def test_eager_loading_with_select_on_joined_table_preloads
end
def test_eager_loading_with_conditions_on_join_model_preloads
authors = assert_queries(2) do
authors = assert_queries_count(2) do
Author.all.merge!(includes: :author_address, joins: :comments, where: "posts.title like 'Welcome%'").to_a
end
assert_equal authors(:david), authors[0]
@ -1321,7 +1321,7 @@ def test_include_has_one_using_primary_key
def test_preloading_empty_belongs_to
c = Client.create!(name: "Foo", client_of: Company.maximum(:id) + 1)
client = assert_queries(2) { Client.preload(:firm).find(c.id) }
client = assert_queries_count(2) { Client.preload(:firm).find(c.id) }
assert_no_queries { assert_nil client.firm }
assert_equal c.client_of, client.client_of
end
@ -1329,7 +1329,7 @@ def test_preloading_empty_belongs_to
def test_preloading_empty_belongs_to_polymorphic
t = Tagging.create!(taggable_type: "Post", taggable_id: Post.maximum(:id) + 1, tag: tags(:general))
tagging = assert_queries(2) { Tagging.preload(:taggable).find(t.id) }
tagging = assert_queries_count(2) { Tagging.preload(:taggable).find(t.id) }
assert_no_queries { assert_nil tagging.taggable }
assert_equal t.taggable_id, tagging.taggable_id
end
@ -1337,7 +1337,7 @@ def test_preloading_empty_belongs_to_polymorphic
def test_preloading_through_empty_belongs_to
c = Client.create!(name: "Foo", client_of: Company.maximum(:id) + 1)
client = assert_queries(2) { Client.preload(:accounts).find(c.id) }
client = assert_queries_count(2) { Client.preload(:accounts).find(c.id) }
assert_no_queries { assert_predicate client.accounts, :empty? }
end
@ -1369,14 +1369,14 @@ def test_preloading_polymorphic_with_custom_foreign_type
sponsor = sponsors(:moustache_club_sponsor_for_groucho)
groucho = members(:groucho)
sponsor = assert_queries(2) {
sponsor = assert_queries_count(2) {
Sponsor.includes(:thing).where(id: sponsor.id).first
}
assert_no_queries { assert_equal groucho, sponsor.thing }
end
def test_joins_with_includes_should_preload_via_joins
post = assert_queries(1) { Post.includes(:comments).joins(:comments).order("posts.id desc").to_a.first }
post = assert_queries_count(1) { Post.includes(:comments).joins(:comments).order("posts.id desc").to_a.first }
assert_no_queries do
assert_not_equal 0, post.comments.to_a.count
@ -1501,7 +1501,7 @@ def test_preloading_has_many_through_with_custom_scope
end
test "preloading associations with string joins and order references" do
author = assert_queries(2) {
author = assert_queries_count(2) {
Author.includes(:posts).joins("LEFT JOIN posts ON posts.author_id = authors.id").order("posts.title DESC").first
}
assert_no_queries {
@ -1510,7 +1510,7 @@ def test_preloading_has_many_through_with_custom_scope
end
test "including associations with where.not adds implicit references" do
author = assert_queries(2) {
author = assert_queries_count(2) {
Author.includes(:posts).where.not(posts: { title: "Welcome to the weblog" }).last
}
@ -1651,22 +1651,22 @@ def test_preloading_has_many_through_with_custom_scope
test "preloading through a polymorphic association doesn't require the association to exist" do
sponsors = []
assert_queries 5 do
assert_queries_count 5 do
sponsors = Sponsor.where(sponsorable_id: 1).preload(sponsorable: [:post, :membership]).to_a
end
# check the preload worked
assert_queries 0 do
assert_queries_count 0 do
sponsors.map(&:sponsorable).map { |s| s.respond_to?(:posts) ? s.post.author : s.membership }
end
end
test "preloading a regular association through a polymorphic association doesn't require the association to exist on all types" do
sponsors = []
assert_queries 6 do
assert_queries_count 6 do
sponsors = Sponsor.where(sponsorable_id: 1).preload(sponsorable: [{ post: :first_comment }, :membership]).to_a
end
# check the preload worked
assert_queries 0 do
assert_queries_count 0 do
sponsors.map(&:sponsorable).map { |s| s.respond_to?(:posts) ? s.post.author : s.membership }
end
end

@ -300,7 +300,7 @@ def test_habtm_collection_size_from_params
def test_build
devel = Developer.find(1)
proj = assert_queries(0) { devel.projects.build("name" => "Projekt") }
proj = assert_queries_count(0) { devel.projects.build("name" => "Projekt") }
assert_not_predicate devel.projects, :loaded?
assert_equal devel.projects.last, proj
@ -316,7 +316,7 @@ def test_build
def test_new_aliased_to_build
devel = Developer.find(1)
proj = assert_queries(0) { devel.projects.new("name" => "Projekt") }
proj = assert_queries_count(0) { devel.projects.new("name" => "Projekt") }
assert_not_predicate devel.projects, :loaded?
assert_equal devel.projects.last, proj
@ -537,7 +537,7 @@ def test_include_uses_array_include_after_loaded
developer = project.developers.first
assert_queries(0) do
assert_queries_count(0) do
assert_predicate project.developers, :loaded?
assert_includes project.developers, developer
end
@ -549,7 +549,7 @@ def test_include_checks_if_record_exists_if_target_not_loaded
project.reload
assert_not_predicate project.developers, :loaded?
assert_queries(1) do
assert_queries_count(1) do
assert_includes project.developers, developer
end
assert_not_predicate project.developers, :loaded?
@ -739,7 +739,7 @@ def test_get_ids
def test_get_ids_for_loaded_associations
developer = developers(:david)
developer.projects.reload
assert_queries(0) do
assert_queries_count(0) do
developer.project_ids
developer.project_ids
end
@ -828,13 +828,13 @@ def test_caching_of_columns
# clear cache possibly created by other tests
david.projects.reset_column_information
assert_queries(:any) { david.projects.columns }
assert_queries_count(include_schema: true) { david.projects.columns }
assert_no_queries { david.projects.columns }
## and again to verify that reset_column_information clears the cache correctly
david.projects.reset_column_information
assert_queries(:any) { david.projects.columns }
assert_queries_count(include_schema: true) { david.projects.columns }
assert_no_queries { david.projects.columns }
end
@ -867,7 +867,7 @@ def test_destruction_does_not_error_without_primary_key
def test_has_and_belongs_to_many_associations_on_new_records_use_null_relations
projects = Developer.new.projects
assert_queries(0) do
assert_queries_count(0) do
assert_equal [], projects
assert_equal [], projects.where(title: "omg")
assert_equal [], projects.pluck(:title)

@ -63,7 +63,7 @@ def test_custom_primary_key_on_new_record_should_fetch_with_query
subscriber = Subscriber.new(nick: "webster132")
assert_not_predicate subscriber.subscriptions, :loaded?
assert_queries 1 do
assert_queries_count 1 do
assert_equal 2, subscriber.subscriptions.size
end
@ -74,7 +74,7 @@ def test_association_primary_key_on_new_record_should_fetch_with_query
author = Author.new(name: "David")
assert_not_predicate author.essays, :loaded?
assert_queries 1 do
assert_queries_count 1 do
assert_equal 1, author.essays.size
end
@ -109,7 +109,7 @@ def test_blank_custom_primary_key_on_new_record_should_not_run_queries
author = Author.new
assert_not_predicate author.essays, :loaded?
assert_queries 0 do
assert_queries_count 0 do
assert_equal 0, author.essays.size
end
end
@ -560,14 +560,14 @@ def test_finder_method_with_dirty_target
company = companies(:first_firm)
new_clients = []
assert_queries(0) do
assert_queries_count(0) do
new_clients << company.clients_of_firm.build(name: "Another Client")
new_clients << company.clients_of_firm.build(name: "Another Client II")
new_clients << company.clients_of_firm.build(name: "Another Client III")
end
assert_not_predicate company.clients_of_firm, :loaded?
assert_queries(1) do
assert_queries_count(1) do
assert_same new_clients[0], company.clients_of_firm.third
assert_same new_clients[1], company.clients_of_firm.fourth
assert_same new_clients[2], company.clients_of_firm.fifth
@ -581,14 +581,14 @@ def test_finder_bang_method_with_dirty_target
company = companies(:first_firm)
new_clients = []
assert_queries(0) do
assert_queries_count(0) do
new_clients << company.clients_of_firm.build(name: "Another Client")
new_clients << company.clients_of_firm.build(name: "Another Client II")
new_clients << company.clients_of_firm.build(name: "Another Client III")
end
assert_not_predicate company.clients_of_firm, :loaded?
assert_queries(1) do
assert_queries_count(1) do
assert_same new_clients[0], company.clients_of_firm.third!
assert_same new_clients[1], company.clients_of_firm.fourth!
assert_same new_clients[2], company.clients_of_firm.fifth!
@ -834,7 +834,7 @@ def test_find_each
assert_not_predicate firm.clients, :loaded?
assert_queries(4) do
assert_queries_count(4) do
firm.clients.find_each(batch_size: 1) { |c| assert_equal firm.id, c.firm_id }
end
@ -844,7 +844,7 @@ def test_find_each
def test_find_each_with_conditions
firm = companies(:first_firm)
assert_queries(2) do
assert_queries_count(2) do
firm.clients.where(name: "Microsoft").find_each(batch_size: 1) do |c|
assert_equal firm.id, c.firm_id
assert_equal "Microsoft", c.name
@ -859,7 +859,7 @@ def test_find_in_batches
assert_not_predicate firm.clients, :loaded?
assert_queries(2) do
assert_queries_count(2) do
firm.clients.find_in_batches(batch_size: 2) do |clients|
clients.each { |c| assert_equal firm.id, c.firm_id }
end
@ -937,9 +937,9 @@ def test_reload_with_query_cache
assert_equal 2, connection.query_cache.size
# Clear the cache and fetch the clients again, populating the cache with a query
assert_queries(1) { firm.clients.reload }
assert_queries_count(1) { firm.clients.reload }
# This query is cached, so it shouldn't make a real SQL query
assert_queries(0) { firm.clients.load }
assert_queries_count(0) { firm.clients.load }
assert_equal 1, connection.query_cache.size
ensure
@ -1106,14 +1106,14 @@ def test_transactions_when_adding_to_persisted
def test_transactions_when_adding_to_new_record
firm = Firm.new
assert_queries(0) do
assert_queries_count(0) do
firm.clients_of_firm.concat(Client.new("name" => "Natural Company"))
end
end
def test_inverse_on_before_validate
firm = companies(:first_firm)
assert_queries(1) do
assert_queries_count(3) do
firm.clients_of_firm << Client.new("name" => "Natural Company")
end
end
@ -1121,7 +1121,7 @@ def test_inverse_on_before_validate
def test_new_aliased_to_build
company = companies(:first_firm)
new_client = assert_queries(0) { company.clients_of_firm.new("name" => "Another Client") }
new_client = assert_queries_count(0) { company.clients_of_firm.new("name" => "Another Client") }
assert_not_predicate company.clients_of_firm, :loaded?
assert_equal "Another Client", new_client.name
@ -1132,7 +1132,7 @@ def test_new_aliased_to_build
def test_build
company = companies(:first_firm)
new_client = assert_queries(0) { company.clients_of_firm.build("name" => "Another Client") }
new_client = assert_queries_count(0) { company.clients_of_firm.build("name" => "Another Client") }
assert_not_predicate company.clients_of_firm, :loaded?
assert_equal "Another Client", new_client.name
@ -1190,7 +1190,7 @@ def test_collection_size_twice_for_regressions
def test_build_many
company = companies(:first_firm)
new_clients = assert_queries(0) { company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) }
new_clients = assert_queries_count(0) { company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) }
assert_equal 2, new_clients.size
end
@ -1205,7 +1205,7 @@ def test_build_without_loading_association
assert_equal 1, first_topic.replies.length
assert_queries(0) do
assert_queries_count(0) do
first_topic.replies.build(title: "Not saved", content: "Superstars")
assert_equal 2, first_topic.replies.size
end
@ -1216,7 +1216,7 @@ def test_build_without_loading_association
def test_build_via_block
company = companies(:first_firm)
new_client = assert_queries(0) { company.clients_of_firm.build { |client| client.name = "Another Client" } }
new_client = assert_queries_count(0) { company.clients_of_firm.build { |client| client.name = "Another Client" } }
assert_not_predicate company.clients_of_firm, :loaded?
assert_equal "Another Client", new_client.name
@ -1227,7 +1227,7 @@ def test_build_via_block
def test_build_many_via_block
company = companies(:first_firm)
new_clients = assert_queries(0) do
new_clients = assert_queries_count(0) do
company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) do |client|
client.name = "changed"
end
@ -1244,7 +1244,7 @@ def test_create_without_loading_association
assert_equal 2, first_firm.clients_of_firm.size
first_firm.clients_of_firm.reset
assert_queries(1) do
assert_queries_count(3) do
first_firm.clients_of_firm.create(name: "Superstars")
end
@ -1323,7 +1323,7 @@ def test_sharded_deleting_models
query_constraints = /#{blog_id} = .* AND #{id} = .*/
expectation = /DELETE.*WHERE.* \(#{query_constraints} OR #{query_constraints}\)/
assert_match(expectation, sql.first)
assert_match(expectation, sql.second)
blog_post.reload
@ -1396,7 +1396,7 @@ def test_counter_cache_updates_in_memory_after_update_with_inverse_of_disabled
reply1 = Reply.create!(title: "re: zoom", content: "speedy quick!")
reply2 = Reply.create!(title: "re: zoom 2", content: "OMG lol!")
assert_queries(4) do
assert_queries_count(6) do
topic.replies << [reply1, reply2]
end
@ -1429,7 +1429,7 @@ def test_counter_cache_updates_in_memory_after_update_with_inverse_of_enabled
categorization1 = Categorization.create!
categorization2 = Categorization.create!
assert_queries(4) do
assert_queries_count(6) do
category.categorizations << [categorization1, categorization2]
end
@ -1591,7 +1591,7 @@ def test_transaction_when_deleting_persisted
def test_transaction_when_deleting_new_record
firm = Firm.new
assert_queries(0) do
assert_queries_count(0) do
client = Client.new("name" => "New Client")
firm.clients_of_firm << client
firm.clients_of_firm.destroy(client)
@ -2107,7 +2107,7 @@ def test_transactions_when_replacing_on_persisted
def test_transactions_when_replacing_on_new_record
firm = Firm.new
assert_queries(0) do
assert_queries_count(0) do
firm.clients_of_firm = [Client.new("name" => "New Client")]
end
end
@ -2162,7 +2162,7 @@ def test_get_ids_for_ordered_association
def test_get_ids_for_association_on_new_record_does_not_try_to_find_records
company = Company.new
assert_queries(0) do
assert_queries_count(0) do
company.contract_ids
end
@ -2243,7 +2243,7 @@ def test_include_checks_if_record_exists_if_target_not_loaded
firm.reload
assert_not_predicate firm.clients, :loaded?
assert_queries(1) do
assert_queries_count(1) do
assert_equal true, firm.clients.include?(client)
end
assert_not_predicate firm.clients, :loaded?
@ -2283,7 +2283,7 @@ def test_calling_first_nth_or_last_on_existing_record_with_build_should_load_ass
firm.clients.build(name: "Foo")
assert_not_predicate firm.clients, :loaded?
assert_queries 1 do
assert_queries_count 1 do
firm.clients.first
firm.clients.second
firm.clients.last
@ -2299,7 +2299,7 @@ def test_calling_first_nth_or_last_on_existing_record_with_build_should_load_ass
assert_not_predicate author.topics_without_type, :loaded?
assert_queries(1) do
assert_queries_count(1) do
if current_adapter?(:Mysql2Adapter, :TrilogyAdapter, :SQLite3Adapter)
assert_equal fourth, author.topics_without_type.first
assert_equal third, author.topics_without_type.second
@ -2315,7 +2315,7 @@ def test_calling_first_nth_or_last_on_existing_record_with_create_should_not_loa
firm.clients.create(name: "Foo")
assert_not_predicate firm.clients, :loaded?
assert_queries 3 do
assert_queries_count 3 do
firm.clients.first
firm.clients.second
firm.clients.last
@ -2339,7 +2339,7 @@ def test_calling_first_or_last_with_integer_on_association_should_not_load_assoc
firm.clients.create(name: "Foo")
assert_not_predicate firm.clients, :loaded?
assert_queries 2 do
assert_queries_count 2 do
firm.clients.first(2)
firm.clients.last(2)
end
@ -2349,7 +2349,7 @@ def test_calling_first_or_last_with_integer_on_association_should_not_load_assoc
def test_calling_many_should_count_instead_of_loading_association
firm = companies(:first_firm)
assert_queries(1) do
assert_queries_count(1) do
firm.clients.many? # use count query
end
assert_not_predicate firm.clients, :loaded?
@ -2363,7 +2363,7 @@ def test_calling_many_on_loaded_association_should_not_use_query
def test_subsequent_calls_to_many_should_use_query
firm = companies(:first_firm)
assert_queries(2) do
assert_queries_count(2) do
firm.clients.many?
firm.clients.many?
end
@ -2371,7 +2371,7 @@ def test_subsequent_calls_to_many_should_use_query
def test_calling_many_should_defer_to_collection_if_using_a_block
firm = companies(:first_firm)
assert_queries(1) do
assert_queries_count(1) do
assert_not_called(firm.clients, :size) do
firm.clients.many? { true }
end
@ -2397,7 +2397,7 @@ def test_calling_many_should_return_true_if_more_than_one
def test_calling_none_should_count_instead_of_loading_association
firm = companies(:first_firm)
assert_queries(1) do
assert_queries_count(1) do
firm.clients.none? # use count query
end
assert_not_predicate firm.clients, :loaded?
@ -2411,7 +2411,7 @@ def test_calling_none_on_loaded_association_should_not_use_query
def test_calling_none_should_defer_to_collection_if_using_a_block
firm = companies(:first_firm)
assert_queries(1) do
assert_queries_count(1) do
assert_not_called(firm.clients, :size) do
firm.clients.none? { true }
end
@ -2433,7 +2433,7 @@ def test_calling_none_should_return_false_if_any
def test_calling_one_should_count_instead_of_loading_association
firm = companies(:first_firm)
assert_queries(1) do
assert_queries_count(1) do
firm.clients.one? # use count query
end
assert_not_predicate firm.clients, :loaded?
@ -2447,7 +2447,7 @@ def test_calling_one_on_loaded_association_should_not_use_query
def test_subsequent_calls_to_one_should_use_query
firm = companies(:first_firm)
assert_queries(2) do
assert_queries_count(2) do
firm.clients.one?
firm.clients.one?
end
@ -2455,7 +2455,7 @@ def test_subsequent_calls_to_one_should_use_query
def test_calling_one_should_defer_to_collection_if_using_a_block
firm = companies(:first_firm)
assert_queries(1) do
assert_queries_count(1) do
assert_not_called(firm.clients, :size) do
firm.clients.one? { true }
end
@ -2748,7 +2748,7 @@ def test_association_with_rewhere_doesnt_set_inverse_instance_key
assert_not_predicate post.taggings_with_delete_all, :loaded?
# 2 queries: one DELETE and another to update the counter cache
assert_queries(2) do
assert_queries_count(2) do
post.taggings_with_delete_all.delete_all
end
end
@ -3034,11 +3034,11 @@ def self.name
car_two = Car.create!
assert_queries(1) do
assert_queries_count(1) do
assert_equal 1, car.bulbs.size
end
assert_queries(1) do
assert_queries_count(1) do
assert_equal 0, car_two.bulbs.size
end
end
@ -3066,11 +3066,11 @@ def self.name
car_two = Car.create!
assert_queries(1) do
assert_queries_count(1) do
assert_not_empty car.bulbs
end
assert_queries(1) do
assert_queries_count(1) do
assert_empty car_two.bulbs
end
end

@ -221,11 +221,11 @@ def test_associate_existing
post = posts(:thinking)
person = people(:david)
assert_queries(1) do
assert_queries_count(3) do
post.people << person
end
assert_queries(1) do
assert_queries_count(1) do
assert_includes post.people, person
end
@ -318,20 +318,20 @@ def test_add_two_instance_and_then_deleting
end
def test_associating_new
assert_queries(1) { posts(:thinking) }
assert_queries_count(1) { posts(:thinking) }
new_person = nil # so block binding catches it
assert_queries(0) do
assert_queries_count(0) do
new_person = Person.new first_name: "bob"
end
# Associating new records always saves them
# Thus, 1 query for the new person record, 1 query for the new join table record
assert_queries(2) do
assert_queries_count(4) do
posts(:thinking).people << new_person
end
assert_queries(1) do
assert_queries_count(1) do
assert_includes posts(:thinking).people, new_person
end
@ -339,15 +339,15 @@ def test_associating_new
end
def test_associate_new_by_building
assert_queries(1) { posts(:thinking) }
assert_queries_count(1) { posts(:thinking) }
assert_queries(0) do
assert_queries_count(0) do
posts(:thinking).people.build(first_name: "Bob")
posts(:thinking).people.new(first_name: "Ted")
end
# Should only need to load the association once
assert_queries(1) do
assert_queries_count(1) do
assert_includes posts(:thinking).people.collect(&:first_name), "Bob"
assert_includes posts(:thinking).people.collect(&:first_name), "Ted"
end
@ -355,7 +355,7 @@ def test_associate_new_by_building
# 2 queries for each new record (1 to save the record itself, 1 for the join model)
# * 2 new records = 4
# + 1 query to save the actual post = 5
assert_queries(5) do
assert_queries_count(7) do
posts(:thinking).body += "-changed"
posts(:thinking).save
end
@ -407,13 +407,13 @@ def test_both_parent_ids_set_when_saving_new
end
def test_delete_association
assert_queries(2) { posts(:welcome); people(:michael) }
assert_queries_count(2) { posts(:welcome); people(:michael) }
assert_queries(1) do
assert_queries_count(3) do
posts(:welcome).people.delete(people(:michael))
end
assert_queries(1) do
assert_queries_count(1) do
assert_empty posts(:welcome).people
end
@ -659,11 +659,11 @@ def test_update_counter_caches_on_destroy_with_indestructible_through_record
end
def test_replace_association
assert_queries(4) { posts(:welcome); people(:david); people(:michael); posts(:welcome).people.reload }
assert_queries_count(4) { posts(:welcome); people(:david); people(:michael); posts(:welcome).people.reload }
# 1 query to delete the existing reader (michael)
# 1 query to associate the new reader (david)
assert_queries(2) do
assert_queries_count(4) do
posts(:welcome).people = [people(:david)]
end
@ -709,16 +709,16 @@ def test_replace_by_id_order_is_preserved
end
def test_associate_with_create
assert_queries(1) { posts(:thinking) }
assert_queries_count(1) { posts(:thinking) }
# 1 query for the new record, 1 for the join table record
# No need to update the actual collection yet!
assert_queries(2) do
assert_queries_count(4) do
posts(:thinking).people.create(first_name: "Jeb")
end
# *Now* we actually need the collection so it's loaded
assert_queries(1) do
assert_queries_count(1) do
assert_includes posts(:thinking).people.collect(&:first_name), "Jeb"
end
@ -804,9 +804,9 @@ def test_push_with_invalid_join_record
end
def test_clear_associations
assert_queries(2) { posts(:welcome); posts(:welcome).people.reload }
assert_queries_count(2) { posts(:welcome); posts(:welcome).people.reload }
assert_queries(1) do
assert_queries_count(1) do
posts(:welcome).people.clear
end

@ -34,120 +34,120 @@ def setup
def test_counting_on_disable_joins_through
assert_equal @author.comments.count, @author.no_joins_comments.count
assert_queries(2) { @author.no_joins_comments.count }
assert_queries(1) { @author.comments.count }
assert_queries_count(2) { @author.no_joins_comments.count }
assert_queries_count(1) { @author.comments.count }
end
def test_counting_on_disable_joins_through_using_custom_foreign_key
assert_equal @author.comments_with_foreign_key.count, @author.no_joins_comments_with_foreign_key.count
assert_queries(2) { @author.no_joins_comments_with_foreign_key.count }
assert_queries(1) { @author.comments_with_foreign_key.count }
assert_queries_count(2) { @author.no_joins_comments_with_foreign_key.count }
assert_queries_count(1) { @author.comments_with_foreign_key.count }
end
def test_pluck_on_disable_joins_through
assert_equal @author.comments.pluck(:id).sort, @author.no_joins_comments.pluck(:id).sort
assert_queries(2) { @author.no_joins_comments.pluck(:id) }
assert_queries(1) { @author.comments.pluck(:id) }
assert_queries_count(2) { @author.no_joins_comments.pluck(:id) }
assert_queries_count(1) { @author.comments.pluck(:id) }
end
def test_pluck_on_disable_joins_through_using_custom_foreign_key
assert_equal @author.comments_with_foreign_key.pluck(:id).sort, @author.no_joins_comments_with_foreign_key.pluck(:id).sort
assert_queries(2) { @author.no_joins_comments_with_foreign_key.pluck(:id) }
assert_queries(1) { @author.comments_with_foreign_key.pluck(:id) }
assert_queries_count(2) { @author.no_joins_comments_with_foreign_key.pluck(:id) }
assert_queries_count(1) { @author.comments_with_foreign_key.pluck(:id) }
end
def test_fetching_on_disable_joins_through
assert_equal @author.comments.first.id, @author.no_joins_comments.first.id
assert_queries(2) { @author.no_joins_comments.first.id }
assert_queries(1) { @author.comments.first.id }
assert_queries_count(2) { @author.no_joins_comments.first.id }
assert_queries_count(1) { @author.comments.first.id }
end
def test_fetching_on_disable_joins_through_using_custom_foreign_key
assert_equal @author.comments_with_foreign_key.first.id, @author.no_joins_comments_with_foreign_key.first.id
assert_queries(2) { @author.no_joins_comments_with_foreign_key.first.id }
assert_queries(1) { @author.comments_with_foreign_key.first.id }
assert_queries_count(2) { @author.no_joins_comments_with_foreign_key.first.id }
assert_queries_count(1) { @author.comments_with_foreign_key.first.id }
end
def test_to_a_on_disable_joins_through
assert_equal @author.comments.sort_by(&:id), @author.no_joins_comments.sort_by(&:id)
@author.reload
assert_queries(2) { @author.no_joins_comments.to_a }
assert_queries(1) { @author.comments.to_a }
assert_queries_count(2) { @author.no_joins_comments.to_a }
assert_queries_count(1) { @author.comments.to_a }
end
def test_appending_on_disable_joins_through
assert_difference(->() { @author.no_joins_comments.reload.size }) do
@post.comments.create(body: "text")
end
assert_queries(2) { @author.no_joins_comments.reload.size }
assert_queries(1) { @author.comments.reload.size }
assert_queries_count(2) { @author.no_joins_comments.reload.size }
assert_queries_count(1) { @author.comments.reload.size }
end
def test_appending_on_disable_joins_through_using_custom_foreign_key
assert_difference(->() { @author.no_joins_comments_with_foreign_key.reload.size }) do
@post.comments.create(body: "text")
end
assert_queries(2) { @author.no_joins_comments_with_foreign_key.reload.size }
assert_queries(1) { @author.comments_with_foreign_key.reload.size }
assert_queries_count(2) { @author.no_joins_comments_with_foreign_key.reload.size }
assert_queries_count(1) { @author.comments_with_foreign_key.reload.size }
end
def test_empty_on_disable_joins_through
empty_author = authors(:bob)
assert_equal [], assert_queries(0) { empty_author.comments.all }
assert_equal [], assert_queries(1) { empty_author.no_joins_comments.all }
assert_equal [], assert_queries_count(0) { empty_author.comments.all }
assert_equal [], assert_queries_count(1) { empty_author.no_joins_comments.all }
end
def test_empty_on_disable_joins_through_using_custom_foreign_key
empty_author = authors(:bob)
assert_equal [], assert_queries(0) { empty_author.comments_with_foreign_key.all }
assert_equal [], assert_queries(1) { empty_author.no_joins_comments_with_foreign_key.all }
assert_equal [], assert_queries_count(0) { empty_author.comments_with_foreign_key.all }
assert_equal [], assert_queries_count(1) { empty_author.no_joins_comments_with_foreign_key.all }
end
def test_pluck_on_disable_joins_through_a_through
rating_ids = Rating.where(comment: @comment).pluck(:id).sort
assert_equal rating_ids, assert_queries(1) { @author.ratings.pluck(:id).sort }
assert_equal rating_ids, assert_queries(3) { @author.no_joins_ratings.pluck(:id).sort }
assert_equal rating_ids, assert_queries_count(1) { @author.ratings.pluck(:id).sort }
assert_equal rating_ids, assert_queries_count(3) { @author.no_joins_ratings.pluck(:id).sort }
end
def test_count_on_disable_joins_through_a_through
ratings_count = Rating.where(comment: @comment).count
assert_equal ratings_count, assert_queries(1) { @author.ratings.count }
assert_equal ratings_count, assert_queries(3) { @author.no_joins_ratings.count }
assert_equal ratings_count, assert_queries_count(1) { @author.ratings.count }
assert_equal ratings_count, assert_queries_count(3) { @author.no_joins_ratings.count }
end
def test_count_on_disable_joins_using_relation_with_scope
assert_equal 2, assert_queries(1) { @author.good_ratings.count }
assert_equal 2, assert_queries(3) { @author.no_joins_good_ratings.count }
assert_equal 2, assert_queries_count(1) { @author.good_ratings.count }
assert_equal 2, assert_queries_count(3) { @author.no_joins_good_ratings.count }
end
def test_to_a_on_disable_joins_with_multiple_scopes
assert_equal [@rating1, @rating2], assert_queries(1) { @author.good_ratings.to_a }
assert_equal [@rating1, @rating2], assert_queries(3) { @author.no_joins_good_ratings.to_a }
assert_equal [@rating1, @rating2], assert_queries_count(1) { @author.good_ratings.to_a }
assert_equal [@rating1, @rating2], assert_queries_count(3) { @author.no_joins_good_ratings.to_a }
end
def test_preloading_has_many_through_disable_joins
assert_queries(3) { Author.all.preload(:good_ratings).map(&:good_ratings) }
assert_queries(4) { Author.all.preload(:no_joins_good_ratings).map(&:good_ratings) }
assert_queries_count(3) { Author.all.preload(:good_ratings).map(&:good_ratings) }
assert_queries_count(4) { Author.all.preload(:no_joins_good_ratings).map(&:good_ratings) }
end
def test_polymophic_disable_joins_through_counting
assert_equal 2, assert_queries(1) { @author.ordered_members.count }
assert_equal 2, assert_queries(3) { @author.no_joins_ordered_members.count }
assert_equal 2, assert_queries_count(1) { @author.ordered_members.count }
assert_equal 2, assert_queries_count(3) { @author.no_joins_ordered_members.count }
end
def test_polymophic_disable_joins_through_ordering
assert_equal [@member2, @member], assert_queries(1) { @author.ordered_members.to_a }
assert_equal [@member2, @member], assert_queries(3) { @author.no_joins_ordered_members.to_a }
assert_equal [@member2, @member], assert_queries_count(1) { @author.ordered_members.to_a }
assert_equal [@member2, @member], assert_queries_count(3) { @author.no_joins_ordered_members.to_a }
end
def test_polymorphic_disable_joins_through_reordering
assert_equal [@member, @member2], assert_queries(1) { @author.ordered_members.reorder(id: :asc).to_a }
assert_equal [@member, @member2], assert_queries(3) { @author.no_joins_ordered_members.reorder(id: :asc).to_a }
assert_equal [@member, @member2], assert_queries_count(1) { @author.ordered_members.reorder(id: :asc).to_a }
assert_equal [@member, @member2], assert_queries_count(3) { @author.no_joins_ordered_members.reorder(id: :asc).to_a }
end
def test_polymorphic_disable_joins_through_ordered_scopes
assert_equal [@member2, @member], assert_queries(1) { @author.ordered_members.unnamed.to_a }
assert_equal [@member2, @member], assert_queries(3) { @author.no_joins_ordered_members.unnamed.to_a }
assert_equal [@member2, @member], assert_queries_count(1) { @author.ordered_members.unnamed.to_a }
assert_equal [@member2, @member], assert_queries_count(3) { @author.no_joins_ordered_members.unnamed.to_a }
end
def test_polymorphic_disable_joins_through_ordered_chained_scopes
@ -156,28 +156,28 @@ def test_polymorphic_disable_joins_through_ordered_chained_scopes
@post2.comments.create(body: "text", origin: member3)
@post2.comments.create(body: "text", origin: member4)
assert_equal [member3, @member2, @member], assert_queries(1) { @author.ordered_members.unnamed.with_member_type_id(@member_type.id).to_a }
assert_equal [member3, @member2, @member], assert_queries(3) { @author.no_joins_ordered_members.unnamed.with_member_type_id(@member_type.id).to_a }
assert_equal [member3, @member2, @member], assert_queries_count(1) { @author.ordered_members.unnamed.with_member_type_id(@member_type.id).to_a }
assert_equal [member3, @member2, @member], assert_queries_count(3) { @author.no_joins_ordered_members.unnamed.with_member_type_id(@member_type.id).to_a }
end
def test_polymorphic_disable_joins_through_ordered_scope_limits
assert_equal [@member2], assert_queries(1) { @author.ordered_members.unnamed.limit(1).to_a }
assert_equal [@member2], assert_queries(3) { @author.no_joins_ordered_members.unnamed.limit(1).to_a }
assert_equal [@member2], assert_queries_count(1) { @author.ordered_members.unnamed.limit(1).to_a }
assert_equal [@member2], assert_queries_count(3) { @author.no_joins_ordered_members.unnamed.limit(1).to_a }
end
def test_polymorphic_disable_joins_through_ordered_scope_first
assert_equal @member2, assert_queries(1) { @author.ordered_members.unnamed.first }
assert_equal @member2, assert_queries(3) { @author.no_joins_ordered_members.unnamed.first }
assert_equal @member2, assert_queries_count(1) { @author.ordered_members.unnamed.first }
assert_equal @member2, assert_queries_count(3) { @author.no_joins_ordered_members.unnamed.first }
end
def test_order_applied_in_double_join
assert_equal [@member2, @member], assert_queries(1) { @author.members.to_a }
assert_equal [@member2, @member], assert_queries(3) { @author.no_joins_members.to_a }
assert_equal [@member2, @member], assert_queries_count(1) { @author.members.to_a }
assert_equal [@member2, @member], assert_queries_count(3) { @author.no_joins_members.to_a }
end
def test_first_and_scope_applied_in_double_join
assert_equal @member2, assert_queries(1) { @author.members.unnamed.first }
assert_equal @member2, assert_queries(3) { @author.no_joins_members.unnamed.first }
assert_equal @member2, assert_queries_count(1) { @author.members.unnamed.first }
assert_equal @member2, assert_queries_count(3) { @author.no_joins_members.unnamed.first }
end
def test_first_and_scope_in_double_join_applies_order_in_memory
@ -186,8 +186,8 @@ def test_first_and_scope_in_double_join_applies_order_in_memory
end
def test_limit_and_scope_applied_in_double_join
assert_equal [@member2], assert_queries(1) { @author.members.unnamed.limit(1).to_a }
assert_equal [@member2], assert_queries(3) { @author.no_joins_members.unnamed.limit(1) }
assert_equal [@member2], assert_queries_count(1) { @author.members.unnamed.limit(1).to_a }
assert_equal [@member2], assert_queries_count(3) { @author.no_joins_members.unnamed.limit(1) }
end
def test_limit_and_scope_in_double_join_applies_limit_in_memory

@ -33,7 +33,7 @@ def setup
def test_has_one
firm = companies(:first_firm)
first_account = Account.find(1)
assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) do
assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) do
assert_equal first_account, firm.account
assert_equal first_account.credit_limit, firm.account.credit_limit
end
@ -46,7 +46,7 @@ def test_has_one_does_not_use_order_by
def test_has_one_cache_nils
firm = companies(:another_firm)
assert_queries(1) { assert_nil firm.account }
assert_queries_count(1) { assert_nil firm.account }
assert_no_queries { assert_nil firm.account }
firms = Firm.includes(:account).to_a
@ -268,7 +268,7 @@ def test_successful_build_association
def test_build_association_dont_create_transaction
firm = Firm.new
assert_queries(0) do
assert_queries_count(0) do
firm.build_account
end
end
@ -377,7 +377,7 @@ def test_reload_association
Account.where(id: odegy.account.id).update_all(credit_limit: 80)
assert_equal 53, odegy.account.credit_limit
assert_queries(1) { odegy.reload_account }
assert_queries_count(1) { odegy.reload_account }
assert_no_queries { odegy.account }
assert_equal 80, odegy.account.credit_limit
end
@ -397,10 +397,10 @@ def test_reload_association_with_query_cache
assert_equal 2, connection.query_cache.size
# Clear the cache and fetch the account again, populating the cache with a query
assert_queries(1) { odegy.reload_account }
assert_queries_count(1) { odegy.reload_account }
# This query is not cached anymore, so it should make a real SQL query
assert_queries(1) { Company.find(odegy_id) }
assert_queries_count(1) { Company.find(odegy_id) }
ensure
ActiveRecord::Base.connection.disable_query_cache!
end
@ -414,7 +414,7 @@ def test_reset_association
assert_no_queries { odegy.reset_account }
assert_queries(1) { odegy.account }
assert_queries_count(1) { odegy.account }
assert_equal 80, odegy.account.credit_limit
end
@ -669,7 +669,7 @@ def test_has_one_transaction
company.account = nil
assert_no_queries { company.account = nil }
account = Account.find(2)
assert_queries { company.account = account }
assert_queries_count(3) { company.account = account }
assert_no_queries { Firm.new.account = account }
end
@ -681,7 +681,7 @@ def test_has_one_assignment_dont_trigger_save_on_change_of_same_object
ship.name = "new name"
assert_predicate ship, :changed?
assert_queries(1) do
assert_queries_count(3) do
# One query for updating name, not triggering query for updating pirate_id
pirate.ship = ship
end
@ -695,7 +695,7 @@ def test_has_one_assignment_triggers_save_on_change_on_replacing_object
ship.save!
new_ship = Ship.create(name: "new name")
assert_queries(2) do
assert_queries_count(4) do
# One query to nullify the old ship, one query to update the new ship
pirate.ship = new_ship
end
@ -751,13 +751,13 @@ def test_with_polymorphic_has_one_with_custom_columns_name
end
def test_has_one_with_touch_option_on_create
assert_queries(3) {
assert_queries_count(5) {
Club.create(name: "1000 Oaks", membership_attributes: { favorite: true })
}
end
def test_polymorphic_has_one_with_touch_option_on_create_wont_cache_association_so_fetching_after_transaction_commit_works
assert_queries(4) {
assert_queries_count(6) {
chef = Chef.create(employable: DrinkDesignerWithPolymorphicTouchChef.new)
employable = chef.employable
@ -769,7 +769,7 @@ def test_polymorphic_has_one_with_touch_option_on_update_will_touch_record_by_fe
DrinkDesignerWithPolymorphicTouchChef.create(chef: Chef.new)
designer = DrinkDesignerWithPolymorphicTouchChef.last
assert_queries(3) {
assert_queries_count(5) {
designer.update(name: "foo")
}
end
@ -778,21 +778,21 @@ def test_has_one_with_touch_option_on_update
new_club = Club.create(name: "1000 Oaks")
new_club.create_membership
assert_queries(2) { new_club.update(name: "Effingut") }
assert_queries_count(4) { new_club.update(name: "Effingut") }
end
def test_has_one_with_touch_option_on_touch
new_club = Club.create(name: "1000 Oaks")
new_club.create_membership
assert_queries(1) { new_club.touch }
assert_queries_count(3) { new_club.touch }
end
def test_has_one_with_touch_option_on_destroy
new_club = Club.create(name: "1000 Oaks")
new_club.create_membership
assert_queries(2) { new_club.destroy }
assert_queries_count(4) { new_club.destroy }
end
def test_has_one_with_touch_option_on_empty_update
@ -910,7 +910,7 @@ class SpecialBulb < ActiveRecord::Base
def test_has_one_with_touch_option_on_nonpersisted_built_associations_doesnt_update_parent
car = SpecialCar.create(name: "honda")
assert_queries(1) do
assert_queries_count(1) do
car.build_special_bulb
car.build_special_bulb
end

@ -38,7 +38,7 @@ def test_has_one_through_with_has_one
def test_has_one_through_executes_limited_query
boring_club = clubs(:boring_club)
assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) do
assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) do
assert_equal boring_club, @member.general_club
end
end
@ -165,7 +165,7 @@ def test_has_one_through_polymorphic
end
def test_has_one_through_eager_loading
members = assert_queries(3) do # base table, through table, clubs table
members = assert_queries_count(3) do # base table, through table, clubs table
Member.all.merge!(includes: :club, where: ["name = ?", "Groucho Marx"]).to_a
end
assert_equal 1, members.size
@ -173,7 +173,7 @@ def test_has_one_through_eager_loading
end
def test_has_one_through_eager_loading_through_polymorphic
members = assert_queries(3) do # base table, through table, clubs table
members = assert_queries_count(3) do # base table, through table, clubs table
Member.all.merge!(includes: :sponsor_club, where: ["name = ?", "Groucho Marx"]).to_a
end
assert_equal 1, members.size
@ -203,7 +203,7 @@ def test_eager_has_one_through_polymorphic_with_source_type
end
def test_has_one_through_nonpreload_eagerloading
members = assert_queries(1) do
members = assert_queries_count(1) do
Member.all.merge!(includes: :club, where: ["members.name = ?", "Groucho Marx"], order: "clubs.name").to_a # force fallback
end
assert_equal 1, members.size
@ -211,7 +211,7 @@ def test_has_one_through_nonpreload_eagerloading
end
def test_has_one_through_nonpreload_eager_loading_through_polymorphic
members = assert_queries(1) do
members = assert_queries_count(1) do
Member.all.merge!(includes: :sponsor_club, where: ["members.name = ?", "Groucho Marx"], order: "clubs.name").to_a # force fallback
end
assert_equal 1, members.size
@ -220,7 +220,7 @@ def test_has_one_through_nonpreload_eager_loading_through_polymorphic
def test_has_one_through_nonpreload_eager_loading_through_polymorphic_with_more_than_one_through_record
Sponsor.new(sponsor_club: clubs(:outrageous_club), sponsorable: members(:groucho)).save!
members = assert_queries(1) do
members = assert_queries_count(1) do
Member.all.merge!(includes: :sponsor_club, where: ["members.name = ?", "Groucho Marx"], order: "clubs.name DESC").to_a # force fallback
end
assert_equal 1, members.size
@ -290,7 +290,7 @@ def test_preloading_has_one_through_on_belongs_to
@member_detail = MemberDetail.new
@member.member_detail = @member_detail
@member.organization = @organization
@member_details = assert_queries(3) do
@member_details = assert_queries_count(3) do
MemberDetail.all.merge!(includes: :member_type).to_a
end
@new_detail = @member_details[0]
@ -322,13 +322,13 @@ def test_through_belongs_to_after_destroy
assert_not_nil @member_detail.member_type
@member_detail.destroy
assert_queries(1) do
assert_queries_count(1) do
@member_detail.association(:member_type).reload
assert_not_nil @member_detail.member_type
end
@member_detail.member.destroy
assert_queries(1) do
assert_queries_count(1) do
@member_detail.association(:member_type).reload
assert_nil @member_detail.member_type
end

@ -37,8 +37,8 @@ def test_counting_on_disable_joins_through
def test_nil_on_disable_joins_through
member = members(:blarpy_winkup)
assert_nil assert_queries(1) { member.organization }
assert_nil assert_queries(1) { member.organization_without_joins }
assert_nil assert_queries_count(1) { member.organization }
assert_nil assert_queries_count(1) { member.organization_without_joins }
end
def test_preload_on_disable_joins_through

@ -43,7 +43,7 @@ def test_construct_finder_sql_does_not_table_name_collide_with_string_joins
SQL
expected = people(:susan)
assert_sql(/agents_people_2/i) do
assert_queries_match(/agents_people_2/i) do
assert_equal [expected], Person.joins(:agents).joins(string_join)
end
end
@ -54,7 +54,7 @@ def test_construct_finder_sql_does_not_table_name_collide_with_aliased_joins
constraint = agents[:primary_contact_id].eq(agents_2[:id]).and(agents[:id].gt(agents_2[:id]))
expected = people(:susan)
assert_sql(/agents_people_2/i) do
assert_queries_match(/agents_people_2/i) do
assert_equal [expected], Person.joins(:agents).joins(agents.create_join(agents, agents.create_on(constraint)))
end
end

@ -45,9 +45,9 @@ def test_has_many_distinct_through_join_model
def test_has_many_distinct_through_count
author = authors(:mary)
assert_not_predicate authors(:mary).unique_categorized_posts, :loaded?
assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count }
assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count(:title) }
assert_queries(1) { assert_equal 0, author.unique_categorized_posts.where(title: nil).count(:title) }
assert_queries_count(1) { assert_equal 1, author.unique_categorized_posts.count }
assert_queries_count(1) { assert_equal 1, author.unique_categorized_posts.count(:title) }
assert_queries_count(1) { assert_equal 0, author.unique_categorized_posts.where(title: nil).count(:title) }
assert_not_predicate authors(:mary).unique_categorized_posts, :loaded?
end
@ -732,7 +732,7 @@ def test_has_many_through_include_checks_if_record_exists_if_target_not_loaded
david.reload
assert_not_predicate david.categories, :loaded?
assert_queries(1) do
assert_queries_count(1) do
assert_includes david.categories, category
end
assert_not_predicate david.categories, :loaded?

@ -62,7 +62,7 @@ def test_has_many_through_has_many_with_has_many_through_source_reflection
end
def test_has_many_through_has_many_with_has_many_through_source_reflection_preload
author = assert_queries(5) { Author.includes(:tags).first }
author = assert_queries_count(5) { Author.includes(:tags).first }
general = tags(:general)
assert_no_queries do
@ -77,7 +77,7 @@ def test_has_many_through_has_many_with_has_many_through_source_reflection_prelo
assert_not taggings_reflection.scope
with_automatic_scope_inversing(tag_reflection, taggings_reflection) do
assert_queries(4) { Author.includes(:tags).first }
assert_queries_count(4) { Author.includes(:tags).first }
end
end
@ -102,7 +102,7 @@ def test_has_many_through_has_many_through_with_has_many_source_reflection
def test_has_many_through_has_many_through_with_has_many_source_reflection_preload
luke, david = subscribers(:first), subscribers(:second)
author = assert_queries(4) { Author.includes(:subscribers).first }
author = assert_queries_count(4) { Author.includes(:subscribers).first }
assert_no_queries do
assert_equal [luke, david, david], author.subscribers.sort_by(&:nick)
end
@ -124,7 +124,7 @@ def test_has_many_through_has_one_with_has_one_through_source_reflection
end
def test_has_many_through_has_one_with_has_one_through_source_reflection_preload
member = assert_queries(4) { Member.includes(:nested_member_types).first }
member = assert_queries_count(4) { Member.includes(:nested_member_types).first }
founding = member_types(:founding)
assert_no_queries do
assert_equal [founding], member.nested_member_types
@ -146,7 +146,7 @@ def test_has_many_through_has_one_through_with_has_one_source_reflection
end
def test_has_many_through_has_one_through_with_has_one_source_reflection_preload
member = assert_queries(4) { Member.includes(:nested_sponsors).first }
member = assert_queries_count(4) { Member.includes(:nested_sponsors).first }
mustache = sponsors(:moustache_club_sponsor_for_groucho)
assert_no_queries do
assert_equal [mustache], member.nested_sponsors
@ -172,7 +172,7 @@ def test_has_many_through_has_one_with_has_many_through_source_reflection
def test_has_many_through_has_one_with_has_many_through_source_reflection_preload
ActiveRecord::Base.connection.table_alias_length # preheat cache
member = assert_queries(4) { Member.includes(:organization_member_details).first }
member = assert_queries_count(4) { Member.includes(:organization_member_details).first }
groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy)
assert_no_queries do
@ -201,7 +201,7 @@ def test_has_many_through_has_one_through_with_has_many_source_reflection
end
def test_has_many_through_has_one_through_with_has_many_source_reflection_preload
member = assert_queries(4) { Member.includes(:organization_member_details_2).first }
member = assert_queries_count(4) { Member.includes(:organization_member_details_2).first }
groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy)
# postgresql test if randomly executed then executes "SHOW max_identifier_length". Hence
@ -231,7 +231,7 @@ def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflectio
end
def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection_preload
author = assert_queries(4) { Author.includes(:post_categories).third }
author = assert_queries_count(4) { Author.includes(:post_categories).third }
general, cooking = categories(:general), categories(:cooking)
assert_no_queries do
@ -260,7 +260,7 @@ def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflectio
def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection_preload
Category.includes(:post_comments).to_a # preheat cache
category = assert_queries(4) { Category.includes(:post_comments).second }
category = assert_queries_count(4) { Category.includes(:post_comments).second }
greetings, more = comments(:greetings), comments(:more_greetings)
assert_no_queries do
@ -288,7 +288,7 @@ def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection
end
def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection_preload
author = assert_queries(6) { Author.includes(:category_post_comments).third }
author = assert_queries_count(6) { Author.includes(:category_post_comments).third }
greetings, more = comments(:greetings), comments(:more_greetings)
assert_no_queries do
@ -314,7 +314,7 @@ def test_has_many_through_has_many_through_with_belongs_to_source_reflection
end
def test_has_many_through_has_many_through_with_belongs_to_source_reflection_preload
author = assert_queries(5) { Author.includes(:tagging_tags).first }
author = assert_queries_count(5) { Author.includes(:tagging_tags).first }
general = tags(:general)
assert_no_queries do
@ -329,7 +329,7 @@ def test_has_many_through_has_many_through_with_belongs_to_source_reflection_pre
assert_not taggings_reflection.scope
with_automatic_scope_inversing(tag_reflection, taggings_reflection) do
assert_queries(4) { Author.includes(:tagging_tags).first }
assert_queries_count(4) { Author.includes(:tagging_tags).first }
end
end
@ -351,7 +351,7 @@ def test_has_many_through_belongs_to_with_has_many_through_source_reflection
end
def test_has_many_through_belongs_to_with_has_many_through_source_reflection_preload
categorization = assert_queries(4) { Categorization.includes(:post_taggings).first }
categorization = assert_queries_count(4) { Categorization.includes(:post_taggings).first }
welcome_general, thinking_general = taggings(:welcome_general), taggings(:thinking_general)
assert_no_queries do
@ -374,7 +374,7 @@ def test_has_one_through_has_one_with_has_one_through_source_reflection
end
def test_has_one_through_has_one_with_has_one_through_source_reflection_preload
member = assert_queries(4) { Member.includes(:nested_member_type).first }
member = assert_queries_count(4) { Member.includes(:nested_member_type).first }
founding = member_types(:founding)
assert_no_queries do
@ -408,7 +408,7 @@ def test_joins_and_includes_from_through_models_not_included_in_association
end
def test_has_one_through_has_one_through_with_belongs_to_source_reflection_preload
member = assert_queries(4) { Member.includes(:club_category).first }
member = assert_queries_count(4) { Member.includes(:club_category).first }
general = categories(:general)
assert_no_queries do
@ -539,7 +539,7 @@ def test_nested_has_many_through_with_conditions_on_through_associations
def test_nested_has_many_through_with_conditions_on_through_associations_preload
assert_empty Author.where("tags.id" => 100).joins(:misc_post_first_blue_tags)
author = assert_queries(2) { Author.includes(:misc_post_first_blue_tags).third }
author = assert_queries_count(2) { Author.includes(:misc_post_first_blue_tags).third }
blue = tags(:blue)
assert_no_queries do
@ -560,7 +560,7 @@ def test_nested_has_many_through_with_conditions_on_source_associations
end
def test_nested_has_many_through_with_conditions_on_source_associations_preload
author = assert_queries(2) { Author.includes(:misc_post_first_blue_tags_2).third }
author = assert_queries_count(2) { Author.includes(:misc_post_first_blue_tags_2).third }
blue = tags(:blue)
assert_no_queries do
@ -649,10 +649,10 @@ def test_has_many_through_reset_source_reflection_after_loading_is_complete
def assert_includes_and_joins_equal(query, expected, association)
query = query.order(:id)
actual = assert_queries(1) { query.joins(association).to_a.uniq }
actual = assert_queries_count(1) { query.joins(association).to_a.uniq }
assert_equal expected, actual
actual = assert_queries(1) { query.includes(association).to_a.uniq }
actual = assert_queries_count(1) { query.includes(association).to_a.uniq }
assert_equal expected, actual
end
end

@ -594,7 +594,7 @@ def test_scoped_allows_conditions
human = Human.find(human.id)
assert_queries(1) do
assert_queries_count(1) do
assert_equal human, human.interests.where("1=1").first.human
end
end
@ -788,7 +788,7 @@ def test_preload_with_scope
def test_preload_makes_correct_number_of_queries_on_array
post = posts(:welcome)
assert_queries(1) do
assert_queries_count(1) do
preloader = ActiveRecord::Associations::Preloader.new(records: [post], associations: :comments)
preloader.call
end
@ -798,7 +798,7 @@ def test_preload_makes_correct_number_of_queries_on_relation
post = posts(:welcome)
relation = Post.where(id: post.id)
assert_queries(2) do
assert_queries_count(2) do
preloader = ActiveRecord::Associations::Preloader.new(records: relation, associations: :comments)
preloader.call
end
@ -831,7 +831,7 @@ def test_preload_groups_queries_with_same_scope
book = books(:awdr)
post = posts(:welcome)
assert_queries(1) do
assert_queries_count(1) do
preloader = ActiveRecord::Associations::Preloader.new(records: [book, post], associations: :author)
preloader.call
end
@ -860,7 +860,7 @@ def test_preload_grouped_queries_of_middle_records
comments(:eager_sti_on_associations_s_comment2),
]
assert_queries(2) do
assert_queries_count(2) do
ActiveRecord::Associations::Preloader.new(records: comments, associations: [:author, :ordinary_post]).call
end
end
@ -868,7 +868,7 @@ def test_preload_grouped_queries_of_middle_records
def test_preload_grouped_queries_of_through_records
author = authors(:david)
assert_queries(3) do
assert_queries_count(3) do
ActiveRecord::Associations::Preloader.new(records: [author], associations: [:hello_post_comments, :comments]).call
end
end
@ -879,7 +879,7 @@ def test_preload_through_records_with_already_loaded_middle_record
member.reload.organization # load through record
assert_queries(1) do
assert_queries_count(1) do
ActiveRecord::Associations::Preloader.new(records: [member], associations: :organization_member_details_2).call
end
@ -903,7 +903,7 @@ def test_preload_with_instance_dependent_scope
body: "this post is also about David"
)
assert_queries(2) do
assert_queries_count(2) do
preloader = ActiveRecord::Associations::Preloader.new(records: [david, david2, bob], associations: :posts_mentioning_author)
preloader.call
end
@ -924,7 +924,7 @@ def test_preload_with_instance_dependent_through_scope
comment1 = david.posts.first.comments.create!(body: "Hi David!")
comment2 = david.posts.first.comments.create!(body: "This comment mentions david")
assert_queries(2) do
assert_queries_count(2) do
preloader = ActiveRecord::Associations::Preloader.new(records: [david, david2, bob], associations: :comments_mentioning_author)
preloader.call
end
@ -961,7 +961,7 @@ def test_preload_with_through_instance_dependent_scope
comment2 = post.comments.create!(body: "hello!")
comment3 = post3.comments.create!(body: "HI BOB!")
assert_queries(3) do
assert_queries_count(3) do
preloader = ActiveRecord::Associations::Preloader.new(records: [david, david2, bob], associations: :comments_on_posts_mentioning_author)
preloader.call
end
@ -996,7 +996,7 @@ def test_some_already_loaded_associations
# SELECT "line_item_discount_applications".* FROM "line_item_discount_applications" WHERE "line_item_discount_applications"."line_item_id" = ?
# SELECT "shipping_line_discount_applications".* FROM "shipping_line_discount_applications" WHERE "shipping_line_discount_applications"."shipping_line_id" = ?
# SELECT "discounts".* FROM "discounts" WHERE "discounts"."id" IN (?, ?).
assert_queries(5) do
assert_queries_count(5) do
preloader = ActiveRecord::Associations::Preloader.new(records: [invoice], associations: [
line_items: { discount_applications: :discount },
shipping_lines: { discount_applications: :discount },
@ -1015,7 +1015,7 @@ def test_some_already_loaded_associations
# SELECT "shipping_lines".* FROM shipping_lines WHERE "shipping_lines"."invoice_id" = ?
# SELECT "shipping_line_discount_applications".* FROM "shipping_line_discount_applications" WHERE "shipping_line_discount_applications"."shipping_line_id" = ?
# SELECT "discounts".* FROM "discounts" WHERE "discounts"."id" = ?.
assert_queries(3) do
assert_queries_count(3) do
preloader = ActiveRecord::Associations::Preloader.new(records: [invoice], associations: [
line_items: { discount_applications: :discount },
shipping_lines: { discount_applications: :discount },
@ -1035,7 +1035,7 @@ def test_preload_through
comments(:eager_sti_on_associations_s_comment2),
]
assert_queries(2) do
assert_queries_count(2) do
preloader = ActiveRecord::Associations::Preloader.new(records: comments, associations: [:author, :post])
preloader.call
end
@ -1053,7 +1053,7 @@ def test_preload_groups_queries_with_same_scope_at_second_level
# SELECT FROM posts ... (thinking)
# SELECT FROM posts ... (welcome)
# SELECT FROM comments ... (comments for both welcome and thinking)
assert_queries(4) do
assert_queries_count(4) do
author = Author
.where(name: "David")
.includes(thinking_posts: :comments, welcome_posts: :comments)
@ -1074,7 +1074,7 @@ def test_preload_groups_queries_with_same_sql_at_second_level
# SELECT FROM posts ... (thinking)
# SELECT FROM posts ... (welcome)
# SELECT FROM comments ... (comments for both welcome and thinking)
assert_queries(4) do
assert_queries_count(4) do
author = Author
.where(name: "David")
.includes(thinking_posts: :comments, welcome_posts: :comments_with_extending)
@ -1094,7 +1094,7 @@ def test_preload_with_grouping_sets_inverse_association
AuthorFavorite.create!(author: mary, favorite_author: bob)
favorites = AuthorFavorite.all.load
assert_queries(1) do
assert_queries_count(1) do
preloader = ActiveRecord::Associations::Preloader.new(records: favorites, associations: [:author, :favorite_author])
preloader.call
end
@ -1111,7 +1111,7 @@ def test_preload_can_group_separate_levels
AuthorFavorite.create!(author: mary, favorite_author: bob)
assert_queries(3) do
assert_queries_count(3) do
preloader = ActiveRecord::Associations::Preloader.new(records: [mary], associations: [:posts, favorite_authors: :posts])
preloader.call
end
@ -1130,7 +1130,7 @@ def test_preload_can_group_multi_level_ping_pong_through
associations = { similar_posts: :comments, favorite_authors: { similar_posts: :comments } }
assert_queries(9) do
assert_queries_count(9) do
preloader = ActiveRecord::Associations::Preloader.new(records: [mary], associations: associations)
preloader.call
end
@ -1150,7 +1150,7 @@ def test_preload_can_group_multi_level_ping_pong_through
with_automatic_scope_inversing(tag_reflection, taggings_reflection) do
mary.reload
assert_queries(8) do
assert_queries_count(8) do
preloader = ActiveRecord::Associations::Preloader.new(records: [mary], associations: associations)
preloader.call
end
@ -1165,7 +1165,7 @@ def test_preload_does_not_group_same_class_different_scope
# When the scopes differ in the generated SQL:
# SELECT "authors".* FROM "authors" WHERE (name LIKE '%a%') AND "authors"."id" = ?
# SELECT "authors".* FROM "authors" WHERE "authors"."id" = ?.
assert_queries(2) do
assert_queries_count(2) do
preloader = ActiveRecord::Associations::Preloader.new(records: [post, postesque], associations: :author_with_the_letter_a)
preloader.call
end
@ -1179,7 +1179,7 @@ def test_preload_does_not_group_same_class_different_scope
postesque.reload
# When the generated SQL is identical, but one scope has preload values.
assert_queries(3) do
assert_queries_count(3) do
preloader = ActiveRecord::Associations::Preloader.new(records: [post, postesque], associations: :author_with_address)
preloader.call
end
@ -1195,7 +1195,7 @@ def test_preload_does_not_group_same_scope_different_key_name
postesque = Postesque.create(author: Author.last)
postesque.reload
assert_queries(2) do
assert_queries_count(2) do
preloader = ActiveRecord::Associations::Preloader.new(records: [post, postesque], associations: :author)
preloader.call
end
@ -1241,7 +1241,7 @@ def test_preload_with_only_some_records_available
bob = authors(:bob)
mary = authors(:mary)
assert_queries(1) do
assert_queries_count(1) do
ActiveRecord::Associations::Preloader.new(records: [bob_post, mary_post], associations: :author, available_records: [bob]).call
end
@ -1260,7 +1260,7 @@ def test_preload_with_some_records_already_loaded
assert_predicate bob_post.association(:author), :loaded?
assert_not mary_post.association(:author).loaded?
assert_queries(1) do
assert_queries_count(1) do
ActiveRecord::Associations::Preloader.new(records: [bob_post, mary_post], associations: :author).call
end
@ -1274,7 +1274,7 @@ def test_preload_with_available_records_with_through_association
author = authors(:david)
categories = Category.all.to_a
assert_queries(1) do
assert_queries_count(1) do
# One query to get the middle records (i.e. essays)
ActiveRecord::Associations::Preloader.new(records: [author], associations: :essay_category, available_records: categories).call
end
@ -1292,7 +1292,7 @@ def test_preload_with_only_some_records_available_with_through_associations
dave = authors(:david)
dave_category = categories(:general)
assert_queries(2) do
assert_queries_count(2) do
ActiveRecord::Associations::Preloader.new(records: [mary, dave], associations: :essay_category, available_records: [mary_category]).call
end
@ -1321,7 +1321,7 @@ def test_preload_with_available_records_queries_when_scoped
post = posts(:welcome)
david = authors(:david)
assert_queries(1) do
assert_queries_count(1) do
ActiveRecord::Associations::Preloader.new(records: [post], associations: :author, scope: Author.where(name: "David"), available_records: [david]).call
end
@ -1333,7 +1333,7 @@ def test_preload_with_available_records_queries_when_collection
post = posts(:welcome)
comments = Comment.all.to_a
assert_queries(1) do
assert_queries_count(1) do
ActiveRecord::Associations::Preloader.new(records: [post], associations: :comments, available_records: comments).call
end
@ -1346,7 +1346,7 @@ def test_preload_with_available_records_queries_when_incomplete
bob = authors(:bob)
david = authors(:david)
assert_queries(1) do
assert_queries_count(1) do
ActiveRecord::Associations::Preloader.new(records: [post], associations: :author, available_records: [bob]).call
end
@ -1496,7 +1496,7 @@ def test_preload_keeps_built_has_many_records_after_query
post = posts(:welcome)
comment = post.comments.build
assert_queries(1) do
assert_queries_count(1) do
ActiveRecord::Associations::Preloader.new(records: [post], associations: :comments).call
assert_includes post.comments.to_a, comment
@ -1570,7 +1570,7 @@ def test_belongs_to_with_annotation_includes_a_query_comment
assert_not_predicate log, :empty?
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
assert_sql(%r{/\* that tells jokes \*/}) do
assert_queries_match(%r{/\* that tells jokes \*/}) do
pirate.parrot_with_annotation
end
end
@ -1585,7 +1585,7 @@ def test_has_and_belongs_to_many_with_annotation_includes_a_query_comment
assert_not_predicate log, :empty?
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
assert_sql(%r{/\* that are very colorful \*/}) do
assert_queries_match(%r{/\* that are very colorful \*/}) do
pirate.parrots_with_annotation.first
end
end
@ -1600,7 +1600,7 @@ def test_has_one_with_annotation_includes_a_query_comment
assert_not_predicate log, :empty?
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
assert_sql(%r{/\* that is a rocket \*/}) do
assert_queries_match(%r{/\* that is a rocket \*/}) do
pirate.ship_with_annotation
end
end
@ -1615,7 +1615,7 @@ def test_has_many_with_annotation_includes_a_query_comment
assert_not_predicate log, :empty?
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
assert_sql(%r{/\* that are also parrots \*/}) do
assert_queries_match(%r{/\* that are also parrots \*/}) do
pirate.birds_with_annotation.first
end
end
@ -1630,7 +1630,7 @@ def test_has_many_through_with_annotation_includes_a_query_comment
assert_not_predicate log, :empty?
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
assert_sql(%r{/\* yarrr \*/}) do
assert_queries_match(%r{/\* yarrr \*/}) do
pirate.treasure_estimates_with_annotation.first
end
end
@ -1645,7 +1645,7 @@ def test_has_many_through_with_annotation_includes_a_query_comment_when_eager_lo
assert_not_predicate log, :empty?
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
assert_sql(%r{/\* yarrr \*/}) do
assert_queries_match(%r{/\* yarrr \*/}) do
SpacePirate.includes(:treasure_estimates_with_annotation, :treasures).first
end
end

@ -269,19 +269,19 @@ def test_assignment_before_either_saved
def test_not_resaved_when_unchanged
firm = Firm.all.merge!(includes: :account).first
firm.name += "-changed"
assert_queries(1) { firm.save! }
assert_queries_count(3) { firm.save! }
firm = Firm.first
firm.account = Account.first
assert_queries(Firm.partial_updates? ? 0 : 1) { firm.save! }
assert_queries_count(Firm.partial_updates? ? 0 : 1) { firm.save! }
firm = Firm.first.dup
firm.account = Account.first
assert_queries(2) { firm.save! }
assert_queries_count(4) { firm.save! }
firm = Firm.first.dup
firm.account = Account.first.dup
assert_queries(2) { firm.save! }
assert_queries_count(4) { firm.save! }
end
def test_callbacks_firing_order_on_create
@ -916,11 +916,11 @@ def test_assign_ids_for_through_a_belongs_to
def test_build_before_save
company = companies(:first_firm)
new_client = assert_queries(0) { company.clients_of_firm.build("name" => "Another Client") }
new_client = assert_queries_count(0) { company.clients_of_firm.build("name" => "Another Client") }
assert_not_predicate company.clients_of_firm, :loaded?
company.name += "-changed"
assert_queries(2) { assert company.save }
assert_queries_count(4) { assert company.save }
assert_predicate new_client, :persisted?
assert_equal 3, company.clients_of_firm.reload.size
end
@ -928,21 +928,21 @@ def test_build_before_save
def test_build_many_before_save
company = companies(:first_firm)
assert_queries(0) { company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) }
assert_queries_count(0) { company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) }
company.name += "-changed"
assert_queries(3) { assert company.save }
assert_queries_count(5) { assert company.save }
assert_equal 4, company.clients_of_firm.reload.size
end
def test_build_via_block_before_save
company = companies(:first_firm)
new_client = assert_queries(0) { company.clients_of_firm.build { |client| client.name = "Another Client" } }
new_client = assert_queries_count(0) { company.clients_of_firm.build { |client| client.name = "Another Client" } }
assert_not_predicate company.clients_of_firm, :loaded?
company.name += "-changed"
assert_queries(2) { assert company.save }
assert_queries_count(4) { assert company.save }
assert_predicate new_client, :persisted?
assert_equal 3, company.clients_of_firm.reload.size
end
@ -950,14 +950,14 @@ def test_build_via_block_before_save
def test_build_many_via_block_before_save
company = companies(:first_firm)
assert_queries(0) do
assert_queries_count(0) do
company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) do |client|
client.name = "changed"
end
end
company.name += "-changed"
assert_queries(3) { assert company.save }
assert_queries_count(5) { assert company.save }
assert_equal 4, company.clients_of_firm.reload.size
end
@ -1494,7 +1494,7 @@ def test_changed_for_autosave_should_handle_cycles
@parrot = @pirate.parrots.create(name: "some_name")
@parrot.name = "changed_name"
assert_queries(1) { @ship.save! }
assert_queries_count(3) { @ship.save! }
assert_no_queries { @ship.save! }
end
@ -1598,7 +1598,7 @@ def save(**)
end
def test_should_not_load_the_associated_model
assert_queries(1) { @pirate.catchphrase = "Arr"; @pirate.save! }
assert_queries_count(3) { @pirate.catchphrase = "Arr"; @pirate.save! }
end
def test_mark_for_destruction_is_ignored_without_autosave_true
@ -1770,7 +1770,7 @@ def save(**)
end
def test_should_not_load_the_associated_model
assert_queries(1) { @ship.name = "The Vile Serpent"; @ship.save! }
assert_queries_count(3) { @ship.name = "The Vile Serpent"; @ship.save! }
end
def test_should_save_with_non_nullable_foreign_keys
@ -1938,11 +1938,11 @@ def test_should_still_raise_an_ActiveRecordRecord_Invalid_exception_if_we_want_t
end
def test_should_not_load_the_associated_models_if_they_were_not_loaded_yet
assert_queries(1) { @pirate.catchphrase = "Arr"; @pirate.save! }
assert_queries_count(3) { @pirate.catchphrase = "Arr"; @pirate.save! }
@pirate.public_send(@association_name).load_target
assert_queries(3) do
assert_queries_count(5) do
@pirate.catchphrase = "Yarr"
new_names = ["Grace OMalley", "Privateers Greed"]
@pirate.public_send(@association_name).each_with_index { |child, i| child.name = new_names[i] }

@ -51,13 +51,13 @@ class BasePreventWritesTest < ActiveRecord::TestCase
Bird.create!(name: "Bluejay")
ActiveRecord::Base.while_preventing_writes do
assert_queries(2) { Bird.where(name: "Bluejay").explain }
assert_queries_count(2) { Bird.where(name: "Bluejay").explain }
end
end
test "an empty transaction does not raise if preventing writes" do
ActiveRecord::Base.while_preventing_writes do
assert_queries(2, ignore_none: true) do
assert_queries_count(2, include_schema: true) do
Bird.transaction do
ActiveRecord::Base.connection.materialize_transactions
end

@ -1450,10 +1450,10 @@ def test_find_on_abstract_base_class_doesnt_use_type_condition
end
end
def test_assert_queries
def test_assert_queries_count
query = lambda { ActiveRecord::Base.connection.execute "select count(*) from developers" }
assert_queries(2) { 2.times { query.call } }
assert_queries 1, &query
assert_queries_count(2) { 2.times { query.call } }
assert_queries_count 1, &query
assert_no_queries { assert true }
end

@ -16,7 +16,7 @@ def setup
end
def test_each_should_execute_one_query_per_batch
assert_queries(@total + 1) do
assert_queries_count(@total + 1) do
Post.find_each(batch_size: 1) do |post|
assert_kind_of Post, post
end
@ -24,14 +24,14 @@ def test_each_should_execute_one_query_per_batch
end
def test_each_should_not_return_query_chain_and_execute_only_one_query
assert_queries(1) do
assert_queries_count(1) do
result = Post.find_each(batch_size: 100000) { }
assert_nil result
end
end
def test_each_should_return_an_enumerator_if_no_block_is_present
assert_queries(1) do
assert_queries_count(1) do
Post.find_each(batch_size: 100000).with_index do |post, index|
assert_kind_of Post, post
assert_kind_of Integer, index
@ -46,7 +46,7 @@ def test_each_should_return_a_sized_enumerator
end
def test_each_enumerator_should_execute_one_query_per_batch
assert_queries(@total + 1) do
assert_queries_count(@total + 1) do
Post.find_each(batch_size: 1).with_index do |post, index|
assert_kind_of Post, post
assert_kind_of Integer, index
@ -63,7 +63,7 @@ def test_each_should_raise_if_select_is_set_without_id
end
def test_each_should_execute_if_id_is_in_select
assert_queries(6) do
assert_queries_count(6) do
Post.select("id, title, type").find_each(batch_size: 2) do |post|
assert_kind_of Post, post
end
@ -114,7 +114,7 @@ def test_logger_not_required
end
def test_find_in_batches_should_return_batches
assert_queries(@total + 1) do
assert_queries_count(@total + 1) do
Post.find_in_batches(batch_size: 1) do |batch|
assert_kind_of Array, batch
assert_kind_of Post, batch.first
@ -123,7 +123,7 @@ def test_find_in_batches_should_return_batches
end
def test_find_in_batches_should_start_from_the_start_option
assert_queries(@total) do
assert_queries_count(@total) do
Post.find_in_batches(batch_size: 1, start: 2) do |batch|
assert_kind_of Array, batch
assert_kind_of Post, batch.first
@ -132,7 +132,7 @@ def test_find_in_batches_should_start_from_the_start_option
end
def test_find_in_batches_should_end_at_the_finish_option
assert_queries(6) do
assert_queries_count(6) do
Post.find_in_batches(batch_size: 1, finish: 5) do |batch|
assert_kind_of Array, batch
assert_kind_of Post, batch.first
@ -141,18 +141,18 @@ def test_find_in_batches_should_end_at_the_finish_option
end
def test_find_in_batches_shouldnt_execute_query_unless_needed
assert_queries(2) do
assert_queries_count(2) do
Post.find_in_batches(batch_size: @total) { |batch| assert_kind_of Array, batch }
end
assert_queries(1) do
assert_queries_count(1) do
Post.find_in_batches(batch_size: @total + 1) { |batch| assert_kind_of Array, batch }
end
end
def test_find_in_batches_should_quote_batch_order
c = Post.connection
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("posts.id"))}/i) do
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("posts.id"))}/i) do
Post.find_in_batches(batch_size: 1) do |batch|
assert_kind_of Array, batch
assert_kind_of Post, batch.first
@ -162,7 +162,7 @@ def test_find_in_batches_should_quote_batch_order
def test_find_in_batches_should_quote_batch_order_with_desc_order
c = Post.connection
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("posts.id"))} DESC/) do
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("posts.id"))} DESC/) do
Post.find_in_batches(batch_size: 1, order: :desc) do |batch|
assert_kind_of Array, batch
assert_kind_of Post, batch.first
@ -269,7 +269,7 @@ def test_find_in_batches_should_use_any_column_as_primary_key
end
def test_find_in_batches_should_use_any_column_as_primary_key_when_start_is_not_specified
assert_queries(Subscriber.count + 1) do
assert_queries_count(Subscriber.count + 1) do
Subscriber.find_in_batches(batch_size: 1) do |batch|
assert_kind_of Array, batch
assert_kind_of Subscriber, batch.first
@ -282,7 +282,7 @@ def test_find_in_batches_should_return_an_enumerator
assert_no_queries do
enum = Post.find_in_batches(batch_size: 1)
end
assert_queries(4) do
assert_queries_count(4) do
enum.first(4) do |batch|
assert_kind_of Array, batch
assert_kind_of Post, batch.first
@ -327,7 +327,7 @@ def test_in_batches_has_attribute_readers
end
def test_in_batches_should_yield_relation_if_block_given
assert_queries(6) do
assert_queries_count(6) do
Post.in_batches(of: 2) do |relation|
assert_kind_of ActiveRecord::Relation, relation
end
@ -335,7 +335,7 @@ def test_in_batches_should_yield_relation_if_block_given
end
def test_in_batches_should_be_enumerable_if_no_block_given
assert_queries(6) do
assert_queries_count(6) do
Post.in_batches(of: 2).each do |relation|
assert_kind_of ActiveRecord::Relation, relation
end
@ -343,7 +343,7 @@ def test_in_batches_should_be_enumerable_if_no_block_given
end
def test_in_batches_each_record_should_yield_record_if_block_is_given
assert_queries(6) do
assert_queries_count(6) do
Post.in_batches(of: 2).each_record do |post|
assert_predicate post.title, :present?
assert_kind_of Post, post
@ -352,7 +352,7 @@ def test_in_batches_each_record_should_yield_record_if_block_is_given
end
def test_in_batches_each_record_should_return_enumerator_if_no_block_given
assert_queries(6) do
assert_queries_count(6) do
Post.in_batches(of: 2).each_record.with_index do |post, i|
assert_predicate post.title, :present?
assert_kind_of Post, post
@ -362,7 +362,7 @@ def test_in_batches_each_record_should_return_enumerator_if_no_block_given
def test_in_batches_each_record_should_be_ordered_by_id
ids = Post.order("id ASC").pluck(:id)
assert_queries(6) do
assert_queries_count(6) do
Post.in_batches(of: 2).each_record.with_index do |post, i|
assert_equal ids[i], post.id
end
@ -370,7 +370,7 @@ def test_in_batches_each_record_should_be_ordered_by_id
end
def test_in_batches_update_all_affect_all_records
assert_queries(6 + 6) do # 6 selects, 6 updates
assert_queries_count(6 + 6) do # 6 selects, 6 updates
Post.in_batches(of: 2).update_all(title: "updated-title")
end
assert_equal Post.all.pluck(:title), ["updated-title"] * Post.count
@ -416,7 +416,7 @@ def test_in_batches_should_be_loaded
end
def test_in_batches_if_not_loaded_executes_more_queries
assert_queries(@total + 1) do
assert_queries_count(@total + 1) do
Post.in_batches(of: 1, load: false) do |relation|
assert_not_predicate relation, :loaded?
end
@ -428,7 +428,7 @@ def test_in_batches_when_loaded_runs_no_queries
posts.load
batch_count = 0
last_id = posts.map(&:id).min
assert_queries(0) do
assert_queries_count(0) do
posts.in_batches(of: 1) do |relation|
batch_count += 1
assert_kind_of ActiveRecord::Relation, relation
@ -445,7 +445,7 @@ def test_in_batches_when_loaded_runs_no_queries_with_order_argument
posts.load
batch_count = 0
last_id = posts.map(&:id).max
assert_queries(0) do
assert_queries_count(0) do
posts.in_batches(of: 1, order: :desc) do |relation|
batch_count += 1
assert_kind_of ActiveRecord::Relation, relation
@ -464,7 +464,7 @@ def test_in_batches_when_loaded_runs_no_queries_with_start_and_end_arguments
start_id = posts.map(&:id)[1]
finish_id = posts.map(&:id)[-2]
assert_queries(0) do
assert_queries_count(0) do
posts.in_batches(of: 1, start: start_id, finish: finish_id) do |relation|
batch_count += 1
assert_kind_of ActiveRecord::Relation, relation
@ -479,7 +479,7 @@ def test_in_batches_when_loaded_can_return_an_enum
posts.load
batch_count = 0
assert_queries(0) do
assert_queries_count(0) do
posts.in_batches(of: 1).each do |relation|
batch_count += 1
assert_kind_of ActiveRecord::Relation, relation
@ -490,7 +490,7 @@ def test_in_batches_when_loaded_can_return_an_enum
end
def test_in_batches_should_return_relations
assert_queries(@total + 1) do
assert_queries_count(@total + 1) do
Post.in_batches(of: 1) do |relation|
assert_kind_of ActiveRecord::Relation, relation
end
@ -499,7 +499,7 @@ def test_in_batches_should_return_relations
def test_in_batches_should_start_from_the_start_option
post = Post.order("id ASC").where("id >= ?", 2).first
assert_queries(2) do
assert_queries_count(2) do
relation = Post.in_batches(of: 1, start: 2).first
assert_equal post, relation.first
end
@ -507,7 +507,7 @@ def test_in_batches_should_start_from_the_start_option
def test_in_batches_should_end_at_the_finish_option
post = Post.order("id DESC").where("id <= ?", 5).first
assert_queries(7) do
assert_queries_count(7) do
relation = Post.in_batches(of: 1, finish: 5, load: true).reverse_each.first
assert_equal post, relation.last
end
@ -516,7 +516,7 @@ def test_in_batches_should_end_at_the_finish_option
def test_in_batches_executes_range_queries_when_unconstrained
c = Post.connection
quoted_posts_id = Regexp.escape(c.quote_table_name("posts.id"))
assert_sql(/WHERE #{quoted_posts_id} > .+ AND #{quoted_posts_id} <= .+/i) do
assert_queries_match(/WHERE #{quoted_posts_id} > .+ AND #{quoted_posts_id} <= .+/i) do
Post.in_batches(of: 2) { |relation| assert_kind_of Post, relation.first }
end
end
@ -524,7 +524,7 @@ def test_in_batches_executes_range_queries_when_unconstrained
def test_in_batches_executes_in_queries_when_unconstrained_and_opted_out_of_ranges
c = Post.connection
quoted_posts_id = Regexp.escape(c.quote_table_name("posts.id"))
assert_sql(/#{quoted_posts_id} IN \(.+\)/i) do
assert_queries_match(/#{quoted_posts_id} IN \(.+\)/i) do
Post.in_batches(of: 2, use_ranges: false) { |relation| assert_kind_of Post, relation.first }
end
end
@ -532,7 +532,7 @@ def test_in_batches_executes_in_queries_when_unconstrained_and_opted_out_of_rang
def test_in_batches_executes_in_queries_when_constrained
c = Post.connection
quoted_posts_id = Regexp.escape(c.quote_table_name("posts.id"))
assert_sql(/#{quoted_posts_id} IN \(.+\)/i) do
assert_queries_match(/#{quoted_posts_id} IN \(.+\)/i) do
Post.where("id < ?", 5).in_batches(of: 2) { |relation| assert_kind_of Post, relation.first }
end
end
@ -540,7 +540,7 @@ def test_in_batches_executes_in_queries_when_constrained
def test_in_batches_executes_range_queries_when_constrained_and_opted_in_into_ranges
c = Post.connection
quoted_posts_id = Regexp.escape(c.quote_table_name("posts.id"))
assert_sql(/#{quoted_posts_id} > .+ AND #{quoted_posts_id} <= .+/i) do
assert_queries_match(/#{quoted_posts_id} > .+ AND #{quoted_posts_id} <= .+/i) do
Post.where("id < ?", 5).in_batches(of: 2, use_ranges: true) { |relation| assert_kind_of Post, relation.first }
end
end
@ -548,24 +548,24 @@ def test_in_batches_executes_range_queries_when_constrained_and_opted_in_into_ra
def test_in_batches_no_subqueries_for_whole_tables_batching
c = Post.connection
quoted_posts_id = Regexp.escape(c.quote_table_name("posts.id"))
assert_sql(/DELETE FROM #{Regexp.escape(c.quote_table_name("posts"))} WHERE #{quoted_posts_id} > .+ AND #{quoted_posts_id} <=/i) do
assert_queries_match(/DELETE FROM #{Regexp.escape(c.quote_table_name("posts"))} WHERE #{quoted_posts_id} > .+ AND #{quoted_posts_id} <=/i) do
Post.in_batches(of: 2).delete_all
end
end
def test_in_batches_shouldnt_execute_query_unless_needed
assert_queries(2) do
assert_queries_count(2) do
Post.in_batches(of: @total) { |relation| assert_kind_of ActiveRecord::Relation, relation }
end
assert_queries(1) do
assert_queries_count(1) do
Post.in_batches(of: @total + 1) { |relation| assert_kind_of ActiveRecord::Relation, relation }
end
end
def test_in_batches_should_quote_batch_order
c = Post.connection
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name('posts'))}\.#{Regexp.escape(c.quote_column_name('id'))}/) do
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name('posts'))}\.#{Regexp.escape(c.quote_column_name('id'))}/) do
Post.in_batches(of: 1) do |relation|
assert_kind_of ActiveRecord::Relation, relation
assert_kind_of Post, relation.first
@ -575,7 +575,7 @@ def test_in_batches_should_quote_batch_order
def test_in_batches_should_quote_batch_order_with_desc_order
c = Post.connection
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("posts.id"))} DESC/) do
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("posts.id"))} DESC/) do
Post.in_batches(of: 1, order: :desc) do |relation|
assert_kind_of ActiveRecord::Relation, relation
assert_kind_of Post, relation.first
@ -585,7 +585,7 @@ def test_in_batches_should_quote_batch_order_with_desc_order
def test_in_batches_enumerator_should_quote_batch_order_with_desc_order
c = Post.connection
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("posts.id"))} DESC/) do
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("posts.id"))} DESC/) do
relation = Post.in_batches(of: 1, order: :desc).first
assert_kind_of ActiveRecord::Relation, relation
assert_kind_of Post, relation.first
@ -594,7 +594,7 @@ def test_in_batches_enumerator_should_quote_batch_order_with_desc_order
def test_in_batches_enumerator_each_record_should_quote_batch_order_with_desc_order
c = Post.connection
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("posts.id"))} DESC/) do
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("posts.id"))} DESC/) do
Post.in_batches(of: 1, order: :desc).each_record do |record|
assert_kind_of Post, record
end
@ -639,7 +639,7 @@ def test_in_batches_should_use_any_column_as_primary_key
end
def test_in_batches_should_use_any_column_as_primary_key_when_start_is_not_specified
assert_queries(Subscriber.count + 1) do
assert_queries_count(Subscriber.count + 1) do
Subscriber.in_batches(of: 1, load: true) do |relation|
assert_kind_of ActiveRecord::Relation, relation
assert_kind_of Subscriber, relation.first
@ -652,7 +652,7 @@ def test_in_batches_should_return_an_enumerator
assert_no_queries do
enum = Post.in_batches(of: 1)
end
assert_queries(4) do
assert_queries_count(4) do
enum.first(4) do |relation|
assert_kind_of ActiveRecord::Relation, relation
assert_kind_of Post, relation.first
@ -763,7 +763,7 @@ def test_find_in_batches_should_return_a_sized_enumerator
end
test ".find_each respects table alias" do
assert_queries(1) do
assert_queries_count(1) do
table_alias = Post.arel_table.alias("omg_posts")
table_metadata = ActiveRecord::TableMetadata.new(Post, table_alias)
predicate_builder = ActiveRecord::PredicateBuilder.new(table_metadata)
@ -779,7 +779,7 @@ def test_find_in_batches_should_return_a_sized_enumerator
test ".find_each bypasses the query cache for its own queries" do
Post.cache do
assert_queries(2) do
assert_queries_count(2) do
Post.find_each { }
Post.find_each { }
end
@ -789,7 +789,7 @@ def test_find_in_batches_should_return_a_sized_enumerator
test ".find_each does not disable the query cache inside the given block" do
Post.cache do
Post.find_each(start: 1, finish: 1) do |post|
assert_queries(1) do
assert_queries_count(1) do
post.comments.count
post.comments.count
end
@ -799,7 +799,7 @@ def test_find_in_batches_should_return_a_sized_enumerator
test ".find_in_batches bypasses the query cache for its own queries" do
Post.cache do
assert_queries(2) do
assert_queries_count(2) do
Post.find_in_batches { }
Post.find_in_batches { }
end
@ -809,7 +809,7 @@ def test_find_in_batches_should_return_a_sized_enumerator
test ".find_in_batches does not disable the query cache inside the given block" do
Post.cache do
Post.find_in_batches(start: 1, finish: 1) do |batch|
assert_queries(1) do
assert_queries_count(1) do
batch.first.comments.count
batch.first.comments.count
end
@ -819,7 +819,7 @@ def test_find_in_batches_should_return_a_sized_enumerator
test ".in_batches bypasses the query cache for its own queries" do
Post.cache do
assert_queries(2) do
assert_queries_count(2) do
Post.in_batches { }
Post.in_batches { }
end
@ -829,7 +829,7 @@ def test_find_in_batches_should_return_a_sized_enumerator
test ".in_batches does not disable the query cache inside the given block" do
Post.cache do
Post.in_batches(start: 1, finish: 1) do |relation|
assert_queries(1) do
assert_queries_count(1) do
relation.count
relation.count
end

@ -214,7 +214,7 @@ def assert_bind_params_to_sql
authors = Author.where(id: [1, 2, 3, nil])
assert_equal sql, @connection.to_sql(authors.arel)
assert_sql(sql) { assert_equal 3, authors.length }
assert_queries_match(sql) { assert_equal 3, authors.length }
# prepared_statements: true
#
@ -228,7 +228,7 @@ def assert_bind_params_to_sql
authors = Author.where(id: [1, 2, 3, 9223372036854775808])
assert_equal sql, @connection.to_sql(authors.arel)
assert_sql(sql) { assert_equal 3, authors.length }
assert_queries_match(sql) { assert_equal 3, authors.length }
# prepared_statements: true
#
@ -242,7 +242,7 @@ def assert_bind_params_to_sql
arel_node = Arel.sql("SELECT #{table}.* FROM #{table} WHERE #{pk} IN (?)", [1, 2, 3])
assert_equal sql, @connection.to_sql(arel_node)
assert_sql(sql) { assert_equal 3, @connection.select_all(arel_node).length }
assert_queries_match(sql) { assert_equal 3, @connection.select_all(arel_node).length }
end
def bind_params(ids)

@ -227,7 +227,7 @@ def test_should_calculate_against_given_relation
end
def test_should_not_use_alias_for_grouped_field
assert_sql(/GROUP BY #{Regexp.escape(Account.connection.quote_table_name("accounts.firm_id"))}/i) do
assert_queries_match(/GROUP BY #{Regexp.escape(Account.connection.quote_table_name("accounts.firm_id"))}/i) do
c = Account.group(:firm_id).order("accounts_firm_id").sum(:credit_limit)
assert_equal [1, 2, 6, 9], c.keys.compact
end
@ -330,26 +330,26 @@ def test_apply_distinct_in_count
def test_count_with_eager_loading_and_custom_order
posts = Post.includes(:comments).order("comments.id")
assert_queries(1) { assert_equal 11, posts.count }
assert_queries(1) { assert_equal 11, posts.count(:all) }
assert_queries_count(1) { assert_equal 11, posts.count }
assert_queries_count(1) { assert_equal 11, posts.count(:all) }
end
def test_count_with_eager_loading_and_custom_select_and_order
posts = Post.includes(:comments).order("comments.id").select(:type)
assert_queries(1) { assert_equal 11, posts.count }
assert_queries(1) { assert_equal 11, posts.count(:all) }
assert_queries_count(1) { assert_equal 11, posts.count }
assert_queries_count(1) { assert_equal 11, posts.count(:all) }
end
def test_count_with_eager_loading_and_custom_order_and_distinct
posts = Post.includes(:comments).order("comments.id").distinct
assert_queries(1) { assert_equal 11, posts.count }
assert_queries(1) { assert_equal 11, posts.count(:all) }
assert_queries_count(1) { assert_equal 11, posts.count }
assert_queries_count(1) { assert_equal 11, posts.count(:all) }
end
def test_distinct_count_all_with_custom_select_and_order
accounts = Account.distinct.select("credit_limit % 10").order(Arel.sql("credit_limit % 10"))
assert_queries(1) { assert_equal 3, accounts.count(:all) }
assert_queries(1) { assert_equal 3, accounts.load.size }
assert_queries_count(1) { assert_equal 3, accounts.count(:all) }
assert_queries_count(1) { assert_equal 3, accounts.load.size }
end
def test_distinct_count_with_order_and_limit
@ -752,31 +752,31 @@ def test_maximum_with_from_option
end
def test_no_queries_for_empty_relation_on_count
assert_queries(0) do
assert_queries_count(0) do
assert_equal 0, Post.where(id: []).count
end
end
def test_no_queries_for_empty_relation_on_sum
assert_queries(0) do
assert_queries_count(0) do
assert_equal 0, Post.where(id: []).sum(:tags_count)
end
end
def test_no_queries_for_empty_relation_on_average
assert_queries(0) do
assert_queries_count(0) do
assert_nil Post.where(id: []).average(:tags_count)
end
end
def test_no_queries_for_empty_relation_on_minimum
assert_queries(0) do
assert_queries_count(0) do
assert_nil Account.where(id: []).minimum(:id)
end
end
def test_no_queries_for_empty_relation_on_maximum
assert_queries(0) do
assert_queries_count(0) do
assert_nil Account.where(id: []).maximum(:id)
end
end
@ -833,7 +833,7 @@ def test_async_pluck_none_relation
end
def test_pluck_with_empty_in
assert_queries(0) do
assert_queries_count(0) do
assert_equal [], Topic.where(id: []).pluck(:id)
end
assert_async_equal [], Topic.where(id: []).async_pluck(:id)
@ -897,7 +897,7 @@ def assert_pluck_type_cast_without_table_name_qualified_column(author_addresses)
def test_pluck_with_type_cast_does_not_corrupt_the_query_cache
topic = topics(:first)
relation = Topic.where(id: topic.id)
assert_queries 1 do
assert_queries_count 1 do
Topic.cache do
kind = relation.select(:written_on).load.first.read_attribute_before_type_cast(:written_on).class
relation.pluck(:written_on)
@ -993,7 +993,7 @@ def test_ids_on_relation
def test_ids_on_loaded_relation
loaded_companies = Company.all.load
company_ids = Company.all.map(&:id)
assert_queries(0) do
assert_queries_count(0) do
assert_equal company_ids.sort, loaded_companies.ids.sort
end
end
@ -1002,7 +1002,7 @@ def test_ids_on_loaded_relation_with_scope
scoped_ids = [1, 2]
loaded_companies = Company.where(id: scoped_ids).load
company_ids = Company.where(id: scoped_ids).map(&:id)
assert_queries(0) do
assert_queries_count(0) do
assert_equal company_ids.sort, loaded_companies.ids.sort
end
end
@ -1016,7 +1016,7 @@ def test_ids_with_contradicting_scope
empty_scope_ids = []
company_ids = Company.where(id: empty_scope_ids).map(&:id)
assert_predicate company_ids, :empty?
assert_queries(0) do
assert_queries_count(0) do
assert_equal company_ids, Company.where(id: empty_scope_ids).ids
end
end
@ -1076,7 +1076,7 @@ def test_ids_on_loaded_relation_with_includes_and_table_scope
company = Company.first
company.contracts.create!
loaded_companies = Company.includes(:contracts).where("contracts.id" => company.contracts.first).load
assert_queries(0) do
assert_queries_count(0) do
assert_equal [company.id], loaded_companies.ids
end
end
@ -1248,7 +1248,7 @@ def test_pluck_joined_with_polymorphic_relation
def test_pluck_loaded_relation
companies = Company.order(:id).limit(3).load
assert_queries(0) do
assert_queries_count(0) do
assert_equal ["37signals", "Summit", "Microsoft"], companies.pluck(:name)
end
end
@ -1256,7 +1256,7 @@ def test_pluck_loaded_relation
def test_pluck_loaded_relation_multiple_columns
companies = Company.order(:id).limit(3).load
assert_queries(0) do
assert_queries_count(0) do
assert_equal [[1, "37signals"], [2, "Summit"], [3, "Microsoft"]], companies.pluck(:id, :name)
end
end
@ -1264,7 +1264,7 @@ def test_pluck_loaded_relation_multiple_columns
def test_pluck_loaded_relation_sql_fragment
companies = Company.order(:name).limit(3).load
assert_queries(1) do
assert_queries_count(1) do
assert_equal ["37signals", "Apex", "Ex Nihilo"], companies.pluck(Arel.sql("DISTINCT name"))
end
end
@ -1272,7 +1272,7 @@ def test_pluck_loaded_relation_sql_fragment
def test_pluck_loaded_relation_aliased_attribute
companies = Company.order(:id).limit(3).load
assert_queries(0) do
assert_queries_count(0) do
assert_equal ["37signals", "Summit", "Microsoft"], companies.pluck(:new_name)
end
end
@ -1321,7 +1321,7 @@ def test_pick_loaded_relation_multiple_columns
def test_pick_loaded_relation_sql_fragment
companies = Company.order(:name).limit(3).load
assert_queries 1 do
assert_queries_count 1 do
assert_equal "37signals", companies.pick(Arel.sql("DISTINCT name"))
end
end
@ -1585,12 +1585,12 @@ def test_count_with_block_and_column_name_raises_an_error
test "#skip_query_cache! for #pluck" do
Account.cache do
assert_queries(1) do
assert_queries_count(1) do
Account.pluck(:credit_limit)
Account.pluck(:credit_limit)
end
assert_queries(2) do
assert_queries_count(2) do
Account.all.skip_query_cache!.pluck(:credit_limit)
Account.all.skip_query_cache!.pluck(:credit_limit)
end
@ -1599,12 +1599,12 @@ def test_count_with_block_and_column_name_raises_an_error
test "#skip_query_cache! for #ids" do
Account.cache do
assert_queries(1) do
assert_queries_count(1) do
Account.ids
Account.ids
end
assert_queries(2) do
assert_queries_count(2) do
Account.all.skip_query_cache!.ids
Account.all.skip_query_cache!.ids
end
@ -1613,12 +1613,12 @@ def test_count_with_block_and_column_name_raises_an_error
test "#skip_query_cache! for a simple calculation" do
Account.cache do
assert_queries(1) do
assert_queries_count(1) do
Account.calculate(:sum, :credit_limit)
Account.calculate(:sum, :credit_limit)
end
assert_queries(2) do
assert_queries_count(2) do
Account.all.skip_query_cache!.calculate(:sum, :credit_limit)
Account.all.skip_query_cache!.calculate(:sum, :credit_limit)
end
@ -1627,12 +1627,12 @@ def test_count_with_block_and_column_name_raises_an_error
test "#skip_query_cache! for a grouped calculation" do
Account.cache do
assert_queries(1) do
assert_queries_count(1) do
Account.group(:firm_id).calculate(:sum, :credit_limit)
Account.group(:firm_id).calculate(:sum, :credit_limit)
end
assert_queries(2) do
assert_queries_count(2) do
Account.all.skip_query_cache!.group(:firm_id).calculate(:sum, :credit_limit)
Account.all.skip_query_cache!.group(:firm_id).calculate(:sum, :credit_limit)
end

@ -152,7 +152,7 @@ class CollectionCacheKeyTest < ActiveRecord::TestCase
test "it triggers at most one query" do
developers = Developer.where(name: "David")
assert_queries(1) { developers.cache_key }
assert_queries_count(1) { developers.cache_key }
assert_no_queries { developers.cache_key }
end

@ -132,7 +132,7 @@ def test_yaml_loads_5_1_dump
def test_yaml_loads_5_1_dump_without_indexes_still_queries_for_indexes
cache = load_bound_reflection(schema_dump_path)
assert_queries :any, ignore_none: true do
assert_queries_count(include_schema: true) do
assert_equal 1, cache.indexes("courses").size
end
end

@ -132,7 +132,7 @@ class ::SpecialReply < ::Reply
# SELECT "topics".* FROM "topics" WHERE "topics"."id" = ? LIMIT ?
# SELECT COUNT(*) FROM "topics" WHERE "topics"."type" IN (?, ?, ?, ?, ?) AND "topics"."parent_id" = ?
assert_queries(2) do
assert_queries_count(2) do
Topic.reset_counters(@topic.id, :replies_count)
end
end
@ -143,7 +143,7 @@ class ::SpecialReply < ::Reply
# SELECT "topics".* FROM "topics" WHERE "topics"."id" = ? LIMIT ?
# SELECT COUNT(*) FROM "topics" WHERE "topics"."type" IN (?, ?, ?, ?, ?) AND "topics"."parent_id" = ?
# UPDATE "topics" SET "updated_at" = ? WHERE "topics"."id" = ?
assert_queries(3) do
assert_queries_count(3) do
Topic.reset_counters(@topic.id, :replies_count, touch: true)
end
end

@ -10,7 +10,7 @@ class CustomLockingTest < ActiveRecord::TestCase
def test_custom_lock
if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
assert_match "SHARE MODE", Person.lock("LOCK IN SHARE MODE").to_sql
assert_sql(/LOCK IN SHARE MODE/) do
assert_queries_match(/LOCK IN SHARE MODE/) do
Person.all.merge!(lock: "LOCK IN SHARE MODE").find(1)
end
end

@ -362,7 +362,7 @@ def test_partial_update
old_updated_on = 1.hour.ago.beginning_of_day
with_partial_writes Pirate, false do
assert_queries(2) { 2.times { pirate.save! } }
assert_queries_count(6) { 2.times { pirate.save! } }
Pirate.where(id: pirate.id).update_all(updated_on: old_updated_on)
end
@ -370,7 +370,7 @@ def test_partial_update
assert_no_queries { 2.times { pirate.save! } }
assert_equal old_updated_on, pirate.reload.updated_on
assert_queries(1) { pirate.catchphrase = "bar"; pirate.save! }
assert_queries_count(3) { pirate.catchphrase = "bar"; pirate.save! }
assert_not_equal old_updated_on, pirate.reload.updated_on
end
end
@ -379,7 +379,7 @@ def test_partial_update_with_optimistic_locking
person = Person.new(first_name: "foo")
with_partial_writes Person, false do
assert_queries(2) { 2.times { person.save! } }
assert_queries_count(6) { 2.times { person.save! } }
Person.where(id: person.id).update_all(first_name: "baz")
end
@ -389,7 +389,7 @@ def test_partial_update_with_optimistic_locking
assert_no_queries { 2.times { person.save! } }
assert_equal old_lock_version, person.reload.lock_version
assert_queries(1) { person.first_name = "bar"; person.save! }
assert_queries_count(3) { person.first_name = "bar"; person.save! }
assert_not_equal old_lock_version, person.reload.lock_version
end
end
@ -645,12 +645,12 @@ def test_datetime_attribute_doesnt_change_if_zone_is_modified_in_string
test "partial insert" do
with_partial_writes Person do
jon = nil
assert_sql(/first_name/i) do
jon = Person.create! first_name: "Jon"
assert_no_queries_match(/followers_count/) do
assert_queries_match(/first_name/) do
jon = Person.create! first_name: "Jon"
end
end
assert ActiveRecord::SQLCounter.log_all.none? { |sql| sql.include?("followers_count") }
jon.reload
assert_equal "Jon", jon.first_name
assert_equal 0, jon.followers_count

@ -25,7 +25,7 @@ def test_result_set_does_not_include_collection_of_excluded_records
def test_result_set_does_not_include_collection_of_excluded_records_from_a_query
query = Post.where(id: @post)
assert_sql(/SELECT #{Regexp.escape Post.connection.quote_table_name("posts.id")} FROM/) do
assert_queries_match(/SELECT #{Regexp.escape Post.connection.quote_table_name("posts.id")} FROM/) do
records = Post.excluding(query).to_a
assert_not_includes records, @post
@ -35,7 +35,7 @@ def test_result_set_does_not_include_collection_of_excluded_records_from_a_query
def test_result_set_does_not_include_collection_of_excluded_records_from_a_loaded_query
query = Post.where(id: @post).load
records = assert_queries 1 do
records = assert_queries_count 1 do
Post.excluding(query).to_a
end
@ -45,7 +45,7 @@ def test_result_set_does_not_include_collection_of_excluded_records_from_a_loade
def test_result_set_does_not_include_collection_of_excluded_records_and_queries
thinking = posts(:thinking)
records = assert_queries 2 do
records = assert_queries_count 2 do
Post.excluding(@post, Post.where(id: thinking)).to_a
end
@ -72,7 +72,7 @@ def test_result_set_through_association_does_not_include_collection_of_excluded_
def test_result_set_through_association_does_not_include_collection_of_excluded_records_from_a_relation
relation = @post.comments
assert_sql(/SELECT #{Regexp.escape Comment.connection.quote_table_name("comments.id")} FROM/) do
assert_queries_match(/SELECT #{Regexp.escape Comment.connection.quote_table_name("comments.id")} FROM/) do
records = Comment.excluding(relation).to_a
assert_not_empty records
@ -84,7 +84,7 @@ def test_result_set_through_association_does_not_include_collection_of_excluded_
def test_result_set_through_association_does_not_include_collection_of_excluded_records_from_a_loaded_relation
relation = @post.comments.load
records = assert_queries 1 do
records = assert_queries_count 1 do
Comment.excluding(relation).to_a
end

@ -276,7 +276,7 @@ def test_exists_passing_active_record_object_is_not_permitted
def test_exists_does_not_select_columns_without_alias
c = Topic.connection
assert_sql(/SELECT 1 AS one FROM #{Regexp.escape(c.quote_table_name("topics"))}/i) do
assert_queries_match(/SELECT 1 AS one FROM #{Regexp.escape(c.quote_table_name("topics"))}/i) do
Topic.exists?
end
end
@ -366,26 +366,26 @@ def test_exists_with_eager_load
def test_exists_with_includes_limit_and_empty_result
assert_no_queries { assert_equal false, Topic.includes(:replies).limit(0).exists? }
assert_queries(1) { assert_equal false, Topic.includes(:replies).limit(1).where("0 = 1").exists? }
assert_queries_count(1) { assert_equal false, Topic.includes(:replies).limit(1).where("0 = 1").exists? }
end
def test_exists_with_distinct_association_includes_and_limit
author = Author.first
unique_categorized_posts = author.unique_categorized_posts.includes(:special_comments)
assert_no_queries { assert_equal false, unique_categorized_posts.limit(0).exists? }
assert_queries(1) { assert_equal true, unique_categorized_posts.limit(1).exists? }
assert_queries_count(1) { assert_equal true, unique_categorized_posts.limit(1).exists? }
end
def test_exists_with_distinct_association_includes_limit_and_order
author = Author.first
unique_categorized_posts = author.unique_categorized_posts.includes(:special_comments).order("comments.tags_count DESC")
assert_no_queries { assert_equal false, unique_categorized_posts.limit(0).exists? }
assert_queries(1) { assert_equal true, unique_categorized_posts.limit(1).exists? }
assert_queries_count(1) { assert_equal true, unique_categorized_posts.limit(1).exists? }
end
def test_exists_should_reference_correct_aliases_while_joining_tables_of_has_many_through_association
ratings = developers(:david).ratings.includes(comment: :post).where(posts: { id: 1 })
assert_queries(1) { assert_not_predicate ratings.limit(1), :exists? }
assert_queries_count(1) { assert_not_predicate ratings.limit(1), :exists? }
end
def test_exists_with_empty_table_and_no_args_given
@ -440,13 +440,13 @@ def test_member_when_non_AR_object_passed_on_loaded_relation
end
def test_include_on_unloaded_relation_with_match
assert_sql(/1 AS one.*LIMIT/) do
assert_queries_match(/1 AS one.*LIMIT/) do
assert_equal true, Customer.where(name: "David").include?(customers(:david))
end
end
def test_include_on_unloaded_relation_without_match
assert_sql(/1 AS one.*LIMIT/) do
assert_queries_match(/1 AS one.*LIMIT/) do
assert_equal false, Customer.where(name: "David").include?(customers(:mary))
end
end
@ -461,7 +461,7 @@ def test_include_on_unloaded_relation_with_mismatched_class
end
def test_include_on_unloaded_relation_with_offset
assert_sql(/ORDER BY name ASC/) do
assert_queries_match(/ORDER BY name ASC/) do
assert_equal true, Customer.offset(1).order("name ASC").include?(customers(:mary))
end
end
@ -504,7 +504,7 @@ def test_include_on_loaded_relation_without_match
end
def test_include_on_unloaded_relation_with_composite_primary_key
assert_sql(/1 AS one.*LIMIT/) do
assert_queries_match(/1 AS one.*LIMIT/) do
book = cpk_books(:cpk_great_author_first_book)
assert Cpk::Book.where(title: "The first book").include?(book)
end
@ -520,13 +520,13 @@ def test_include_on_loaded_relation_with_composite_primary_key
end
def test_member_on_unloaded_relation_with_match
assert_sql(/1 AS one.*LIMIT/) do
assert_queries_match(/1 AS one.*LIMIT/) do
assert_equal true, Customer.where(name: "David").member?(customers(:david))
end
end
def test_member_on_unloaded_relation_without_match
assert_sql(/1 AS one.*LIMIT/) do
assert_queries_match(/1 AS one.*LIMIT/) do
assert_equal false, Customer.where(name: "David").member?(customers(:mary))
end
end
@ -541,7 +541,7 @@ def test_member_on_unloaded_relation_with_mismatched_class
end
def test_member_on_unloaded_relation_with_offset
assert_sql(/ORDER BY name ASC/) do
assert_queries_match(/ORDER BY name ASC/) do
assert_equal true, Customer.offset(1).order("name ASC").member?(customers(:mary))
end
end
@ -575,7 +575,7 @@ def test_member_on_loaded_relation_without_match
end
def test_member_on_unloaded_relation_with_composite_primary_key
assert_sql(/1 AS one.*LIMIT/) do
assert_queries_match(/1 AS one.*LIMIT/) do
book = cpk_books(:cpk_great_author_first_book)
assert Cpk::Book.where(title: "The first book").member?(book)
end
@ -617,19 +617,19 @@ def test_find_by_ids_with_limit_and_offset
end
def test_find_with_large_number
assert_queries(0) do
assert_queries_count(0) do
assert_raises(ActiveRecord::RecordNotFound) { Topic.find("9999999999999999999999999999999") }
end
end
def test_find_by_with_large_number
assert_queries(0) do
assert_queries_count(0) do
assert_nil Topic.find_by(id: "9999999999999999999999999999999")
end
end
def test_find_by_id_with_large_number
assert_queries(0) do
assert_queries_count(0) do
assert_nil Topic.find_by_id("9999999999999999999999999999999")
end
end
@ -661,7 +661,7 @@ def test_find_an_empty_array
end
def test_find_doesnt_have_implicit_ordering
assert_sql(/^((?!ORDER).)*$/) { Topic.find(1) }
assert_queries_match(/^((?!ORDER).)*$/) { Topic.find(1) }
end
def test_find_by_ids_missing_one
@ -949,11 +949,11 @@ def test_model_class_responds_to_third_to_last_bang
def test_nth_to_last_with_order_uses_limit
c = Topic.connection
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.id"))} DESC LIMIT/i) do
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.id"))} DESC LIMIT/i) do
Topic.second_to_last
end
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.updated_at"))} DESC LIMIT/i) do
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.updated_at"))} DESC LIMIT/i) do
Topic.order(:updated_at).second_to_last
end
end
@ -979,9 +979,9 @@ def test_model_class_responds_to_last_bang
end
def test_take_and_first_and_last_with_integer_should_use_sql_limit
assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.take(3).entries }
assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.first(2).entries }
assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.last(5).entries }
assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.take(3).entries }
assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.first(2).entries }
assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) { Topic.last(5).entries }
end
def test_last_with_integer_and_order_should_keep_the_order
@ -990,13 +990,13 @@ def test_last_with_integer_and_order_should_keep_the_order
def test_last_with_integer_and_order_should_use_sql_limit
relation = Topic.order("title")
assert_queries(1) { relation.last(5) }
assert_queries_count(1) { relation.last(5) }
assert_not_predicate relation, :loaded?
end
def test_last_with_integer_and_reorder_should_use_sql_limit
relation = Topic.reorder("title")
assert_queries(1) { relation.last(5) }
assert_queries_count(1) { relation.last(5) }
assert_not_predicate relation, :loaded?
end
@ -1067,7 +1067,7 @@ def test_implicit_order_column_is_configurable
assert_equal topics(:third), Topic.last
c = Topic.connection
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.title"))} DESC, #{Regexp.escape(c.quote_table_name("topics.id"))} DESC LIMIT/i) {
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.title"))} DESC, #{Regexp.escape(c.quote_table_name("topics.id"))} DESC LIMIT/i) {
Topic.last
}
ensure
@ -1079,7 +1079,7 @@ def test_implicit_order_set_to_primary_key
Topic.implicit_order_column = "id"
c = Topic.connection
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.id"))} DESC LIMIT/i) {
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.id"))} DESC LIMIT/i) {
Topic.last
}
ensure
@ -1091,7 +1091,7 @@ def test_implicit_order_for_model_without_primary_key
NonPrimaryKey.implicit_order_column = "created_at"
c = NonPrimaryKey.connection
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("non_primary_keys.created_at"))} DESC LIMIT/i) {
assert_queries_match(/ORDER BY #{Regexp.escape(c.quote_table_name("non_primary_keys.created_at"))} DESC LIMIT/i) {
NonPrimaryKey.last
}
ensure
@ -1104,7 +1104,7 @@ def test_implicit_order_column_reorders_query_constraints
quoted_type = Regexp.escape(c.quote_table_name("clothing_items.clothing_type"))
quoted_color = Regexp.escape(c.quote_table_name("clothing_items.color"))
assert_sql(/ORDER BY #{quoted_color} ASC, #{quoted_type} ASC LIMIT/i) do
assert_queries_match(/ORDER BY #{quoted_color} ASC, #{quoted_type} ASC LIMIT/i) do
assert_kind_of ClothingItem, ClothingItem.first
end
ensure
@ -1118,7 +1118,7 @@ def test_implicit_order_column_prepends_query_constraints
quoted_color = Regexp.escape(c.quote_table_name("clothing_items.color"))
quoted_descrption = Regexp.escape(c.quote_table_name("clothing_items.description"))
assert_sql(/ORDER BY #{quoted_descrption} ASC, #{quoted_type} ASC, #{quoted_color} ASC LIMIT/i) do
assert_queries_match(/ORDER BY #{quoted_descrption} ASC, #{quoted_type} ASC, #{quoted_color} ASC LIMIT/i) do
assert_kind_of ClothingItem, ClothingItem.first
end
ensure
@ -1748,7 +1748,7 @@ def test_finder_with_offset_string
end
test "find_by doesn't have implicit ordering" do
assert_sql(/^((?!ORDER).)*$/) { Post.find_by(id: posts(:eager_other).id) }
assert_queries_match(/^((?!ORDER).)*$/) { Post.find_by(id: posts(:eager_other).id) }
end
test "find_by! with hash conditions returns the first matching record" do
@ -1764,7 +1764,7 @@ def test_finder_with_offset_string
end
test "find_by! doesn't have implicit ordering" do
assert_sql(/^((?!ORDER).)*$/) { Post.find_by!(id: posts(:eager_other).id) }
assert_queries_match(/^((?!ORDER).)*$/) { Post.find_by!(id: posts(:eager_other).id) }
end
test "find_by! raises RecordNotFound if the record is missing" do
@ -1797,12 +1797,12 @@ def test_finder_with_offset_string
test "#skip_query_cache! for #exists?" do
Topic.cache do
assert_queries(1) do
assert_queries_count(1) do
Topic.exists?
Topic.exists?
end
assert_queries(2) do
assert_queries_count(2) do
Topic.all.skip_query_cache!.exists?
Topic.all.skip_query_cache!.exists?
end
@ -1811,12 +1811,12 @@ def test_finder_with_offset_string
test "#skip_query_cache! for #exists? with a limited eager load" do
Topic.cache do
assert_queries(1) do
assert_queries_count(1) do
Topic.eager_load(:replies).limit(1).exists?
Topic.eager_load(:replies).limit(1).exists?
end
assert_queries(2) do
assert_queries_count(2) do
Topic.eager_load(:replies).limit(1).skip_query_cache!.exists?
Topic.eager_load(:replies).limit(1).skip_query_cache!.exists?
end
@ -1828,7 +1828,7 @@ def test_finder_with_offset_string
quoted_type = Regexp.escape(c.quote_table_name("clothing_items.clothing_type"))
quoted_color = Regexp.escape(c.quote_table_name("clothing_items.color"))
assert_sql(/ORDER BY #{quoted_type} DESC, #{quoted_color} DESC LIMIT/i) do
assert_queries_match(/ORDER BY #{quoted_type} DESC, #{quoted_color} DESC LIMIT/i) do
assert_kind_of ClothingItem, ClothingItem.last
end
end
@ -1838,7 +1838,7 @@ def test_finder_with_offset_string
quoted_type = Regexp.escape(c.quote_table_name("clothing_items.clothing_type"))
quoted_color = Regexp.escape(c.quote_table_name("clothing_items.color"))
assert_sql(/ORDER BY #{quoted_type} ASC, #{quoted_color} ASC LIMIT/i) do
assert_queries_match(/ORDER BY #{quoted_type} ASC, #{quoted_color} ASC LIMIT/i) do
assert_kind_of ClothingItem, ClothingItem.first
end
end

@ -479,7 +479,7 @@ def test_alt_eager_loading
def test_eager_load_belongs_to_primary_key_quoting
c = Account.connection
bind_param = Arel::Nodes::BindParam.new(nil)
assert_sql(/#{Regexp.escape(c.quote_table_name("companies.id"))} = (?:#{Regexp.escape(bind_param.to_sql)}|1)/i) do
assert_queries_match(/#{Regexp.escape(c.quote_table_name("companies.id"))} = (?:#{Regexp.escape(bind_param.to_sql)}|1)/i) do
Account.all.merge!(includes: :firm).find(1)
end
end

@ -133,7 +133,7 @@ def test_insert_all_can_skip_duplicate_records
def test_insert_all_generates_correct_sql
skip unless supports_insert_on_duplicate_skip?
assert_sql(/ON DUPLICATE KEY UPDATE/) do
assert_queries_match(/ON DUPLICATE KEY UPDATE/) do
Book.insert_all [{ id: 1, name: "Agile Web Development with Rails" }]
end
end

@ -382,7 +382,7 @@ def test_lock_without_default_queries_count
assert_equal "title1", t1.title
assert_equal 0, t1.lock_version
assert_queries(1) { t1.update(title: "title2") }
assert_queries_count(3) { t1.update(title: "title2") }
t1.reload
assert_equal "title2", t1.title
@ -390,7 +390,7 @@ def test_lock_without_default_queries_count
t2 = LockWithoutDefault.new(title: "title1")
assert_queries(1) { t2.save! }
assert_queries_count(3) { t2.save! }
t2.reload
assert_equal "title1", t2.title
@ -439,7 +439,7 @@ def test_lock_with_custom_column_without_default_queries_count
assert_equal "title1", t1.title
assert_equal 0, t1.custom_lock_version
assert_queries(1) { t1.update(title: "title2") }
assert_queries_count(3) { t1.update(title: "title2") }
t1.reload
assert_equal "title2", t1.title
@ -447,7 +447,7 @@ def test_lock_with_custom_column_without_default_queries_count
t2 = LockWithCustomColumnWithoutDefault.new(title: "title1")
assert_queries(1) { t2.save! }
assert_queries_count(3) { t2.save! }
t2.reload
assert_equal "title1", t2.title
@ -761,7 +761,7 @@ def test_with_lock_configures_transaction
def test_lock_sending_custom_lock_statement
Person.transaction do
person = Person.find(1)
assert_sql(/LIMIT \$?\d FOR SHARE NOWAIT/) do
assert_queries_match(/LIMIT \$?\d FOR SHARE NOWAIT/) do
person.lock!("FOR SHARE NOWAIT")
end
end
@ -777,7 +777,7 @@ def test_with_lock_sets_isolation
def test_with_lock_locks_with_no_args
person = Person.find 1
assert_sql(/LIMIT \$?\d FOR UPDATE/i) do
assert_queries_match(/LIMIT \$?\d FOR UPDATE/i) do
person.with_lock do
end
end

@ -394,8 +394,8 @@ def test_remove_columns_single_statement
# SQLite3's ALTER TABLE statement has several limitations. To manage
# this, the adapter creates a temporary table, copies the data, drops
# the old table, creates the new table, then copies the data back.
expected_query_count = current_adapter?(:SQLite3Adapter) ? 12 : 1
assert_queries(expected_query_count) do
expected_query_count = current_adapter?(:SQLite3Adapter) ? 14 : 1
assert_queries_count(expected_query_count) do
connection.remove_columns("my_table", "col_one", "col_two")
end
@ -411,8 +411,8 @@ def test_add_timestamps_single_statement
# SQLite3's ALTER TABLE statement has several limitations. To manage
# this, the adapter creates a temporary table, copies the data, drops
# the old table, creates the new table, then copies the data back.
expected_query_count = current_adapter?(:SQLite3Adapter) ? 12 : 1
assert_queries(expected_query_count) do
expected_query_count = current_adapter?(:SQLite3Adapter) ? 14 : 1
assert_queries_count(expected_query_count) do
connection.add_timestamps("my_table")
end

@ -35,7 +35,7 @@ class ReferencesForeignKeyInCreateTest < ActiveRecord::TestCase
end
test "foreign keys can be created in one query when index is not added" do
assert_queries(1) do
assert_queries_count(1) do
@connection.create_table :testings do |t|
t.references :testing_parent, foreign_key: true, index: false
end

@ -1238,7 +1238,7 @@ def test_adding_multiple_columns
raise "need an expected query count for #{classname}"
}
assert_queries(expected_query_count) do
assert_queries_count(expected_query_count) do
with_bulk_change_table do |t|
t.column :name, :string
t.string :qualification, :experience
@ -1278,7 +1278,7 @@ def test_removing_columns
[:qualification, :experience].each { |c| assert column(c) }
assert_queries(1) do
assert_queries_count(1) do
with_bulk_change_table do |t|
t.remove :qualification, :experience
t.string :qualification_experience
@ -1296,7 +1296,7 @@ def test_adding_timestamps
assert column(:title)
assert_queries(1) do
assert_queries_count(1) do
with_bulk_change_table do |t|
t.timestamps
t.remove :title
@ -1314,7 +1314,7 @@ def test_removing_timestamps
[:created_at, :updated_at].each { |c| assert column(c) }
assert_queries(1) do
assert_queries_count(1) do
with_bulk_change_table do |t|
t.remove_timestamps
t.string :title
@ -1341,7 +1341,7 @@ def test_adding_indexes
raise "need an expected query count for #{classname}"
}
assert_queries(expected_query_count) do
assert_queries_count(expected_query_count) do
with_bulk_change_table do |t|
t.index :username, unique: true, name: :awesome_username_index
t.index [:name, :age], comment: "This is a comment"
@ -1375,7 +1375,7 @@ def test_removing_index
raise "need an expected query count for #{classname}"
}
assert_queries(expected_query_count) do
assert_queries_count(expected_query_count) do
with_bulk_change_table do |t|
t.remove_index :name
t.index :name, name: :new_name_index, unique: true
@ -1406,7 +1406,7 @@ def test_changing_columns
raise "need an expected query count for #{classname}"
}
assert_queries(expected_query_count, ignore_none: true) do
assert_queries_count(expected_query_count, include_schema: true) do
with_bulk_change_table do |t|
t.change :name, :string, default: "NONAME"
t.change :birthdate, :datetime, comment: "This is a comment"
@ -1437,7 +1437,7 @@ def test_changing_column_null_with_default
raise "need an expected query count for #{classname}"
}
assert_queries(expected_query_count, ignore_none: true) do
assert_queries_count(expected_query_count, include_schema: true) do
with_bulk_change_table do |t|
t.change :name, :string, default: "NONAME"
t.change :birthdate, :datetime
@ -1508,7 +1508,7 @@ def test_changing_index
raise "need an expected query count for #{classname}"
}
assert_queries(expected_query_count) do
assert_queries_count(expected_query_count) do
with_bulk_change_table do |t|
t.remove_index name: :username_index
t.index :username, name: :username_index, unique: true
@ -1576,7 +1576,7 @@ def change
end
}.new
assert_queries(1) do
assert_queries_count(1) do
migration.migrate(:down)
end

@ -1096,7 +1096,7 @@ def setup
part = ship.parts.build(name: "Stern")
ship.treasures.build(looter: part)
assert_queries 3 do
assert_queries_count(5) do
ship.save!
end
end

@ -20,7 +20,7 @@ def test_none
end
def test_none_chainable
assert_queries(0) do
assert_queries_count(0) do
assert_equal [], Developer.none.where(name: "David")
end
end
@ -38,7 +38,7 @@ def test_async_query_on_null_relation
end
def test_none_chained_to_methods_firing_queries_straight_to_db
assert_no_queries(ignore_none: false) do
assert_no_queries do
assert_equal [], Developer.none.pluck(:id, :name)
assert_equal 0, Developer.none.delete_all
assert_equal 0, Developer.none.update_all(name: "David")

@ -1523,7 +1523,7 @@ def test_reset_column_information_resets_children
def test_update_uses_query_constraints_config
clothing_item = clothing_items(:green_t_shirt)
sql = capture_sql { clothing_item.update(description: "Lovely green t-shirt") }.first
sql = capture_sql { clothing_item.update(description: "Lovely green t-shirt") }.second
assert_match(/WHERE .*clothing_type/, sql)
assert_match(/WHERE .*color/, sql)
end
@ -1531,7 +1531,7 @@ def test_update_uses_query_constraints_config
def test_save_uses_query_constraints_config
clothing_item = clothing_items(:green_t_shirt)
clothing_item.description = "Lovely green t-shirt"
sql = capture_sql { clothing_item.save }.first
sql = capture_sql { clothing_item.save }.second
assert_match(/WHERE .*clothing_type/, sql)
assert_match(/WHERE .*color/, sql)
end
@ -1545,7 +1545,7 @@ def test_reload_uses_query_constraints_config
def test_destroy_uses_query_constraints_config
clothing_item = clothing_items(:green_t_shirt)
sql = capture_sql { clothing_item.destroy }.first
sql = capture_sql { clothing_item.destroy }.second
assert_match(/WHERE .*clothing_type/, sql)
assert_match(/WHERE .*color/, sql)
end
@ -1559,7 +1559,7 @@ def test_delete_uses_query_constraints_config
def test_update_attribute_uses_query_constraints_config
clothing_item = clothing_items(:green_t_shirt)
sql = capture_sql { clothing_item.update_attribute(:description, "Lovely green t-shirt") }.first
sql = capture_sql { clothing_item.update_attribute(:description, "Lovely green t-shirt") }.second
assert_match(/WHERE .*clothing_type/, sql)
assert_match(/WHERE .*color/, sql)
end
@ -1568,7 +1568,7 @@ def test_it_is_possible_to_update_parts_of_the_query_constraints_config
clothing_item = clothing_items(:green_t_shirt)
clothing_item.color = "blue"
clothing_item.description = "Now it's a blue t-shirt"
sql = capture_sql { clothing_item.save }.first
sql = capture_sql { clothing_item.save }.second
assert_match(/WHERE .*clothing_type/, sql)
assert_match(/WHERE .*color/, sql)

@ -250,7 +250,7 @@ def test_create_without_primary_key_no_extra_query
self.table_name = "dashboards"
end
klass.create! # warmup schema cache
assert_queries(3, ignore_none: true) { klass.create! }
assert_queries_count(3, include_schema: true) { klass.create! }
end
def test_assign_id_raises_error_if_primary_key_doesnt_exist

@ -295,25 +295,25 @@ def test_cache_passing_a_relation
end
def test_find_queries
assert_queries(2) { Task.find(1); Task.find(1) }
assert_queries_count(2) { Task.find(1); Task.find(1) }
end
def test_find_queries_with_cache
Task.cache do
assert_queries(1) { Task.find(1); Task.find(1) }
assert_queries_count(1) { Task.find(1); Task.find(1) }
end
end
def test_find_queries_with_cache_multi_record
Task.cache do
assert_queries(2) { Task.find(1); Task.find(1); Task.find(2) }
assert_queries_count(2) { Task.find(1); Task.find(1); Task.find(2) }
end
end
def test_find_queries_with_multi_cache_blocks
Task.cache do
Task.cache do
assert_queries(2) { Task.find(1); Task.find(2) }
assert_queries_count(2) { Task.find(1); Task.find(2) }
end
assert_no_queries { Task.find(1); Task.find(1); Task.find(2) }
end
@ -321,19 +321,19 @@ def test_find_queries_with_multi_cache_blocks
def test_count_queries_with_cache
Task.cache do
assert_queries(1) { Task.count; Task.count }
assert_queries_count(1) { Task.count; Task.count }
end
end
def test_exists_queries_with_cache
Post.cache do
assert_queries(1) { Post.exists?; Post.exists? }
assert_queries_count(1) { Post.exists?; Post.exists? }
end
end
def test_select_all_with_cache
Post.cache do
assert_queries(1) do
assert_queries_count(1) do
2.times { Post.connection.select_all(Post.all) }
end
end
@ -341,7 +341,7 @@ def test_select_all_with_cache
def test_select_one_with_cache
Post.cache do
assert_queries(1) do
assert_queries_count(1) do
2.times { Post.connection.select_one(Post.all) }
end
end
@ -349,7 +349,7 @@ def test_select_one_with_cache
def test_select_value_with_cache
Post.cache do
assert_queries(1) do
assert_queries_count(1) do
2.times { Post.connection.select_value(Post.all) }
end
end
@ -357,7 +357,7 @@ def test_select_value_with_cache
def test_select_values_with_cache
Post.cache do
assert_queries(1) do
assert_queries_count(1) do
2.times { Post.connection.select_values(Post.all) }
end
end
@ -365,7 +365,7 @@ def test_select_values_with_cache
def test_select_rows_with_cache
Post.cache do
assert_queries(1) do
assert_queries_count(1) do
2.times { Post.connection.select_rows(Post.all) }
end
end
@ -407,7 +407,7 @@ def test_cache_does_not_raise_exceptions
subscriber = ActiveSupport::Notifications.subscribe "sql.active_record", logger
ActiveRecord::Base.cache do
assert_queries(1) { Task.find(1); Task.find(1) }
assert_queries_count(1) { Task.find(1); Task.find(1) }
end
assert_not_predicate logger, :exception?
@ -421,7 +421,7 @@ def test_query_cache_does_not_allow_sql_key_mutation
end
ActiveRecord::Base.cache do
assert_queries(1) do
assert_queries_count(1) do
assert_raises FrozenError do
Task.find(1)
end
@ -433,11 +433,11 @@ def test_query_cache_does_not_allow_sql_key_mutation
def test_cache_is_flat
Task.cache do
assert_queries(1) { Topic.find(1); Topic.find(1) }
assert_queries_count(1) { Topic.find(1); Topic.find(1) }
end
ActiveRecord::Base.cache do
assert_queries(1) { Task.find(1); Task.find(1) }
assert_queries_count(1) { Task.find(1); Task.find(1) }
end
end
@ -451,7 +451,7 @@ def test_cache_is_ignored_for_locked_relations
task = Task.find 1
Task.cache do
assert_queries(2) { task.lock!; task.lock! }
assert_queries_count(2) { task.lock!; task.lock! }
end
end
@ -460,7 +460,7 @@ def test_cache_is_available_when_connection_is_connected
ActiveRecord::Base.configurations = {}
Task.cache do
assert_queries(1) { Task.find(1); Task.find(1) }
assert_queries_count(1) { Task.find(1); Task.find(1) }
end
ensure
ActiveRecord::Base.configurations = conf
@ -475,7 +475,7 @@ def test_cache_is_available_when_using_a_not_connected_connection
assert_not_predicate Task, :connected?
Task.cache do
assert_queries(1) { Task.find(1); Task.find(1) }
assert_queries_count(1) { Task.find(1); Task.find(1) }
ensure
ActiveRecord::Base.establish_connection(original_connection)
end
@ -485,7 +485,7 @@ def test_query_cache_executes_new_queries_within_block
ActiveRecord::Base.connection.enable_query_cache!
# Warm up the cache by running the query
assert_queries(1) do
assert_queries_count(1) do
assert_equal 0, Post.where(title: "test").to_a.count
end
@ -496,7 +496,7 @@ def test_query_cache_executes_new_queries_within_block
ActiveRecord::Base.connection.uncached do
# Check that new query is executed, avoiding the cache
assert_queries(1) do
assert_queries_count(1) do
assert_equal 0, Post.where(title: "test").to_a.count
end
end
@ -902,13 +902,13 @@ def test_query_cache_lru_eviction
connection.pool.db_config.stub(:query_cache, 2) do
connection.send(:configure_query_cache!)
Post.cache do
assert_queries(2) do
assert_queries_count(2) do
connection.select_all("SELECT 1")
connection.select_all("SELECT 2")
connection.select_all("SELECT 1")
end
assert_queries(1) do
assert_queries_count(1) do
connection.select_all("SELECT 3")
connection.select_all("SELECT 3")
end
@ -917,7 +917,7 @@ def test_query_cache_lru_eviction
connection.select_all("SELECT 1")
end
assert_queries(1) do
assert_queries_count(1) do
connection.select_all("SELECT 2")
end
end

@ -58,7 +58,7 @@ def test_escaping_bad_comments
def test_basic_commenting
ActiveRecord::QueryLogs.tags = [ :application ]
assert_sql(%r{select id from posts /\*application:active_record\*/$}) do
assert_queries_match(%r{select id from posts /\*application:active_record\*/$}) do
ActiveRecord::Base.connection.execute "select id from posts"
end
end
@ -67,14 +67,14 @@ def test_add_comments_to_beginning_of_query
ActiveRecord::QueryLogs.tags = [ :application ]
ActiveRecord::QueryLogs.prepend_comment = true
assert_sql(%r{/\*application:active_record\*/ select id from posts$}) do
assert_queries_match(%r{/\*application:active_record\*/ select id from posts$}) do
ActiveRecord::Base.connection.execute "select id from posts"
end
end
def test_exists_is_commented
ActiveRecord::QueryLogs.tags = [ :application ]
assert_sql(%r{/\*application:active_record\*/}) do
assert_queries_match(%r{/\*application:active_record\*/}) do
Dashboard.exists?
end
end
@ -83,7 +83,7 @@ def test_delete_is_commented
ActiveRecord::QueryLogs.tags = [ :application ]
record = Dashboard.first
assert_sql(%r{/\*application:active_record\*/}) do
assert_queries_match(%r{/\*application:active_record\*/}) do
record.destroy
end
end
@ -91,7 +91,7 @@ def test_delete_is_commented
def test_update_is_commented
ActiveRecord::QueryLogs.tags = [ :application ]
assert_sql(%r{/\*application:active_record\*/}) do
assert_queries_match(%r{/\*application:active_record\*/}) do
dash = Dashboard.first
dash.name = "New name"
dash.save
@ -101,7 +101,7 @@ def test_update_is_commented
def test_create_is_commented
ActiveRecord::QueryLogs.tags = [ :application ]
assert_sql(%r{/\*application:active_record\*/}) do
assert_queries_match(%r{/\*application:active_record\*/}) do
Dashboard.create(name: "Another dashboard")
end
end
@ -109,7 +109,7 @@ def test_create_is_commented
def test_select_is_commented
ActiveRecord::QueryLogs.tags = [ :application ]
assert_sql(%r{/\*application:active_record\*/}) do
assert_queries_match(%r{/\*application:active_record\*/}) do
Dashboard.all.to_a
end
end
@ -119,11 +119,11 @@ def test_retrieves_comment_from_cache_when_enabled_and_set
i = 0
ActiveRecord::QueryLogs.tags = [ { query_counter: -> { i += 1 } } ]
assert_sql("SELECT 1 /*query_counter:1*/") do
assert_queries_match("SELECT 1 /*query_counter:1*/") do
ActiveRecord::Base.connection.execute "SELECT 1"
end
assert_sql("SELECT 1 /*query_counter:1*/") do
assert_queries_match("SELECT 1 /*query_counter:1*/") do
ActiveRecord::Base.connection.execute "SELECT 1"
end
end
@ -133,13 +133,13 @@ def test_resets_cache_on_context_update
ActiveSupport::ExecutionContext[:temporary] = "value"
ActiveRecord::QueryLogs.tags = [ temporary_tag: ->(context) { context[:temporary] } ]
assert_sql("SELECT 1 /*temporary_tag:value*/") do
assert_queries_match("SELECT 1 /*temporary_tag:value*/") do
ActiveRecord::Base.connection.execute "SELECT 1"
end
ActiveSupport::ExecutionContext[:temporary] = "new_value"
assert_sql("SELECT 1 /*temporary_tag:new_value*/") do
assert_queries_match("SELECT 1 /*temporary_tag:new_value*/") do
ActiveRecord::Base.connection.execute "SELECT 1"
end
end
@ -147,11 +147,11 @@ def test_resets_cache_on_context_update
def test_default_tag_behavior
ActiveRecord::QueryLogs.tags = [:application, :foo]
ActiveSupport::ExecutionContext.set(foo: "bar") do
assert_sql(%r{/\*application:active_record,foo:bar\*/}) do
assert_queries_match(%r{/\*application:active_record,foo:bar\*/}) do
Dashboard.first
end
end
assert_sql(%r{/\*application:active_record\*/}) do
assert_queries_match(%r{/\*application:active_record\*/}) do
Dashboard.first
end
end
@ -160,7 +160,7 @@ def test_connection_is_passed_to_tagging_proc
connection = ActiveRecord::Base.connection
ActiveRecord::QueryLogs.tags = [ same_connection: ->(context) { context[:connection] == connection } ]
assert_sql("SELECT 1 /*same_connection:true*/") do
assert_queries_match("SELECT 1 /*same_connection:true*/") do
connection.execute "SELECT 1"
end
end
@ -170,21 +170,21 @@ def test_connection_does_not_override_already_existing_connection_in_context
ActiveSupport::ExecutionContext[:connection] = fake_connection
ActiveRecord::QueryLogs.tags = [ fake_connection: ->(context) { context[:connection] == fake_connection } ]
assert_sql("SELECT 1 /*fake_connection:true*/") do
assert_queries_match("SELECT 1 /*fake_connection:true*/") do
ActiveRecord::Base.connection.execute "SELECT 1"
end
end
def test_empty_comments_are_not_added
ActiveRecord::QueryLogs.tags = [ empty: -> { nil } ]
assert_sql(%r{select id from posts$}) do
assert_queries_match(%r{select id from posts$}) do
ActiveRecord::Base.connection.execute "select id from posts"
end
end
def test_sql_commenter_format
ActiveRecord::QueryLogs.update_formatter(:sqlcommenter)
assert_sql(%r{/\*application='active_record'\*/}) do
assert_queries_match(%r{/\*application='active_record'\*/}) do
Dashboard.first
end
end
@ -192,7 +192,7 @@ def test_sql_commenter_format
def test_custom_basic_tags
ActiveRecord::QueryLogs.tags = [ :application, { custom_string: "test content" } ]
assert_sql(%r{/\*application:active_record,custom_string:test content\*/}) do
assert_queries_match(%r{/\*application:active_record,custom_string:test content\*/}) do
Dashboard.first
end
end
@ -200,7 +200,7 @@ def test_custom_basic_tags
def test_custom_proc_tags
ActiveRecord::QueryLogs.tags = [ :application, { custom_proc: -> { "test content" } } ]
assert_sql(%r{/\*application:active_record,custom_proc:test content\*/}) do
assert_queries_match(%r{/\*application:active_record,custom_proc:test content\*/}) do
Dashboard.first
end
end
@ -211,7 +211,7 @@ def test_multiple_custom_tags
{ custom_proc: -> { "test content" }, another_proc: -> { "more test content" } },
]
assert_sql(%r{/\*application:active_record,custom_proc:test content,another_proc:more test content\*/}) do
assert_queries_match(%r{/\*application:active_record,custom_proc:test content,another_proc:more test content\*/}) do
Dashboard.first
end
end
@ -224,7 +224,7 @@ def test_sqlcommenter_format_value
{ tracestate: "congo=t61rcWkgMzE,rojo=00f067aa0ba902b7", custom_proc: -> { "Joe's Shack" } },
]
assert_sql(%r{custom_proc='Joe%27s%20Shack',tracestate='congo%3Dt61rcWkgMzE%2Crojo%3D00f067aa0ba902b7'\*/}) do
assert_queries_match(%r{custom_proc='Joe%27s%20Shack',tracestate='congo%3Dt61rcWkgMzE%2Crojo%3D00f067aa0ba902b7'\*/}) do
Dashboard.first
end
end
@ -237,7 +237,7 @@ def test_sqlcommenter_format_value_string_coercible
{ custom_proc: -> { 1234 } },
]
assert_sql(%r{custom_proc='1234'\*/}) do
assert_queries_match(%r{custom_proc='1234'\*/}) do
Dashboard.first
end
end
@ -256,7 +256,7 @@ def test_custom_proc_context_tags
ActiveSupport::ExecutionContext[:foo] = "bar"
ActiveRecord::QueryLogs.tags = [ :application, { custom_context_proc: ->(context) { context[:foo] } } ]
assert_sql(%r{/\*application:active_record,custom_context_proc:bar\*/}) do
assert_queries_match(%r{/\*application:active_record,custom_context_proc:bar\*/}) do
Dashboard.first
end
end

@ -196,7 +196,7 @@ def test_eager_loading_query
end
assert_equal expected_records, deferred_posts.to_a
assert_queries(0) do
assert_queries_count(0) do
deferred_posts.each(&:comments)
end
assert_equal Post.connection.supports_concurrent_connections?, status[:async]
@ -205,7 +205,7 @@ def test_eager_loading_query
end
def test_contradiction
assert_queries(0) do
assert_queries_count(0) do
assert_equal [], Post.where(id: []).load_async.to_a
end
@ -315,7 +315,7 @@ def test_eager_loading_query
assert_not_predicate deferred_posts, :scheduled?
assert_equal expected_records, deferred_posts.to_a
assert_queries(0) do
assert_queries_count(0) do
deferred_posts.each(&:comments)
end
@ -326,7 +326,7 @@ def test_eager_loading_query
end
def test_contradiction
assert_queries(0) do
assert_queries_count(0) do
assert_equal [], Post.where(id: []).load_async.to_a
end
@ -458,7 +458,7 @@ def test_eager_loading_query
assert_predicate deferred_posts, :scheduled?
assert_equal expected_records, deferred_posts.to_a
assert_queries(0) do
assert_queries_count(0) do
deferred_posts.each(&:comments)
end
assert_equal Post.connection.supports_concurrent_connections?, status[:async]
@ -467,7 +467,7 @@ def test_eager_loading_query
end
def test_contradiction
assert_queries(0) do
assert_queries_count(0) do
assert_equal [], Post.where(id: []).load_async.to_a
end

@ -206,28 +206,28 @@ def test_merge_doesnt_duplicate_same_clauses
non_mary_and_bob = Author.where.not(id: [mary, bob])
author_id = Author.connection.quote_table_name("authors.id")
assert_sql(/WHERE #{Regexp.escape(author_id)} NOT IN \((\?|\W?\w?\d), \g<1>\)\z/) do
assert_queries_match(/WHERE #{Regexp.escape(author_id)} NOT IN \((\?|\W?\w?\d), \g<1>\)\z/) do
assert_equal [david], non_mary_and_bob.merge(non_mary_and_bob)
end
only_david = Author.where("#{author_id} IN (?)", david)
if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
assert_sql(/WHERE \(#{Regexp.escape(author_id)} IN \('1'\)\)\z/) do
assert_queries_match(/WHERE \(#{Regexp.escape(author_id)} IN \('1'\)\)\z/) do
assert_equal [david], only_david.merge(only_david)
end
assert_sql(/WHERE \(#{Regexp.escape(author_id)} IN \('1'\)\)\z/) do
assert_queries_match(/WHERE \(#{Regexp.escape(author_id)} IN \('1'\)\)\z/) do
assert_deprecated(ActiveRecord.deprecator) do
assert_equal [david], only_david.merge(only_david, rewhere: true)
end
end
else
assert_sql(/WHERE \(#{Regexp.escape(author_id)} IN \(1\)\)\z/) do
assert_queries_match(/WHERE \(#{Regexp.escape(author_id)} IN \(1\)\)\z/) do
assert_equal [david], only_david.merge(only_david)
end
assert_sql(/WHERE \(#{Regexp.escape(author_id)} IN \(1\)\)\z/) do
assert_queries_match(/WHERE \(#{Regexp.escape(author_id)} IN \(1\)\)\z/) do
assert_deprecated(ActiveRecord.deprecator) do
assert_equal [david], only_david.merge(only_david, rewhere: true)
end
@ -298,7 +298,7 @@ def test_relation_merging_with_locks
def test_relation_merging_with_preload
[Post.all.merge(Post.preload(:author)), Post.preload(:author).merge(Post.all)].each do |posts|
assert_queries(2) { assert posts.first.author }
assert_queries_count(2) { assert posts.first.author }
end
end
@ -318,7 +318,7 @@ def test_relation_merging_with_skip_query_cache
end
def test_relation_merging_with_association
assert_queries(2) do # one for loading post, and another one merged query
assert_queries_count(2) do # one for loading post, and another one merged query
post = Post.where(body: "Such a lovely day").first
comments = Comment.where(body: "Thank you for the welcome").merge(post.comments)
assert_equal 1, comments.count
@ -372,30 +372,30 @@ def test_merging_with_order_without_binds
end
def test_merging_annotations_respects_merge_order
assert_sql(%r{/\* foo \*/ /\* bar \*/}) do
assert_queries_match(%r{/\* foo \*/ /\* bar \*/}) do
Post.annotate("foo").merge(Post.annotate("bar")).first
end
assert_sql(%r{/\* bar \*/ /\* foo \*/}) do
assert_queries_match(%r{/\* bar \*/ /\* foo \*/}) do
Post.annotate("bar").merge(Post.annotate("foo")).first
end
assert_sql(%r{/\* foo \*/ /\* bar \*/ /\* baz \*/ /\* qux \*/}) do
assert_queries_match(%r{/\* foo \*/ /\* bar \*/ /\* baz \*/ /\* qux \*/}) do
Post.annotate("foo").annotate("bar").merge(Post.annotate("baz").annotate("qux")).first
end
end
def test_merging_duplicated_annotations
posts = Post.annotate("foo")
assert_sql(%r{FROM #{Regexp.escape(Post.quoted_table_name)} /\* foo \*/\z}) do
assert_queries_match(%r{FROM #{Regexp.escape(Post.quoted_table_name)} /\* foo \*/\z}) do
posts.merge(posts).uniq!(:annotate).to_a
end
assert_sql(%r{FROM #{Regexp.escape(Post.quoted_table_name)} /\* foo \*/\z}) do
assert_queries_match(%r{FROM #{Regexp.escape(Post.quoted_table_name)} /\* foo \*/\z}) do
posts.merge(posts).to_a
end
assert_sql(%r{FROM #{Regexp.escape(Post.quoted_table_name)} /\* foo \*/ /\* bar \*/\z}) do
assert_queries_match(%r{FROM #{Regexp.escape(Post.quoted_table_name)} /\* foo \*/ /\* bar \*/\z}) do
Post.annotate("foo").merge(Post.annotate("bar")).merge(posts).to_a
end
assert_sql(%r{FROM #{Regexp.escape(Post.quoted_table_name)} /\* bar \*/ /\* foo \*/\z}) do
assert_queries_match(%r{FROM #{Regexp.escape(Post.quoted_table_name)} /\* bar \*/ /\* foo \*/\z}) do
Post.annotate("bar").merge(Post.annotate("foo")).merge(posts).to_a
end
end

@ -322,7 +322,7 @@ def test_update_all_doesnt_ignore_order
assert_not test_update_with_order_succeeds.call("id ASC")
else
# test that we're failing because the current Arel's engine doesn't support UPDATE ORDER BY queries is using subselects instead
assert_sql(/\AUPDATE .+ \(SELECT .* ORDER BY id DESC\)\z/i) do
assert_queries_match(/\AUPDATE .+ \(SELECT .* ORDER BY id DESC\)\z/i) do
test_update_with_order_succeeds.call("id DESC")
end
end

@ -418,7 +418,7 @@ def test_where_on_association_with_custom_primary_key_with_relation
def test_where_on_association_with_relation_performs_subselect_not_two_queries
author = authors(:david)
assert_queries(1) do
assert_queries_count(1) do
Essay.where(writer: Author.where(id: author.id)).to_a
end
end

@ -331,14 +331,14 @@ def test_relation_with_annotation_includes_comment_in_to_sql
def test_relation_with_annotation_includes_comment_in_sql
post_with_annotation = Post.where(id: 1).annotate("foo")
assert_sql(%r{/\* foo \*/}) do
assert_queries_match(%r{/\* foo \*/}) do
assert post_with_annotation.first, "record should be found"
end
end
def test_relation_with_annotation_chains_sql_comments
post_with_annotation = Post.where(id: 1).annotate("foo").annotate("bar")
assert_sql(%r{/\* foo \*/ /\* bar \*/}) do
assert_queries_match(%r{/\* foo \*/ /\* bar \*/}) do
assert post_with_annotation.first, "record should be found"
end
end
@ -351,7 +351,7 @@ def test_relation_with_annotation_filters_sql_comment_delimiters
def test_relation_with_annotation_includes_comment_in_count_query
post_with_annotation = Post.annotate("foo")
all_count = Post.all.to_a.count
assert_sql(%r{/\* foo \*/}) do
assert_queries_match(%r{/\* foo \*/}) do
assert_equal all_count, post_with_annotation.count
end
end
@ -421,25 +421,25 @@ def test_skip_preloading_after_arel_has_been_generated
end
test "no queries on empty IN" do
assert_queries(0) do
assert_queries_count(0) do
Post.where(id: []).load
end
end
test "can unscope empty IN" do
assert_queries(1) do
assert_queries_count(1) do
Post.where(id: []).unscope(where: :id).load
end
end
test "no queries on empty relation exists?" do
assert_queries(0) do
assert_queries_count(0) do
Post.where(id: []).exists?(123)
end
end
test "no queries on empty condition exists?" do
assert_queries(0) do
assert_queries_count(0) do
Post.all.exists?(id: [])
end
end

@ -98,7 +98,7 @@ def test_loaded_all
assert_not_predicate topics, :loaded?
assert_not_predicate topics, :loaded
assert_queries(1) do
assert_queries_count(1) do
2.times { assert_equal 5, topics.to_a.size }
end
@ -109,7 +109,7 @@ def test_loaded_all
def test_scoped_first
topics = Topic.all.order("id ASC")
assert_queries(1) do
assert_queries_count(1) do
2.times { assert_equal "The First Topic", topics.first.title }
end
@ -153,7 +153,7 @@ def test_first_get_more_than_available
def test_reload
topics = Topic.all
assert_queries(1) do
assert_queries_count(1) do
2.times { topics.to_a }
end
@ -162,7 +162,7 @@ def test_reload
original_size = topics.to_a.size
Topic.create! title: "fake"
assert_queries(1) { topics.reload }
assert_queries_count(1) { topics.reload }
assert_equal original_size + 1, topics.size
assert_predicate topics, :loaded?
end
@ -614,27 +614,27 @@ def test_eager_association_loading_of_stis_with_multiple_references
end
def test_find_with_preloaded_associations
assert_queries(2) do
assert_queries_count(2) do
posts = Post.preload(:comments).order("posts.id")
assert posts.first.comments.first
end
assert_queries(2) do
assert_queries_count(2) do
posts = Post.preload(:comments).order("posts.id")
assert posts.first.comments.first
end
assert_queries(2) do
assert_queries_count(2) do
posts = Post.preload(:author).order("posts.id")
assert posts.first.author
end
assert_queries(2) do
assert_queries_count(2) do
posts = Post.preload(:author).order("posts.id")
assert posts.first.author
end
assert_queries(3) do
assert_queries_count(3) do
posts = Post.preload(:author, :comments).order("posts.id")
assert posts.first.author
assert posts.first.comments.first
@ -642,36 +642,36 @@ def test_find_with_preloaded_associations
end
def test_preload_applies_to_all_chained_preloaded_scopes
assert_queries(3) do
assert_queries_count(3) do
post = Post.with_comments.with_tags.first
assert post
end
end
def test_extracted_association
relation_authors = assert_queries(2) { Post.all.extract_associated(:author) }
root_authors = assert_queries(2) { Post.extract_associated(:author) }
relation_authors = assert_queries_count(2) { Post.all.extract_associated(:author) }
root_authors = assert_queries_count(2) { Post.extract_associated(:author) }
assert_equal relation_authors, root_authors
assert_equal Post.all.collect(&:author), relation_authors
end
def test_find_with_included_associations
assert_queries(2) do
assert_queries_count(2) do
posts = Post.includes(:comments).order("posts.id")
assert posts.first.comments.first
end
assert_queries(2) do
assert_queries_count(2) do
posts = Post.all.includes(:comments).order("posts.id")
assert posts.first.comments.first
end
assert_queries(2) do
assert_queries_count(2) do
posts = Post.includes(:author).order("posts.id")
assert posts.first.author
end
assert_queries(3) do
assert_queries_count(3) do
posts = Post.includes(:author, :comments).order("posts.id")
assert posts.first.author
assert posts.first.comments.first
@ -902,17 +902,17 @@ def test_typecasting_where_with_array
def test_find_all_using_where_with_relation
david = authors(:david)
assert_queries(1) {
assert_queries_count(1) {
relation = Author.where(id: Author.where(id: david.id))
assert_equal [david], relation.to_a
}
assert_queries(1) {
assert_queries_count(1) {
relation = Author.where("id in (?)", Author.where(id: david).select(:id))
assert_equal [david], relation.to_a
}
assert_queries(1) do
assert_queries_count(1) do
relation = Author.where("id in (:author_ids)", author_ids: Author.where(id: david).select(:id))
assert_equal [david], relation.to_a
end
@ -922,17 +922,17 @@ def test_find_all_using_where_with_relation_with_bound_values
david = authors(:david)
davids_posts = david.posts.order(:id).to_a
assert_queries(1) do
assert_queries_count(1) do
relation = Post.where(id: david.posts.select(:id))
assert_equal davids_posts, relation.order(:id).to_a
end
assert_queries(1) do
assert_queries_count(1) do
relation = Post.where("id in (?)", david.posts.select(:id))
assert_equal davids_posts, relation.order(:id).to_a, "should process Relation as bind variables"
end
assert_queries(1) do
assert_queries_count(1) do
relation = Post.where("id in (:post_ids)", post_ids: david.posts.select(:id))
assert_equal davids_posts, relation.order(:id).to_a, "should process Relation as named bind variables"
end
@ -940,7 +940,7 @@ def test_find_all_using_where_with_relation_with_bound_values
def test_find_all_using_where_with_relation_and_alternate_primary_key
cool_first = minivans(:cool_first)
assert_queries(1) {
assert_queries_count(1) {
relation = Minivan.where(minivan_id: Minivan.where(name: cool_first.name))
assert_equal [cool_first], relation.to_a
}
@ -966,7 +966,7 @@ def test_find_all_using_where_with_relation_does_not_alter_select_values
subquery = Author.where(id: david.id)
assert_queries(1) {
assert_queries_count(1) {
relation = Author.where(id: subquery)
assert_equal [david], relation.to_a
}
@ -976,7 +976,7 @@ def test_find_all_using_where_with_relation_does_not_alter_select_values
def test_find_all_using_where_with_relation_with_joins
david = authors(:david)
assert_queries(1) {
assert_queries_count(1) {
relation = Author.where(id: Author.joins(:posts).where(id: david.id))
assert_equal [david], relation.to_a
}
@ -984,7 +984,7 @@ def test_find_all_using_where_with_relation_with_joins
def test_find_all_using_where_with_relation_with_select_to_build_subquery
david = authors(:david)
assert_queries(1) {
assert_queries_count(1) {
relation = Author.where(name: Author.where(id: david.id).select(:name))
assert_equal [david], relation.to_a
}
@ -1059,33 +1059,33 @@ def test_count_with_distinct
def test_size_with_distinct
posts = Post.distinct.select(:author_id, :comments_count)
assert_queries(1) { assert_equal 8, posts.size }
assert_queries(1) { assert_equal 8, posts.load.size }
assert_queries_count(1) { assert_equal 8, posts.size }
assert_queries_count(1) { assert_equal 8, posts.load.size }
end
def test_size_with_eager_loading_and_custom_order
posts = Post.includes(:comments).order("comments.id")
assert_queries(1) { assert_equal 11, posts.size }
assert_queries(1) { assert_equal 11, posts.load.size }
assert_queries_count(1) { assert_equal 11, posts.size }
assert_queries_count(1) { assert_equal 11, posts.load.size }
end
def test_size_with_eager_loading_and_custom_select_and_order
posts = Post.includes(:comments).order("comments.id").select(:type)
assert_queries(1) { assert_equal 11, posts.size }
assert_queries(1) { assert_equal 11, posts.load.size }
assert_queries_count(1) { assert_equal 11, posts.size }
assert_queries_count(1) { assert_equal 11, posts.load.size }
end
def test_size_with_eager_loading_and_custom_order_and_distinct
posts = Post.includes(:comments).order("comments.id").distinct
assert_queries(1) { assert_equal 11, posts.size }
assert_queries(1) { assert_equal 11, posts.load.size }
assert_queries_count(1) { assert_equal 11, posts.size }
assert_queries_count(1) { assert_equal 11, posts.load.size }
end
def test_size_with_eager_loading_and_manual_distinct_select_and_custom_order
accounts = Account.select("DISTINCT accounts.firm_id").order("accounts.firm_id")
assert_queries(1) { assert_equal 5, accounts.size }
assert_queries(1) { assert_equal 5, accounts.load.size }
assert_queries_count(1) { assert_equal 5, accounts.size }
assert_queries_count(1) { assert_equal 5, accounts.load.size }
end
def test_count_explicit_columns
@ -1110,7 +1110,7 @@ def test_multiple_selects
def test_size
posts = Post.all
assert_queries(1) { assert_equal 11, posts.size }
assert_queries_count(1) { assert_equal 11, posts.size }
assert_not_predicate posts, :loaded?
best_posts = posts.where(comments_count: 0)
@ -1121,7 +1121,7 @@ def test_size
def test_size_with_limit
posts = Post.limit(10)
assert_queries(1) { assert_equal 10, posts.size }
assert_queries_count(1) { assert_equal 10, posts.size }
assert_not_predicate posts, :loaded?
best_posts = posts.where(comments_count: 0)
@ -1156,11 +1156,11 @@ def test_count_complex_chained_relations
def test_empty
posts = Post.all
assert_queries(1) { assert_equal false, posts.empty? }
assert_queries_count(1) { assert_equal false, posts.empty? }
assert_not_predicate posts, :loaded?
no_posts = posts.where(title: "")
assert_queries(1) { assert_equal true, no_posts.empty? }
assert_queries_count(1) { assert_equal true, no_posts.empty? }
assert_not_predicate no_posts, :loaded?
best_posts = posts.where(comments_count: 0)
@ -1171,18 +1171,18 @@ def test_empty
def test_empty_complex_chained_relations
posts = Post.select("comments_count").where("id is not null").group("author_id").where("legacy_comments_count > 0")
assert_queries(1) { assert_equal false, posts.empty? }
assert_queries_count(1) { assert_equal false, posts.empty? }
assert_not_predicate posts, :loaded?
no_posts = posts.where(title: "")
assert_queries(1) { assert_equal true, no_posts.empty? }
assert_queries_count(1) { assert_equal true, no_posts.empty? }
assert_not_predicate no_posts, :loaded?
end
def test_any
posts = Post.all
assert_queries(3) do
assert_queries_count(3) do
assert_predicate posts, :any? # Uses COUNT()
assert_not_predicate posts.where(id: nil), :any?
@ -1199,7 +1199,7 @@ def test_any
def test_many
posts = Post.all
assert_queries(2) do
assert_queries_count(2) do
assert_predicate posts, :many? # Uses COUNT()
assert posts.many? { |p| p.id > 0 }
assert_not posts.many? { |p| p.id < 2 }
@ -1221,13 +1221,13 @@ def test_many_with_limits
def test_none?
posts = Post.all
assert_queries(1) do
assert_queries_count(1) do
assert_not posts.none? # Uses COUNT()
end
assert_not_predicate posts, :loaded?
assert_queries(1) do
assert_queries_count(1) do
assert posts.none? { |p| p.id < 0 }
assert_not posts.none? { |p| p.id == 1 }
@ -1240,13 +1240,13 @@ def test_none?
def test_one
posts = Post.all
assert_queries(1) do
assert_queries_count(1) do
assert_not posts.one? # Uses COUNT()
end
assert_not_predicate posts, :loaded?
assert_queries(1) do
assert_queries_count(1) do
assert_not posts.one? { |p| p.id < 3 }
assert posts.one? { |p| p.id == 1 }
@ -1259,7 +1259,7 @@ def test_one
def test_one_with_destroy
posts = Post.all
assert_queries(1) do
assert_queries_count(1) do
assert_not posts.one?
end
@ -1786,10 +1786,10 @@ def test_distinct
query = Tag.select(:name).where(id: [tag1.id, tag2.id])
assert_equal ["Foo", "Foo"], query.map(&:name)
assert_sql(/DISTINCT/) do
assert_queries_match(/DISTINCT/) do
assert_equal ["Foo"], query.distinct.map(&:name)
end
assert_sql(/DISTINCT/) do
assert_queries_match(/DISTINCT/) do
assert_equal ["Foo"], query.distinct(true).map(&:name)
end
assert_equal ["Foo", "Foo"], query.distinct(true).distinct(false).map(&:name)
@ -1973,7 +1973,7 @@ def test_presence
topics = Topic.all
# the first query is triggered because there are no topics yet.
assert_queries(1) { assert_predicate topics, :present? }
assert_queries_count(1) { assert_predicate topics, :present? }
# checking if there are topics is used before you actually display them,
# thus it shouldn't invoke an extra count query.
@ -1986,7 +1986,7 @@ def test_presence
assert_no_queries { topics.each }
# count always trigger the COUNT query.
assert_queries(1) { topics.count }
assert_queries_count(1) { topics.count }
assert_predicate topics, :loaded?
end
@ -2026,7 +2026,7 @@ def test_destroy_by
end
test "find_by doesn't have implicit ordering" do
assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by(author_id: 2) }
assert_queries_match(/^((?!ORDER).)*$/) { Post.all.find_by(author_id: 2) }
end
test "find_by requires at least one argument" do
@ -2046,7 +2046,7 @@ def test_destroy_by
end
test "find_by! doesn't have implicit ordering" do
assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by!(author_id: 2) }
assert_queries_match(/^((?!ORDER).)*$/) { Post.all.find_by!(author_id: 2) }
end
test "find_by! raises RecordNotFound if the record is missing" do
@ -2114,13 +2114,13 @@ def test_destroy_by
end
test "relations don't load all records in #inspect" do
assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) do
assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) do
Post.all.inspect
end
end
test "loading query is annotated in #inspect" do
assert_sql(%r(/\* loading for inspect \*/)) do
assert_queries_match(%r(/\* loading for inspect \*/)) do
Post.all.inspect
end
end
@ -2145,13 +2145,13 @@ def test_destroy_by
end
test "relations don't load all records in #pretty_print" do
assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) do
assert_queries_match(/LIMIT|ROWNUM <=|FETCH FIRST/) do
PP.pp Post.all, StringIO.new # avoid outputting.
end
end
test "loading query is annotated in #pretty_print" do
assert_sql(%r(/\* loading for pp \*/)) do
assert_queries_match(%r(/\* loading for pp \*/)) do
PP.pp Post.all, StringIO.new # avoid outputting.
end
end
@ -2187,7 +2187,7 @@ def test_destroy_by
test "#load" do
relation = Post.all
assert_queries(1) do
assert_queries_count(1) do
assert_equal relation, relation.load
end
assert_no_queries { relation.to_a }
@ -2393,12 +2393,12 @@ def test_find_by_with_take_memoization
test "#skip_query_cache!" do
Post.cache do
assert_queries(1) do
assert_queries_count(1) do
Post.all.load
Post.all.load
end
assert_queries(2) do
assert_queries_count(2) do
Post.all.skip_query_cache!.load
Post.all.skip_query_cache!.load
end
@ -2407,12 +2407,12 @@ def test_find_by_with_take_memoization
test "#skip_query_cache! with an eager load" do
Post.cache do
assert_queries(1) do
assert_queries_count(1) do
Post.eager_load(:comments).load
Post.eager_load(:comments).load
end
assert_queries(2) do
assert_queries_count(2) do
Post.eager_load(:comments).skip_query_cache!.load
Post.eager_load(:comments).skip_query_cache!.load
end
@ -2421,12 +2421,12 @@ def test_find_by_with_take_memoization
test "#skip_query_cache! with a preload" do
Post.cache do
assert_queries(2) do
assert_queries_count(2) do
Post.preload(:comments).load
Post.preload(:comments).load
end
assert_queries(4) do
assert_queries_count(4) do
Post.preload(:comments).skip_query_cache!.load
Post.preload(:comments).skip_query_cache!.load
end

@ -91,11 +91,11 @@ def self.search_as_method(term)
}
end
assert_sql(/LIKE '20!% !_reduction!_!!'/) do
assert_queries_match(/LIKE '20!% !_reduction!_!!'/) do
searchable_post.search_as_method("20% _reduction_!").to_a
end
assert_sql(/LIKE '20!% !_reduction!_!!'/) do
assert_queries_match(/LIKE '20!% !_reduction!_!!'/) do
searchable_post.search_as_scope("20% _reduction_!").to_a
end
end

@ -84,14 +84,14 @@ def test_combined_default_scope_without_and_with_all_queries_works
Mentor.create!
klass = DeveloperWithIncludedMentorDefaultScopeNotAllQueriesAndDefaultScopeFirmWithAllQueries
create_sql = capture_sql { klass.create!(name: "Steve") }.first
create_sql = capture_sql { klass.create!(name: "Steve") }.second
assert_match(/mentor_id/, create_sql)
assert_match(/firm_id/, create_sql)
developer = klass.find_by!(name: "Steve")
update_sql = capture_sql { developer.update(name: "Stephen") }.first
update_sql = capture_sql { developer.update(name: "Stephen") }.second
assert_no_match(/mentor_id/, update_sql)
assert_match(/firm_id/, update_sql)
@ -99,14 +99,14 @@ def test_combined_default_scope_without_and_with_all_queries_works
def test_default_scope_runs_on_create
Mentor.create!
create_sql = capture_sql { DeveloperwithDefaultMentorScopeNot.create!(name: "Eileen") }.first
create_sql = capture_sql { DeveloperwithDefaultMentorScopeNot.create!(name: "Eileen") }.second
assert_match(/mentor_id/, create_sql)
end
def test_default_scope_with_all_queries_runs_on_create
Mentor.create!
create_sql = capture_sql { DeveloperWithDefaultMentorScopeAllQueries.create!(name: "Eileen") }.first
create_sql = capture_sql { DeveloperWithDefaultMentorScopeAllQueries.create!(name: "Eileen") }.second
assert_match(/mentor_id/, create_sql)
end
@ -151,7 +151,7 @@ def test_default_scope_doesnt_run_on_update
def test_default_scope_with_all_queries_runs_on_update
Mentor.create!
dev = DeveloperWithDefaultMentorScopeAllQueries.create!(name: "Eileen")
update_sql = capture_sql { dev.update!(name: "Not Eileen") }.first
update_sql = capture_sql { dev.update!(name: "Not Eileen") }.second
assert_match(/mentor_id/, update_sql)
end
@ -197,7 +197,7 @@ def test_default_scope_doesnt_run_on_destroy
def test_default_scope_with_all_queries_runs_on_destroy
Mentor.create!
dev = DeveloperWithDefaultMentorScopeAllQueries.create!(name: "Eileen")
destroy_sql = capture_sql { dev.destroy }.first
destroy_sql = capture_sql { dev.destroy }.second
assert_match(/mentor_id/, destroy_sql)
end

@ -24,7 +24,7 @@ def test_implements_enumerable
def test_found_items_are_cached
all_posts = Topic.base
assert_queries(1) do
assert_queries_count(1) do
all_posts.collect { true }
all_posts.collect { true }
end
@ -227,7 +227,7 @@ def test_first_and_last_should_not_use_query_when_results_are_loaded
def test_empty_should_not_load_results
topics = Topic.base
assert_queries(2) do
assert_queries_count(2) do
topics.empty? # use count query
topics.load # force load
topics.empty? # use loaded (no query)
@ -236,7 +236,7 @@ def test_empty_should_not_load_results
def test_any_should_not_load_results
topics = Topic.base
assert_queries(2) do
assert_queries_count(2) do
topics.any? # use count query
topics.load # force load
topics.any? # use loaded (no query)
@ -245,7 +245,7 @@ def test_any_should_not_load_results
def test_any_should_call_proxy_found_if_using_a_block
topics = Topic.base
assert_queries(1) do
assert_queries_count(1) do
assert_not_called(topics, :empty?) do
topics.any? { true }
end
@ -266,7 +266,7 @@ def test_model_class_should_respond_to_any
def test_many_should_not_load_results
topics = Topic.base
assert_queries(2) do
assert_queries_count(2) do
topics.many? # use count query
topics.load # force load
topics.many? # use loaded (no query)
@ -275,7 +275,7 @@ def test_many_should_not_load_results
def test_many_should_call_proxy_found_if_using_a_block
topics = Topic.base
assert_queries(1) do
assert_queries_count(1) do
assert_not_called(topics, :size) do
topics.many? { true }
end
@ -428,8 +428,8 @@ def test_should_use_where_in_query_for_scope
def test_size_should_use_count_when_results_are_not_loaded
topics = Topic.base
assert_queries(1) do
assert_sql(/COUNT/i) { topics.size }
assert_queries_count(1) do
assert_queries_match(/COUNT/i) { topics.size }
end
end
@ -495,11 +495,11 @@ def test_nested_scoping
def test_scopes_batch_finders
assert_equal 4, Topic.approved.count
assert_queries(5) do
assert_queries_count(5) do
Topic.approved.find_each(batch_size: 1) { |t| assert_predicate t, :approved? }
end
assert_queries(3) do
assert_queries_count(3) do
Topic.approved.find_in_batches(batch_size: 2) do |group|
group.each { |t| assert_predicate t, :approved? }
end
@ -528,7 +528,7 @@ def test_index_on_scope
end
def test_nested_scopes_queries_size
assert_queries(1) do
assert_queries_count(1) do
Topic.approved.by_lifo.replied.written_before(Time.now).to_a
end
end
@ -540,7 +540,7 @@ def test_scopes_are_cached_on_associations
post = posts(:welcome)
Post.cache do
assert_queries(1) { post.comments.containing_the_letter_e.to_a }
assert_queries_count(1) { post.comments.containing_the_letter_e.to_a }
assert_no_queries { post.comments.containing_the_letter_e.to_a }
end
end
@ -549,10 +549,10 @@ def test_scopes_with_arguments_are_cached_on_associations
post = posts(:welcome)
Post.cache do
one = assert_queries(1) { post.comments.limit_by(1).to_a }
one = assert_queries_count(1) { post.comments.limit_by(1).to_a }
assert_equal 1, one.size
two = assert_queries(1) { post.comments.limit_by(2).to_a }
two = assert_queries_count(1) { post.comments.limit_by(2).to_a }
assert_equal 2, two.size
assert_no_queries { post.comments.limit_by(1).to_a }
@ -622,7 +622,7 @@ def test_scope_with_annotation
scope :including_annotate_in_scope, Proc.new { annotate("from-scope") }
end
assert_sql(%r{/\* from-scope \*/}) do
assert_queries_match(%r{/\* from-scope \*/}) do
assert_equal Topic.including_annotate_in_scope.to_a, Topic.all.to_a
end
end

@ -156,7 +156,7 @@ def test_scoped_count
def test_scoped_find_with_annotation
Developer.annotate("scoped").scoping do
developer = nil
assert_sql(%r{/\* scoped \*/}) do
assert_queries_match(%r{/\* scoped \*/}) do
developer = Developer.where("name = 'David'").first
end
assert_equal "David", developer.name
@ -370,7 +370,7 @@ def test_scoping_applies_to_update_with_all_queries
end
Author.where(organization_id: 1).scoping(all_queries: true) do
update_scoped_sql = capture_sql { dev.update(name: "Not Eileen") }.first
update_scoped_sql = capture_sql { dev.update(name: "Not Eileen") }.second
assert_match(/organization_id/, update_scoped_sql)
end
end

@ -5,6 +5,7 @@
require "active_support/testing/autorun"
require "active_support/testing/method_call_assertions"
require "active_support/testing/stream"
require "active_record/testing/query_assertions"
require "active_record/fixtures"
require "cases/validations_repair_helper"
@ -20,6 +21,7 @@ module ActiveRecord
class TestCase < ActiveSupport::TestCase # :nodoc:
include ActiveSupport::Testing::MethodCallAssertions
include ActiveSupport::Testing::Stream
include ActiveRecord::Assertions::QueryAssertions
include ActiveRecord::TestFixtures
include ActiveRecord::ValidationsRepairHelper
include AdapterHelper
@ -35,45 +37,34 @@ def create_fixtures(*fixture_set_names, &block)
ActiveRecord::FixtureSet.create_fixtures(ActiveRecord::TestCase.fixture_paths, fixture_set_names, fixture_class_names, &block)
end
def teardown
SQLCounter.clear_log
end
def capture_sql
ActiveRecord::Base.connection.materialize_transactions
SQLCounter.clear_log
yield
SQLCounter.log.dup
end
def assert_sql(*patterns_to_match, &block)
_assert_nothing_raised_or_warn("assert_sql") { capture_sql(&block) }
failed_patterns = []
patterns_to_match.each do |pattern|
failed_patterns << pattern unless SQLCounter.log_all.any? { |sql| pattern === sql }
def capture_sql(include_schema: false)
counter = SQLCounter.new
ActiveSupport::Notifications.subscribed(counter, "sql.active_record") do
yield
if include_schema
counter.log_all
else
counter.log
end
end
assert_predicate failed_patterns, :empty?, "Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} not found.#{SQLCounter.log.size == 0 ? '' : "\nQueries:\n#{SQLCounter.log.join("\n")}"}"
end
def assert_queries(num = 1, options = {}, &block)
ignore_none = options.fetch(:ignore_none) { num == :any }
ActiveRecord::Base.connection.materialize_transactions
SQLCounter.clear_log
x = _assert_nothing_raised_or_warn("assert_queries", &block)
the_log = ignore_none ? SQLCounter.log_all : SQLCounter.log
if num == :any
assert_operator the_log.size, :>=, 1, "1 or more queries expected, but none were executed."
else
mesg = "#{the_log.size} instead of #{num} queries were executed.#{the_log.size == 0 ? '' : "\nQueries:\n#{the_log.join("\n")}"}"
assert_equal num, the_log.size, mesg
# Redefine existing assertion method to explicitly not materialize transactions.
def assert_queries_match(match, count: nil, include_schema: false, &block)
counter = SQLCounter.new
ActiveSupport::Notifications.subscribed(counter, "sql.active_record") do
result = _assert_nothing_raised_or_warn("assert_queries_match", &block)
queries = include_schema ? counter.log_all : counter.log
matched_queries = queries.select { |query| match === query }
if count
assert_equal count, matched_queries.size, "#{matched_queries.size} instead of #{count} queries were executed.#{queries.empty? ? '' : "\nQueries:\n#{queries.join("\n")}"}"
else
assert_operator matched_queries.size, :>=, 1, "1 or more queries expected, but none were executed.#{queries.empty? ? '' : "\nQueries:\n#{queries.join("\n")}"}"
end
result
end
x
end
def assert_no_queries(options = {}, &block)
options.reverse_merge! ignore_none: true
assert_queries(0, options, &block)
end
def assert_column(model, column_name, msg = nil)
@ -280,23 +271,4 @@ def self.run(*args)
super if current_adapter?(:SQLite3Adapter)
end
end
class SQLCounter
class << self
attr_accessor :ignored_sql, :log, :log_all
def clear_log; self.log = []; self.log_all = []; end
end
clear_log
def call(name, start, finish, message_id, values)
return if values[:cached]
sql = values[:sql]
self.class.log_all << sql
self.class.log << sql unless ["SCHEMA", "TRANSACTION"].include? values[:name]
end
end
ActiveSupport::Notifications.subscribe("sql.active_record", SQLCounter.new)
end

@ -1338,13 +1338,13 @@ def test_empty_transaction_is_not_materialized
end
def test_unprepared_statement_materializes_transaction
assert_sql(/BEGIN/i, /COMMIT/i) do
assert_queries_match(/BEGIN|COMMIT/i, include_schema: true) do
Topic.transaction { Topic.where("1=1").first }
end
end
def test_nested_transactions_skip_excess_savepoints
capture_sql do
actual_queries = capture_sql(include_schema: true) do
# RealTransaction (begin..commit)
Topic.transaction(requires_new: true) do
# ResetParentTransaction (no queries)
@ -1362,8 +1362,6 @@ def test_nested_transactions_skip_excess_savepoints
end
end
actual_queries = ActiveRecord::SQLCounter.log_all
expected_queries = [
/BEGIN/i,
/DELETE/i,
@ -1383,7 +1381,7 @@ def test_nested_transactions_skip_excess_savepoints
def test_nested_transactions_after_disable_lazy_transactions
Topic.connection.disable_lazy_transactions!
capture_sql do
actual_queries = capture_sql(include_schema: true) do
# RealTransaction (begin..commit)
Topic.transaction(requires_new: true) do
# ResetParentTransaction (no queries)
@ -1401,8 +1399,6 @@ def test_nested_transactions_after_disable_lazy_transactions
end
end
actual_queries = ActiveRecord::SQLCounter.log_all
expected_queries = [
/BEGIN/i,
/DELETE/i,
@ -1422,7 +1418,7 @@ def test_nested_transactions_after_disable_lazy_transactions
def test_prepared_statement_materializes_transaction
Topic.first
assert_sql(/BEGIN/i, /COMMIT/i) do
assert_queries_match(/BEGIN|COMMIT/i, include_schema: true) do
Topic.transaction { Topic.first }
end
end
@ -1445,7 +1441,7 @@ def test_raising_does_not_materialize_transaction
end
def test_accessing_raw_connection_materializes_transaction
assert_sql(/BEGIN/i, /COMMIT/i) do
assert_queries_match(/BEGIN|COMMIT/i, include_schema: true) do
Topic.transaction { Topic.connection.raw_connection }
end
end
@ -1453,7 +1449,7 @@ def test_accessing_raw_connection_materializes_transaction
def test_accessing_raw_connection_disables_lazy_transactions
Topic.connection.raw_connection
assert_sql(/BEGIN/i, /COMMIT/i) do
assert_queries_match(/BEGIN|COMMIT/i, include_schema: true) do
Topic.transaction { }
end
end
@ -1469,7 +1465,7 @@ def test_checking_in_connection_reenables_lazy_transactions
end
def test_transactions_can_be_manually_materialized
assert_sql(/BEGIN/i, /COMMIT/i) do
assert_queries_match(/BEGIN|COMMIT/i, include_schema: true) do
Topic.transaction do
Topic.connection.materialize_transactions
end

@ -654,7 +654,7 @@ def test_new_record
@connection.add_index(:topics, :title, unique: true, name: :topics_index)
t = Topic.new(title: "abc")
assert_queries(1) do
assert_queries_count(1) do
t.valid?
end
end
@ -665,7 +665,7 @@ def test_changing_non_unique_attribute
t = Topic.create!(title: "abc")
t.author_name = "John"
assert_no_queries(ignore_none: false) do
assert_no_queries do
t.valid?
end
end
@ -676,7 +676,7 @@ def test_changing_unique_attribute
t = Topic.create!(title: "abc")
t.title = "abc v2"
assert_queries(1) do
assert_queries_count(1) do
t.valid?
end
end
@ -688,7 +688,7 @@ def test_changing_non_unique_attribute_and_unique_attribute_is_nil
t = Topic.create!
assert_nil t.title
t.author_name = "John"
assert_queries(1) do
assert_queries_count(1) do
t.valid?
end
end
@ -699,7 +699,7 @@ def test_conditions
t = Topic.create!(title: "abc")
t.title = "abc v2"
assert_queries(1) do
assert_queries_count(1) do
t.valid?
end
end
@ -710,7 +710,7 @@ def test_case_sensitive
t = Topic.create!(title: "abc")
t.title = "abc v2"
assert_queries(1) do
assert_queries_count(1) do
t.valid?
end
end
@ -723,7 +723,7 @@ def test_partial_index
t = Topic.create!(title: "abc")
t.author_name = "John"
assert_queries(1) do
assert_queries_count(1) do
t.valid?
end
end
@ -734,7 +734,7 @@ def test_non_unique_index
t = Topic.create!(title: "abc")
t.author_name = "John"
assert_queries(1) do
assert_queries_count(1) do
t.valid?
end
end
@ -745,12 +745,12 @@ def test_scope
t = Topic.create!(title: "abc", author_name: "John")
t.content = "hello world"
assert_no_queries(ignore_none: false) do
assert_no_queries do
t.valid?
end
t.author_name = "Amy"
assert_queries(1) do
assert_queries_count(1) do
t.valid?
end
end
@ -764,12 +764,12 @@ def test_uniqueness_on_relation
t = TopicWithEvent.create!(event: e1)
t.content = "hello world"
assert_no_queries(ignore_none: false) do
assert_no_queries do
t.valid?
end
t.event = e2
assert_queries(1) do
assert_queries_count(1) do
t.valid?
end
ensure
@ -792,12 +792,12 @@ def test_index_of_sublist_of_columns
t = Topic.create!(title: "abc", author_name: "John")
t.content = "hello world"
assert_no_queries(ignore_none: false) do
assert_no_queries do
t.valid?
end
t.author_name = "Amy"
assert_queries(1, ignore_none: false) do
assert_queries_count(1) do
t.valid?
end
end
@ -808,7 +808,7 @@ def test_index_of_columns_list_and_extra_columns
t = Topic.create!(title: "abc", author_name: "John")
t.content = "hello world"
assert_queries(1) do
assert_queries_count(1) do
t.valid?
end
end
@ -821,7 +821,7 @@ def test_expression_index
t = Topic.create!(title: "abc", author_name: "John")
t.content = "hello world"
assert_queries(1) do
assert_queries_count(1) do
t.valid?
end
end

@ -85,7 +85,7 @@ class ActiveStorage::VariantWithRecordTest < ActiveSupport::TestCase
users.reset
assert_no_difference -> { ActiveStorage::VariantRecord.count } do
assert_queries(11) do
assert_queries_count(11) do
# 11 queries:
# users x 1
# attachment (cover photo) x 2
@ -105,9 +105,8 @@ class ActiveStorage::VariantWithRecordTest < ActiveSupport::TestCase
users.reset
assert_no_difference -> { ActiveStorage::VariantRecord.count } do
assert_queries(6) do
# 6 queries:
# users x 1
assert_queries_count(5) do
# 5 queries:
# attachment (cover photos) x 1
# blob for the cover photo x 1
# variant record x 1
@ -144,7 +143,7 @@ class ActiveStorage::VariantWithRecordTest < ActiveSupport::TestCase
user.reload
assert_no_difference -> { ActiveStorage::VariantRecord.count } do
assert_queries(9) do
assert_queries_count(9) do
# 9 queries:
# attachments (vlogs) x 1
# blob x 2
@ -163,7 +162,7 @@ class ActiveStorage::VariantWithRecordTest < ActiveSupport::TestCase
user.reload
assert_no_difference -> { ActiveStorage::VariantRecord.count } do
assert_queries(7) do
assert_queries_count(7) do
# 7 queries:
# attachments (vlogs) x 1
# blob x 1
@ -181,7 +180,7 @@ class ActiveStorage::VariantWithRecordTest < ActiveSupport::TestCase
user.reload
assert_no_difference -> { ActiveStorage::VariantRecord.count } do
assert_queries(5) do
assert_queries_count(5) do
# 5 queries:
# attachments (vlogs) x 1
# blobs for the vlogs x 1
@ -200,7 +199,7 @@ class ActiveStorage::VariantWithRecordTest < ActiveSupport::TestCase
user.reload
assert_no_difference -> { ActiveStorage::VariantRecord.count } do
assert_queries(5) do
assert_queries_count(5) do
# 5 queries:
# attachments (vlogs) x 1
# blobs for the vlogs x 1
@ -219,7 +218,7 @@ class ActiveStorage::VariantWithRecordTest < ActiveSupport::TestCase
user.reload
assert_no_difference -> { ActiveStorage::VariantRecord.count } do
assert_queries(6) do
assert_queries_count(6) do
# 6 queries:
# user x 1
# attachments (vlogs) x 1
@ -244,7 +243,7 @@ class ActiveStorage::VariantWithRecordTest < ActiveSupport::TestCase
# More queries here because we are creating a different variant.
# The second time we load this variant, we are back down to just 3 queries.
assert_queries(9, matcher: /SELECT/) do
assert_queries_match(/SELECT/i, count: 9) do
# 9 queries:
# attachments (vlogs) initial load x 1
# blob x 1 (gets both records)
@ -260,7 +259,7 @@ class ActiveStorage::VariantWithRecordTest < ActiveSupport::TestCase
user.reload
assert_queries(5) do
assert_queries_count(5) do
user.vlogs.with_all_variant_records.each do |vlog|
rep = vlog.representation(resize_to_limit: [200, 200])
rep.processed

@ -362,8 +362,10 @@ Rails adds some custom assertions of its own to the `minitest` framework:
| [`assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)`](https://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html#method-i-assert_generates) | Asserts that the provided options can be used to generate the provided path. This is the inverse of assert_recognizes. The extras parameter is used to tell the request the names and values of additional request parameters that would be in a query string. The message parameter allows you to specify a custom error message for assertion failures.|
| [`assert_response(type, message = nil)`](https://api.rubyonrails.org/classes/ActionDispatch/Assertions/ResponseAssertions.html#method-i-assert_response) | Asserts that the response comes with a specific status code. You can specify `:success` to indicate 200-299, `:redirect` to indicate 300-399, `:missing` to indicate 404, or `:error` to match the 500-599 range. You can also pass an explicit status number or its symbolic equivalent. For more information, see [full list of status codes](https://rubydoc.info/gems/rack/Rack/Utils#HTTP_STATUS_CODES-constant) and how their [mapping](https://rubydoc.info/gems/rack/Rack/Utils#SYMBOL_TO_STATUS_CODE-constant) works.|
| [`assert_redirected_to(options = {}, message=nil)`](https://api.rubyonrails.org/classes/ActionDispatch/Assertions/ResponseAssertions.html#method-i-assert_redirected_to) | Asserts that the response is a redirect to a URL matching the given options. You can also pass named routes such as `assert_redirected_to root_path` and Active Record objects such as `assert_redirected_to @article`.|
|`assert_queries(int, &block)` | Asserts that `&block` generates an `int` number of SQL queries.|
|`assert_queries_count(int, &block)` | Asserts that `&block` generates an `int` number of SQL queries.|
|`assert_no_queries(&block)` | Asserts that `&block` generates no SQL queries.|
|`assert_queries_match(pattern, &block)` | Asserts that `&block` generates SQL queries that match the pattern.|
|`assert_no_queries_match(pattern, &block)` | Asserts that `&block` generates no SQL queries that match the pattern.|
You'll see the usage of some of these assertions in the next chapter.