From 546de0f6c6a91e4e2019f4759098caa5185176e0 Mon Sep 17 00:00:00 2001 From: Ulysse Buonomo Date: Fri, 24 Sep 2021 09:46:54 +0200 Subject: [PATCH] Avoid eager loading in Relation#pretty_print We mimic the behaviour used with `#inspect`, only fetching up to 11 elements if records are not loaded already. Here's the reproduction: ``` require "activerecord" ActiveRecord::Base.establish_connection YOUR_DB_URL_THERE ActiveRecord::Migration.new.tap do |m| m.create_table :foos do |t| t.text :name end end class Foo < ActiveRecord::Base end 100.times { Foo.create(name: "foo#{_1}") } pp Foo.all # loads the whole table. ``` Signed-off-by: Ulysse Buonomo --- activerecord/CHANGELOG.md | 12 +++++++++ activerecord/lib/active_record/relation.rb | 9 +++++-- activerecord/test/cases/relations_test.rb | 29 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index dcad1820c5..0da3b5fd94 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,15 @@ +* Avoid loading every records in `ActiveRecord::Relation#pretty_print` + + ```ruby + # Before + pp Foo.all # Loads the whole table. + + # After + pp Foo.all # Shows 10 items and an ellipsis. + ``` + + *Ulysse Buonomo* + * Change `QueryMethods#in_order_of` to drop records not listed in values. `in_order_of` now filters down to the values provided, to match the behavior of the `Enumerable` version. diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 92082306c0..6d91b64e46 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -773,8 +773,13 @@ module ActiveRecord end end - def pretty_print(q) - q.pp(records) + def pretty_print(pp) + subject = loaded? ? records : annotate("loading for pp") + entries = subject.take([limit_value, 11].compact.min) + + entries[10] = "..." if entries.size == 11 + + pp.pp(entries) end # Returns true if relation is blank. diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 6e1bb26cff..75fa17b9c4 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -2021,6 +2021,35 @@ class RelationTest < ActiveRecord::TestCase end end + test "relations limit the records in #pretty_print at 10" do + relation = Post.limit(11) + out = StringIO.new + PP.pp(relation, out) + assert_equal 10, out.string.scan(/#<\w*Post:/).size + assert out.string.end_with?("\"...\"]\n"), "Did not end with an ellipsis." + end + + test "relations don't load all records in #pretty_print" do + assert_sql(/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 + PP.pp Post.all, StringIO.new # avoid outputting. + end + end + + test "already-loaded relations don't perform a new query in #pretty_print" do + relation = Post.limit(2) + relation.to_a + + assert_no_queries do + PP.pp relation, StringIO.new # avoid outputting. + end + end + test "using a custom table affects the wheres" do post = posts(:welcome)