Issue #8520 has been updated by p8 (Petrik de Heus).
There is an open issue in Rails to limit `ActiveRecord::Base#inspect` for performance
reasons.
https://github.com/rails/rails/issues/49707
Calling `to_s` on a `Hash` will call `inspect` on its contents.
`ActiveRecord::Base#inspect` prints all the records attributes. It loops through all
attributes and filters sensitive ones.
So calling `to_s` on a `Hash` with a lot of ActiveRecord instances/attributes can result
in performance issues, as it filters all attributes.
Of course this issue can be fixed in Rails by changing `ActiveRecord::Base#inspect`, or
not calling to `to_s` on a large `Hash`.
But it might not be obvious to everyone that `Hash#to_s` is an alias to `Hash#inspect`, as
a lot of objects have different behaviour for `to_s` and `inspect`.
----------------------------------------
Feature #8520: Distinct to_s methods for Array, Hash...
https://bugs.ruby-lang.org/issues/8520#change-105092
* Author: LFDM (Gernot Höflechner)
* Status: Feedback
* Priority: Normal
* Assignee: matz (Yukihiro Matsumoto)
----------------------------------------
I apologize if something like this has already been proposed in the past, if it was, I
can't find it at the moment.
Ruby 2.0 rightfully changed to behaviour of inspect (not delegating to to_s anymore), as
inspect was effectively disabled when you had custom to_s methods implemented.
However I think that a mix of the old and the new would combine the best of both worlds.
Array or Hash to_s methods should not delegate to inspect, but instead reflect the old
behavior and call to_s to all members of a given collection.
Use Case:
I am currently designing a fairly large application that constructs very complex objects.
For debugging reasons those objects have to_s methods implemented to read terminal output
in a digestible format.
In constructing these to_s methods it was very convenient to string-interpolate
collections of such objects.
A quick example:
class A
def initialize
@a = "Large example text"
end
def to_s
# abbreviated form
@a[0]
end
end
arr = []
5.times { arr << A.new }
arr << arr.clone
puts "#{arr}"
Ruby 1.9.3 output: [L, L, L, L, L, [L, L, L, L, L]]
Ruby 2.0.0.output: [#<A:0x00000001f52c50 @a="Large example text">,
#<A:0x00000001f52c00 @a="Large example text">, #<A:0x00000001f52bb0 ...
and much more
I deliberately nested the example - as it obstructs the use of a simple join (arr * "
" => L L L L L L L L L L), which cannot reflect the array's nesting.
Printing a hash would be even more difficult - and with more nesting this becomes an
immense task.
Of course someone could just adjust the to_s method, but the elegance gets lost, logging
something like this would quickly lead to not so pretty code:
"The array looked like: #{arr}"
So I'd say distinct to_s methods, that call to_s recursively instead of delegating to
inspect. Basically leaving inspect at its correct 2.0 behavior and reverting to_s (and
thus #{}) back to its 1.9 behaviour.
Let's hope I am not overlooking something here.
What do you think?
Thanks for your feedback in advance,
GH
--
https://bugs.ruby-lang.org/