1

I'm reproducing a bug in my Rails console. I'm interested in what some methods return, but some of them turn out to be private, so in my console I have to write:

> my_object.my_method
NoMethodError (private method `my_method' called for #<MyClass:0x0123456789ABCDEF>)
> my_object.send(:my_method)

This gets a bit tedious after a while, especially since it's not obvious which are private without drilling through to the class they're defined in.

Is there any way I could temporarily make all methods public? I don't intend to use it in production, just temporarily in my local console while I'm debugging.

UPDATE: when I say “all methods”, I don’t just mean the ones on my_object. I mean literally all methods on every object.

Simon
  • 25,468
  • 44
  • 152
  • 266

2 Answers2

6

To make all methods public, this should work:

ObjectSpace.each_object(Module) do |m|
  m.send(:public, *m.private_instance_methods(false))
end

ObjectSpace.each_object traverses all modules (that includes classes and singleton classes) and makes their (own) private_instance_methods public.


To just make a single object public, you could use:

my_object.singleton_class.send(:public, *my_object.private_methods)

By changing the singleton class, only the my_object instance is affected.

Note that by default, private_methods returns inherited methods too, including many from Kernel. You might want to pass false to just include the object's own private methods.

Stefan
  • 109,145
  • 14
  • 143
  • 218
  • Thanks! I’m afraid my question was ambiguous. When I said “all methods”, I didn’t mean just the ones on `my_object`. I meant _all methods_. – Simon Nov 17 '20 at 18:59
0

Something like

my_object.class.private_instance_methods.each { |m| my_object.class.send :public, m }

might help you shoot a leg, I guess. :) (but the answer above is way better)

Konstantin Strukov
  • 2,899
  • 1
  • 10
  • 14