ruby / debug

Debugging functionality for Ruby
BSD 2-Clause "Simplified" License
1.14k stars 127 forks source link

Add hook for customizing the debug representation of an object #1005

Open amomchilov opened 1 year ago

amomchilov commented 1 year ago

This PR depends on the changes in #1004. Only this last commit of this PR is unique to this change.

Description

I propose we add a hook method that developers can implement in their classes to customize the structural representation of their objects in a debugger. Used judiciously, this has the potential to really improve the clarify of certain types of objects.

I found it particularly useful for container-like objects, like OpenStruct and ActionController::StrongParameters.

Before After
Screenshot 2023-07-28 at 10 12 48 AM Screenshot 2023-07-28 at 10 17 11 AM
example.rb ```ruby require 'ostruct' require 'action_controller' class OpenStruct # Use our hash representation directly, to hide the `@table` clutter. def debug_representation = to_h end class ActionController::Parameters # Flatten the parameters right into the top level of this object's representation. def debug_representation { :@permitted => @permitted, :@logging_context => @logging_context, **@parameters } end end line = OpenStruct.new( start_point: OpenStruct.new(x: 1, y: 2), end_point: OpenStruct.new(x: 3, y: 4), ) params = ActionController::Parameters.new( { person: { name: "Francesco", age: 22, role: "admin" } } ) ```

I chose the spelling #debug_representation, because it's clear and to-the-point, but it's open to ideas.

jabamaus commented 1 year ago

A big +1 for this feature. This would be great. Surprised this wasn't in from the start. Being able to control what's on the debug inspector without overloading to_s and inspect (which may be needed for something else) seems like a very sensible idea.

When are some of these PRs going to get applied? It's been quiet the last few months...

ko1 commented 1 year ago

Could you give us the API specification?

jabamaus commented 1 year ago

I'm not sure what the content of this PR exactly is but what I'd simply like is the ability to define a method on my objects called something like "to_rdbg" (or something I don't really mind) and have rdbg call that preferentially to to_s/inspect. In this way I could have to_s/inspect freed up for just my use and control over what appears in the debug window.

amomchilov commented 1 year ago

@jabamaus @ko1 Ignore the first few commits that come from other branches. This is the relevant commit to this PR: https://github.com/ruby/debug/pull/1005/commits/89427979a16497d27e2f4021ae84f094768627e1

@ko1 The API is really simple: If your object responds to #debug_representation, the debugger will call it and use the result as the representation of your object.

Look closely at the PR description, I put an example.rb that shows an examples for OpenStruct and ActionController::Parameters.

jabamaus commented 1 year ago

Thanks @amomchilov that makes it easier to follow. What will happen if the object being inspected is a BasicObect? BasicObject does not implement respond_to?

amomchilov commented 1 year ago

@jabamaus Please have a look at the implementation. It always uses the Kernel implementation of respond_to?, so that it works even on BasicObject, or any objects with a bad override of #respond_to?.

ko1 commented 1 year ago

@ko1 The API is really simple: If your object responds to #debug_representation, the debugger will call it and use the result as the representation of your object.

Could you explain the specification of #debug_representation?

launchable-app[bot] commented 3 days ago

:white_check_mark: All Tests passed!

:heavy_multiplication_x:no tests failed :heavy_check_mark:669 tests passed(1 flake)