New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid eager loading in Relation#pretty_print #43302
Conversation
Hey @BuonOmo, thanks for contributing to Rails! According to the contributing guides: "you should add an entry to the top of the CHANGELOG of the framework that you modified if you're adding or removing a feature, committing a bug fix, or adding deprecation notices. Refactorings and documentation changes generally should not go to the CHANGELOG." Changes to |
d7ab766
to
6ad3eff
Compare
@p8 I missed that one, sorry... I've added the entry and taken your suggestion 🙂 |
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
@BuonOmo Sorry for the late reply. |
@p8 all done. I've also rolled back to my previous commit: the ellipsis is now within the array rather than just after: Before
After
|
@BuonOmo Nice! |
subject = loaded? ? records : annotate("loading for pp") | ||
entries = subject.take([limit_value, 11].compact.min) | ||
|
||
ellipsis = Class.new { def pretty_print(q); q.text("..."); end }.new |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll be creating this class on every pretty print, we may as well create it once.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reasoning behind creating it every time is that pp
will likely be used in dev env, but not in production, hence we don't really need to define it early. I could memoize it though, but I don't think it has a point, should performance matter in pp
?
Moreover, I don't know if you had the chance to read it but I've tested memory growth related to creating those classes and I doesn't seem so important. I may have overlooked something there ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point, it just felt weird seeing that rather than a clean ellipsis, but whatever!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, looks good!
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 <buonomo.ulysse@gmail.com>
@p8 @gsamokovarov I've applied your change requests, squashed and rebased 🙂 |
Thanks @BuonOmo ! |
…d in collection association. The change in PR rails#43302 introduced a bug where unsaved records are not displayed in pretty_print. The following code will not show unsaved records until this PR is merged. ```ruby post = Post.create! post.comments.build pp(post.comments) #=> expected "[#<Post:0x000000014c0b48a0 ...>]", got "[]" ``` Fixed to call `#load_target` before display as well as `#inspect`.
Summary
We mimic the behaviour used with
#inspect
, only fetching up to 11elements if records are not loaded already.
Here's the issue reproduction:
Other Information
Since I'm not yet fully understanding ruby's handling of these unnammed classes (
Class.new
), I've checked if this was not leaking:And at some point memory stops growing, yet the GC does not get back all the memory. Shall I consider making it a private constant? Or just add a simple string at the end, yet it is less elegant IMHO
Also, is this relevant to AR's changelog ? I've not seen anything related to inspect or pretty_print, hence I've not added any entry