[ruby-core:121558] [Ruby Feature#21219] `Object#inspect` accept a list of instance variables to display
From:
"mame (Yusuke Endoh) via ruby-core" <ruby-core@...>
Date:
2025-04-07 17:37:19 UTC
List:
ruby-core #121558
Issue #21219 has been updated by mame (Yusuke Endoh).
Just FYI, pretty_print already has that mechanism. It allows to control the list of instance variables that should be displayed by defining a method named `pretty_print_instance_variables`.
```ruby
class Foo
def initialize
@pub_1 = :A
@pub_2 = :B
@priv_1 = :secret
@priv_2 = :secret
end
def pretty_print_instance_variables
super - [:@priv_1, :@priv_2]
end
end
pp Foo.new #=> #<Foo:0x00007f319f5077b0 @pub_1=:A, @pub_2=:B>
```
I am not sure how to achieve this with `#inspect`. Should we introduce a method like `#inspect_instance_variables` or something to do the same protocol?
I don't think the keyword argument in `#inspect` is a very good API because specifying the ivar name list outside of the class definition looks a bit unconfortable.
----------------------------------------
Feature #21219: `Object#inspect` accept a list of instance variables to display
https://bugs.ruby-lang.org/issues/21219#change-112584
* Author: byroot (Jean Boussier)
* Status: Open
----------------------------------------
## Context
The default `Object#inspect` implementation is quite useful to have a generic representation of objects in error message and similar places.
However sometimes objects are referencing other objects with a very large `inspect` representation, making error message hard to understand.
In some other cases, some instance variables are holding secrets such as password or private keys, and the default inspect behavior can cause
these secrets to be leaked in logs among other places.
You can of course define your own `inspect` implementation for any object, but it's not as simple as it may seems because you need to handle circular references, otherwise you can end up with a `SystemStackError`.
Also, it's more minor, but since Ruby 2.7, you can no longer access an object's address, so you can't implement an `inspect` method that is consistent with `Object#inspect`
>>From my experience, user defined implementations of `#inspect` are very rare, and I think the above is in part responsible.
## Feature
I think it would be useful if the default `Object#inspect` implementation accepted a list of instance variables to display, so that you could very easily hide internal state, either because it's too verbose, or because it is secret:
```ruby
require 'logger'
logger = Logger.new(STDOUT)
class DatabaseConfig
def initialize(host, user, password)
@host = host
@user = user
@password = password
end
def inspect = super(instance_variables: [:@host, :@user])
end
env = {db_config: DatabaseConfig.new("localhost", "root", "hunter2")}
logger.info("something happened, env: #{env}")
```
```
INFO -- : something happened, env: {db_config: #<DatabaseConfig:0x00000001002b3a08 @host="localhost", @user="root">}
```
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/